Webpack+React+多语言(一) 基础配置

已经看过这一节的朋友,可以看Webpack+React+多语言(二) 插件配置+多语言
github地址:webpack-react-language
关键字:react 多语言 国际版 React-intl

移动端网站需要重构,当前的想法是使用webpack+react来重构移动端,当然,是需要支持多语言的。

  • 1.创建一个项目:webpack-react-language

这个项目名字有点长,我主要是为了与本地其他的项目区别开来
目录结构

|- build
    |-- index.html
    |-- bundle.js(该文件是webpack打包后生成的)
|- app
    |-- components
        |--- Dialog.jsx
    |-- main.js
|- package.json(第二步生成)
|- webpack.config.js(第四步生成)
  • 2.创建package.json
npm init
  • 3.安装webpack
//全局安装webpack,优点是打包时可以直接输webpack命令
npm install -g webpack
//在本项目中安装webpack,--save-dev的意思是将依赖写入项目的package.json文件
npm install --save-dev webpack
  • 4.创建webpack.config.js配置文件
module.exports = { 
    entry: __dirname + "/app/main.js",//唯一入口文件,就像Java中的main方法 
    output: {//输出目录 
        path: __dirname + "/build",//打包后的js文件存放的地方 
        filename: "bundle.js"//打包后的js文件名 
    }
};

运行webpack,webpack非全局安装需输入node_modules/.bin/webpack

webpack打包成功.png

看到以上提示说明打包成功了,可以看到build目录下的bundle.js里多了很多自动生成的代码,但预览index.html却什么都没有看到,这是因为还没有往页面中写入内容。

  • 5.更方便地执行打包命令

执行类似于node_modules/.bin/webpack这样的命令其实是比较烦人且容易出错的,不过值得庆幸的是npm可以引导任务执行,对其进行配置后可以使用简单的npm start命令来代替这些繁琐的命令。在package.json中对npm的脚本部分进行相关设置即可,设置方法如下。
打开package.json,找到script代码块,更改为:

"scripts": { 
    "build": "webpack"
    或者
    "start":"webpack"
}

但是start是一个特殊的脚本名称,如果脚本名称不是start,则需要npm run (script name),如npm run build,但是start可以直接执行npm start

  • 6.使用Source Maps,使调试更容易
devtool选项 配置结果
source-map 在一个单独的文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包文件的构建速度
cheap-module-source-map 在一个单独的文件中生成一个不带列映射的map,不带列映射提高项目构建速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便
eval-source-map 使用eval打包源文件模块,在同一个文件中生成干净的完整的source map。这个选项可以在不影响构建速度的前提下生成完整的sourcemap,但是对打包后输出的JS文件的执行具有性能和安全的隐患。不过在开发阶段这是一个非常好的选项,但是在生产阶段一定不要用这个选项
cheap-module-eval-source-map 这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射,和eval-source-map选项具有相似的缺点

正如上表所述,上述选项由上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的构建速度的后果就是对打包后的文件的的执行有一定影响。

在学习阶段以及在小到中性的项目上,eval-source-map是一个很好的选项,不过记得只在开发阶段使用它,继续上面的例子,进行如下配置

/webpack.config.js
module.exports = { 
    devtool: 'eval-source-map',//生成Source Maps,这里选择eval-source-map 
    entry: __dirname + '/app/main.js',//唯一入口文件,__dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录 
    output: {//输出目录 
        path: __dirname + '/build',//打包后的js文件存放的地方 
        filename: 'bundle.js'//打包后输出的js的文件名 
    }
};
  • 7.安装React、Babel
npm install react --save-dev
npm install react-dom --save-dev
npm install babel-core --save-dev
npm install babel-loader --save-dev
npm install babel-preset-es2015 --save-dev
npm install babel-preset-react --save-dev
基本插件安装成功之后的package.json.png

在webpack.config.js中

/webpack.config.js
module.exports = { 
    devtool: 'eval-source-map',//生成Source Maps,这里选择eval-source-map 
    entry: __dirname + '/app/main.js',//唯一入口文件,__dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录 
    output: {//输出目录 
        path: __dirname + '/build',//打包后的js文件存放的地方 
        filename: 'bundle.js'//打包后输出的js的文件名 
    },
    module: {    //loaders加载器    
        loaders: [{            
            test: /\.(js|jsx)$/,//一个匹配loaders所处理的文件的拓展名的正则表达式,这里用来匹配js和jsx文件(必须)            
            exclude: /node_modules/,//屏蔽不需要处理的文件(文件夹)(可选)            
            loader: 'babel-loader'//loader的名称(必须) 原来可以简写成babel,现在会提示报错,需要写全babel-loader,后续其他的loader也是一样的处理
        }]
    }
};

在项目根目录下新建.babelrc文件,没错你没看错,就是只有后缀名的文件,添加如下代码:

//.babelrc
{ 
    "presets": [ 
        "react",
        "es2015" 
    ]
}
  • 8.编写页面文件,为后续测试功能做准备

app/main.js

import React from 'react';
import ReactDom from 'react-dom';
import Dialog from './components/dialog.jsx';
ReactDom.render(    
    <Dialog />,    
    document.getElementById('content')
);

app/components/dialog.jsx

import React from 'react';
class Dialog extends React.Component {    
    render() {        
        return (            
            <div>Hello World!</div>        
        )    
    }
}
//导出组件
export default Dialog;

build/index.html

<!DOCTYPE html>
<html lang="en">
<head>    
    <meta charset="UTF-8">    
    <title>Title</title>
</head>
<body>    
    <div id="content"></div>    
    <script src="bundle.js"></script>
</body>
</html>

我使用的编辑器是webstorm,上述步骤完成之后,执行npm start,打包成功后,运行index.html,可以看到页面上

成功运行.png

  • 9.安装并启用webpack-dev-server

执行到这一步,基本的运作是可以了,但是每次修改文件之后,都需要重新打包,再运行,才可以看到新的内容,如何能忍受这么low的执行过程呢?

我们可以使用webpack-dev-server来搭建本地开发服务器,webpack-dev-server允许我们可以把本地项目跑在像nginx那样的web服务器上,修改代码后,立即可以看到变化;所见即所得,大大增加开发效率。

安装webpack-dev-server

npm install webpack-dev-server -g
npm install webpack-dev-server --save-dev

更改packaje.json中的代码块

"scripts": { 
    "start": "webpack", 
    "dev": "webpack-dev-server --devtool eval --progress --colors --content-base build"
}

ps:dev里各属性值的意思是:

  • webpack-dev-server: 在 localhost:8080 建立一个 Web 服务器
  • --devtool eval:为你的代码创建源地址。当有任何报错的时候可以让你更加精确地定位到文件和行号
  • --progress: 显示合并代码进度
  • --colors: 在命令行中显示颜色
  • --content-base build:指向设置的输出目录

在webpack.config.js中配置webpack-dev-server,在这里需要修改下entry的路径,给它加一个webpack/hot/dev-server,这里会用到Hot Module Replacement(热替换)插件,所以需要增加这个前缀,后文会提到,代码如下:

//webpack.config.js
module.exports = { 
    devtool: 'eval-source-map',//生成Source Maps,这里选择eval-source-map 
    entry: ['webpack/hot/dev-server', __dirname + '/app/main.js'],//唯一入口文件,__dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录 
    output: {//输出目录 
        path: __dirname + '/build',//打包后的js文件存放的地方 
        filename: 'bundle.js'//打包后输出的js的文件名 
    }, 
    module: { //loaders加载器 
        loaders: [ { 
            test: /\.(js|jsx)$/,//一个匹配loaders所处理的文件的拓展名的正则表达式,这里用来匹配js和jsx文件(必须) 
            exclude: /node_modules/,//屏蔽不需要处理的文件(文件夹)(可选) 
            loader: 'babel'//loader的名称(必须) 
        } ] 
    }, 
    //webpack-dev-server配置 
    devServer: { 
        contentBase: './build',//默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到"build"目录) 
        colors: true,//在cmd终端中输出彩色日志 
        historyApiFallback: true,//在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html 
        inline: true,//设置为true,当源文件改变时会自动刷新页面 
        port: 8080,//设置默认监听端口,如果省略,默认为"8080" 
        process: true,//显示合并代码进度 
    }
};

在浏览器中打开http://localhost:8080/,如果页面上是空白的,没有内容,按F12打开控制台,可以清除地看到错误提示:Uncaught Error: [HMR] Hot Module Replacement is disabled
现在我们来安装和配置这个Hot Module Replacement。

新版本的webpack(当前我使用的是webpack3.0),这样配置会有问题。
如果用的不是webpack3,可以忽略下面这部分,直接看#10


新版webpack沿用上面的配置文件报错

建议
1.webpack3的朋友,按下面的代码配置,或者将webpack的版本退回我图上的版本,进行操作。
2.推荐先看第十步的内容,可以帮助大家了解下面代码中的HotModuleReplacementPlugin

