Webpack

React已成为前端当下最热门的前端框架之一 , 其虚拟DOM和组件化开发让前端开发更富灵活性,而Webpack凭借它异步加载和可分离打包等优秀的特性,更为React的开发提供了便利。

Webpack

Webpack 是什么

webpack是一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理。能够像Node.js一样处理依赖关系,然后解析出模块之间的依赖,将代码打包.我们可以直接使用 require(XXX) 的形式来引入各模块,即使它们可能需要经过编译(比如JSX和sass),但我们无须在上面花费太多心思,因为 webpack 有着各种健全的加载器(loader)在默默处理这些事情。

Webpack 的优势

其优势主要可以归类为如下几个:

  1. webpack 是以 commonJS 的形式来书写脚本滴,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。
  2. 能被模块化的不仅仅是 JS 了,还包含图片和CSS。
  3. 开发便捷,能替代部分 grunt/gulp 的工作,比如打包、压缩混淆、图片转base64等。
  4. 扩展性强,插件机制完善,特别是支持 React 热插拔(见 react-hot-loader )的功能让人眼前一亮。

Webpack 的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var webpack = require('webpack');
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');

module.exports = {
//插件项
plugins: [commonsPlugin],
//页面入口文件配置
entry: {
index : './src/js/page/index.js'
},
//入口文件输出配置
output: {
path: 'dist/js/page',
filename: '[name].js'
},
module: {
//加载器配置
loaders: [
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.js$/, loader: 'jsx-loader?harmony' },
{ test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
]
},
//其它解决方案配置
resolve: {
root: 'E:/github/flux-example/src', //绝对路径
extensions: ['', '.js', '.json', '.scss'],
alias: {
AppStore : 'js/stores/AppStores.js',
ActionType : 'js/actions/ActionType.js',
AppAction : 'js/actions/AppAction.js'
}
}
};

这里对Webpack的打包行为做了配置,主要分为几个部分:

  1. entry:指定打包的入口文件,每有一个键值对,就是一个入口文件 output:配置打包结果,path定义了输出的文件夹,filename则定义了打包结果文件的名称
  2. resolve:定义了解析模块路径时的配置,常用的就是extensions,可以用来指定模块的后缀,这样在引入模块时就不需要写后缀了,会自动补全
  3. module:定义了对模块的处理逻辑,这里可以用loaders定义了一系列的加载器,以及一些正则。当需要加载的文件匹配test的正则时,就会调用后面的loader对文件进行处理,这正是webpack强大的原因。它告知 webpack 每一种文件都需要使用什么加载器来处理.比如这里定义了凡是 .js 结尾的文件都是用 babel-loader 做处理,而 .jsx 结尾的文件会先经过 jsx-loader 处理,然后经过 babel-loader 处理。当然这些loader也需要通过 npm install 安装
  4. plugins: 这里我们使用了一个 CommonsChunkPlugin 的插件,它用于提取多个入口文件的公共脚本部分,然后生成一个 common.js 来方便多页面之间进行复用。react-hot

运行webpack

  1. 直接执行webpack --display-error-details即可,后面的参数“–display-error-details”是推荐加上的,方便出错时能查阅更详尽的信息(比如 webpack 寻找模块的过程),从而更好定位到问题。
  2. 安装并启用webpack-dev-server:webpack-dev-server允许我们可以把本地项目跑在像nginx那样的web服务器上,更重要的是我们可以在package.json文件内定义scripts,同时修改webpack的配置文件来达到类似BrowserSync(即文件修改能被监听,并自动刷新浏览器)的效果!
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --devtool eval --progress --colors --content-base build"
    /*
    *webpack-dev-server: 在 localhost:8080 建立一个 Web 服务器
    *--devtool eval:为你的代码创建源地址。当有任何报错的时候可以让你更加精确地定位到文件和行号
    *--progress: 显示合并代码进度
    *--colors: 在命令行中显示颜色
    *--content-base build:指向设置的输出目录
    */

    }

在没引入webpack-dev-server之前,执行:npm run build项目就跑起来啦.有了webpack-dev-server之后,npm run dev你只要在浏览器打开这个地址:http://localhost:8080,webpack-dev-server会为你准备好一切,你只要敲一敲键盘,save一下,所见即所得。

生成Hash名称的script来防止缓存

经典问题,代码更新了,但是浏览器有缓存,到时候就傻了。 怎么解决,换名字呗。可以直接在后面加参数,也可以直接换掉文件名字。 webpack提供给了我们非常简单的方法,基于文件的md5,只要把

1
2
3
4
5
output: {
path: BUILD_PATH,
//只要再加上hash这个参数就可以了
filename: '[name].[hash].js'
},

运行完build以后,看看生成的文件,很完美~

1
2
3
4
5
index.html
<body>
<h3>Welcome to webpack</h3>
<script src="vendors.js"></script><script src="app.b6641abee64c999d95c1.js"></script>
</body>

分离app.js和第三方库(打包结果太大)

现在我们build出来的只有一个bundle.js 如果第三方库很多的话,会造成这个文件非常大,减慢加载速度,现在我们要把第三方库和我们app本身的代码分成两个文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//修改entry入口文件
entry: {
app: path.resolve(APP_PATH, 'index.js'),
//添加要打包在vendors里面的库
vendors: ['jquery', 'moment']
},
//添加CommonsChunkPlugin
plugins: [
//这个使用uglifyJs压缩你的js代码
new webpack.optimize.UglifyJsPlugin({minimize: true}),
//把入口文件里面的数组打包成verdors.js
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'),
new HtmlwebpackPlugin({
title: 'Hello World app'
})
]
//添加完毕 运行npm run build,在build文件夹中发现如下结构
//budle.js
//index.html
//vendors.js

React相关

  1. 推荐使用 npm install react 的形式来安装并引用 React 模块,而不是直接使用编译后的 react.js,这样最终编译出来的 React 部分的脚本会减少 10-20 kb左右的大小。
  2. react-hot-loader 是一款非常好用的 React 热插拔的加载插件,通过它可以实现修改-运行同步的效果,配合 webpack-dev-server 使用更佳!

参考: