引言
目前,几乎所有业务的开发构建都会用到 webpack 。的确,作为模块加载和打包神器,只需配置几个文件,加载各种 loader 就可以享受无痛流程化开发。但对于 webpack 这样一个复杂度较高的插件集合,它的整体流程及思想对我们来说还是很透明的。那么接下来我会带你了解 webpack 这样一个构建黑盒,首先来谈谈它的流程。
准备工作
1. webstorm 中配置 webpack-webstorm-debugger-script
在开始了解之前,必须要能对 webpack 整个流程进行 debug ,配置过程比较简单。
先将 webpack-webstorm-debugger-script 中的 webstorm-debugger.js
置于webpack.config.js
的同一目录下,搭建好你的脚手架后就可以直接 Debug 这个 webstorm-debugger.js 文件了。
2. webpack.config.js 配置
估计大家对 webpack.config.js 的配置也尝试过不少次了,这里就大致对这个配置文件进行个分析。
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 36 37 38 39 40 41 42 |
var path = require('path'); var node_modules = path.resolve(__dirname, 'node_modules'); var pathToReact = path.resolve(node_modules, 'react/dist/react.min.js'); module.exports = { // 入口文件,是模块构建的起点,同时每一个入口文件对应最后生成的一个 chunk。 entry: { bundle: [ 'webpack/hot/dev-server', 'webpack-dev-server/client?http://localhost:8080', path.resolve(__dirname, 'app/app.js') ] }, // 文件路径指向(可加快打包过程)。 resolve: { alias: { 'react': pathToReact } }, // 生成文件,是模块构建的终点,包括输出文件与输出路径。 output: { path: path.resolve(__dirname, 'build'), filename: '[name].js' }, // 这里配置了处理各模块的 loader ,包括 css 预处理 loader ,es6 编译 loader,图片处理 loader。 module: { loaders: [ { test: /\.js$/, loader: 'babel', query: { presets: ['es2015', 'react'] } } ], noParse: [pathToReact] }, // webpack 各插件对象,在 webpack 的事件流中执行对应的方法。 plugins: [ new webpack.HotModuleReplacementPlugin() ] }; |
除此之外再大致介绍下 webpack 的一些核心概念:
- loader:能转换各类资源,并处理成对应模块的加载器。loader 间可以串行使用。
- chunk:code splitting 后的产物,也就是按需加载的分块,装载了不同的 module。
对于 module 和 chunk 的关系可以参照 webpack 官方的这张图:
- plugin:webpack 的插件实体,这里以 UglifyJsPlugin 为例。
1234567891011121314151617function UglifyJsPlugin(options) {this.options = options;}module.exports = UglifyJsPlugin;UglifyJsPlugin.prototype.apply = function(compiler) {compiler.plugin("compilation", function(compilation) {compilation.plugin("build-module", function(module) {});compilation.plugin("optimize-chunk-assets", function(chunks, callback) {// Uglify 逻辑});compilation.plugin("normal-module-loader", function(context) {});});};
在 webpack 中你经常可以看到 compilation.plugin(‘xxx’, callback) ,你可以把它当作是一个事件的绑定,这些事件在打包时由 webpack 来触发。
3. 流程总览
在具体流程学习前,可以先通过这幅 webpack 整体流程图 了解一下大致流程(建议保存下来查看)。
shell 与 config 解析
每次在命令行输入 webpack 后,操作系统都会去调用 ./node_modules/.bin/webpack
这个 shell 脚本。这个脚本会去调用 ./node_modules/webpack/bin/webpack.js
并追加输入的参数,如 -p , -w 。(图中 webpack.js 是 webpack 的启动文件,而 $@ 是后缀参数)
在 webpack.js 这个文件中 webpack 通过 optimist 将用户配置的 webpack.config.js 和 shell 脚本传过来的参数整合成 options 对象传到了下一个流程的控制对象中。
1. optimist
和 commander 一样,optimist 实现了 node 命令行的解析,其 API 调用非常方便。