webpack3 配置
//webpack-dev-server配置 
    plugins: [
      new webpack.HotModuleReplacementPlugin({
          contentBase: './build',//默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到"build"目录) 
          colors: true,//在cmd终端中输出彩色日志 
          historyApiFallback: true,//在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html 
          inline: true,//设置为true,当源文件改变时会自动刷新页面 
          port: 8080,//设置默认监听端口,如果省略,默认为"8080" 
          process: true,//显示合并代码进度 
      })
    ]
  • 10.Hot Module Replacement

Hot Module Replacement(HMR)是webpack里很有用的一个插件,它允许你在修改组件代码后,自动刷新实时预览修改后的效果。
在webpack中实现HMR也很简单,只需要做两项配置

1.在webpack配置文件中添加HMR插件;
2.在Webpack Dev Server中添加“hot”参数;

不过配置完这些后,JS模块其实还是不能自动热加载的,还需要在你的JS模块中执行一个Webpack提供的API才能实现热加载,虽然这个API不难使用,但是如果是React模块,使用我们已经熟悉的Babel可以更方便的实现功能热加载。
整理下我们的思路,具体实现方法如下

  • Babel和webpack是独立的工具
  • 二者可以一起工作
  • 二者都可以通过插件拓展功能
  • HMR是一个webpack插件,它让你能浏览器中实时观察模块修改后的效果,但是如果你想让它工作,需要对模块进行额外的配额;
  • Babel有一个叫做react-transform-hrm的插件,可以在不对React模块进行额外的配置的前提下让HMR正常工作;

在webpack.config.js中配置如下:

//webpack.config.js
var webpack = require('webpack')
module.exports = { 
    devtool: 'eval-source-map',//生成Source Maps,这里选择eval-source-map 
    entry: ['webpack/hot/dev-server', __dirname + '/app/main.js'],//唯一入口文件,__dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录 
    output: {//输出目录 
        path: __dirname + '/build',//打包后的js文件存放的地方 
        filename: 'bundle.js'//打包后输出的js的文件名 
    }, 
    module: { //loaders加载器 
        loaders: [ { 
            test: /\.(js|jsx)$/,//一个匹配loaders所处理的文件的拓展名的正则表达式,这里用来匹配js和jsx文件(必须) 
            exclude: /node_modules/,//屏蔽不需要处理的文件(文件夹)(可选) 
            loader: 'babel'//loader的名称(必须) 
        } ] 
    }, 
    plugins: [    
        new webpack.HotModuleReplacementPlugin()//热模块替换插件
    ],
    //webpack-dev-server配置 
    devServer: { 
        contentBase: './build',//默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到"build"目录) 
        colors: true,//在cmd终端中输出彩色日志 
        historyApiFallback: true,//在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html 
        inline: true,//设置为true,当源文件改变时会自动刷新页面 
        port: 8080,//设置默认监听端口,如果省略,默认为"8080" 
        process: true,//显示合并代码进度 
    }
};

现在可以正常工作了,运行npm run dev,待命令行提示webpack: bundle is now VALID后,在浏览器中输入http://localhost:8080,可以看到,正常显示Hello World
如果觉得这样不放心,让我们进行如下额外配置

安装react-transform-hmr,在不对React模块进行额外的配置的前提下让HMR正常工作

npm install --save-dev babel-plugin-react-transform react-transform-hmr

在.babelrc文件里配置babel,注意这里有一堆括号,别写错了

//.babelrc
{ 
    "presets": [ 
        "react", 
        "es2015" 
    ], 
    "env": { 
        "development": { 
            "plugins": [ 
                [ 
                    "react-transform", { 
                        "transforms": [{ 
                                "transform": "react-transform-hmr", 
                                "imports": [ "react" ], 
                                "locals": [ "module" ] 
                        }] 
                    }
                ]
             ]
         } 
    }
}

至此,已经用webpack构建好了React项目的基础依赖,可以愉快的开发React程序了。

由于内容太多,于是将本文分成了多个部分,下一部分Webpack+React+多语言(二) 插件配置+多语言
github地址:webpack-react-language

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容

  • 构建一个小项目——FlyBird,学习webpack和react。(本文成文于2017/2/25) 从webpac...
    布蕾布蕾阅读 16,809评论 31 98
  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,147评论 7 35
  • 20170315更新 由于webpack已更新至2.0版本,许多配置项都已改变,所以可能本文有些项已经过时了 推荐...
    waka阅读 48,824评论 57 88
  • webpack 介绍 webpack 是什么 为什么引入新的打包工具 webpack 核心思想 webpack 安...
    yxsGert阅读 6,458评论 2 71
  • 谨以此文记录我刚到青岛的日子! 有人说,年轻就应该去拼搏,去在最美好的时间里做自己最想做的事情;也有人说,年...
    罡丨Brave阅读 157评论 0 0