前些天 webpack2.2 发布了正式版。个人觉得 webpack2 带来的最大的变化莫过于新的官网了 https://webpack.js.org,新官网带来的新的文档比之前的要好太多了。而且早就想试试 Tree Shaking 了,所以趁此时间赶紧升级了一把。虽然已经发布了 2.2 的正式版,不过目前还需要通过 最新消息,官方已经把 beta 去掉了,现在直接安装 npm install webpack@beta
来安装,大家要注意哦~npm install webpack
就是最新 2.2.1 的版本了,如果要装老版本的话需要 npm install -g webpack@1
。另外官方给出了详细的webpack1升级到webpack2的迁移指南,也可以参考其对应的的中文翻译版。以下就按照我的认识给大家梳理一下 webpack2 的一些变化,详细的更新情况还请参考官方文档。
配置文件
新版 webpack.config.js
内的几个配置项发生了比较大的变化,如果你升级了之后什么都不修改的话默认会报错。
可以看到配置项的确有些不同,其中变化最大的是loader
的配置:
- 取消了
modules.preLoaders
,modules.loaders
,modules.afterLoaders
,统一变成了modules.rules
。 - 多个 loader 从之前的字符串链式拼接变成了
loader.use
数组形式。 - 所有的 loader 都默认必须补全
-loader
,不能使用简写形式。据作者说是因为有些新手会把简写名称误以为是 loader 名称而和其它模块搞混淆了所以默认移除了这个功能。 - loader 的参数配置只能写在
rule.options
内部不能写在外面,例如 sass-loader 的参数配置方式是在webpack.config.js
最外部增加的就不符合新版要求,使用的时候 webpack 会提示不合法参数的错误。
另外就是 module.resolve
的变化,resolve.root
, resolve.moduleDirectories
和 resolve.fallback
全部统一成了 resolve.modules
,感觉更好理解了,讲道理之前完全记不住这几个东西。。。另外 resolve.extensions
不需要自己写一个空字符串在那了,webpack 会自动解析无后缀的模块加载。
编译大小的速度
更新好配置文件后就可以愉快的运行了。和之前的对比了一下,总体来说,编译速度的确是有优化,但优化幅度并不大。编译体积上虽然有 Tree Shaking 加成,但是对于这种大项目来说优化幅度并不是非常明显。总体上来说性能的话你最好别对新版本抱有太大的期望,以下是 Firekylin 两个版本编译前后的对比:
webpack | v1(ms) | v2(ms) |
---|---|---|
开发环境 | 15416 | 11502 |
生产环境 | 35844 | 21279 |
新特性
撇开 webpack 尴尬的编译速度不说,我们来看看 v2 版本为我们带来了哪些新特性吧。
Promise 化
可以看到新版很多代码都 Promise 化了,首先是配置文件 Promise 化了。之前 webpack.config.js
返回的永远是一个配置对象,现在能支持返回一个函数,函数参数是命令行传入的一些自定义环境参数,函数执行返回一个 Promise 对象。变成函数后我们就可以在配置文件内根据环境参数自定义配置了,不用像以前一样通过不同的文件区分不同的环境。返回 Promise 的话有助于我们在配置文件中执行一些异步操作并返回结果。不过感觉这个需求比较小众,目前我都还没有需求需要在配置文件中执行异步。
另外一个 Promise 化的东西就是分块代码加载 Promise 化了,不管是 require.ensure
还是 AMD 的 require
甚至是 ES6 的动态 import
,返回的都是 Promise 的对象。所以对于一些不支持 Promise 的浏览器需要加载 Promise 的 Polyfill 库才行。ES6 的动态 import
在下面详细说说。
原生的 import
支持
旧版本只支持 AMD/CMD 和 CommonJS 等 require
加载模块,如果使用 ES6 语法的话需要使用 babel-loader
将其编译成 require
的版本才行。但是 import
加载最大的特点是它是编译时加载,在编译的时候我们就可以知道我们需要使用这个模块的哪些属性和方法,如果只是单纯的转换成 require
加载的话这些特性就都没了。好在 v2 版本已经原生支持了,Tree Shaking 通过静态分析只加载会被执行的代码也顺理成章的支持起来了。关于 Tree Shaking 更多的内容可以参考这篇文章:《webpack2 的 tree shaking 真的好用吗?》。TL;DR;总的观点基本上和我上面测试的结果一直,Tree Shaking 对代码函数式要求很高,对目前的代码来说优化程度寥寥。
原生 import
支持带来的另一个影响就是增加了新的异步分块代码加载方式。在老的版本中如果你想要分块加载一个模块基本写法如下:
require.ensure(['a'], function(require) {
var a = require('a');
a.dosomething();
}, 'chunkNameIfYouWant');
写法和 AMD require
类似采用回调后置了代码执行时间。webpack2 中原生支持的import
函数加载模块,并返回 Promise 对象:
import('a').then(function(a) {
a.dosomething();
});
//async/await 版
(async function() {
let a = await import('a');
a.dosomething();
})();
Promise 化后带来的好处就是更加直观且语义化,配合 async/await
语法书写后基本就可以等同于同步代码理解。而且 Promise 带有 resolve 和 reject 两种方法,我们可以非常方便的 catch 到模块加载失败的错误并作出对应操作。不过 require.ensure
是支持第三个参数自定义分块代码的分块名称的,目前 import()
加载还不支持这个功能,如果需要自定义分块名称的话还是只能使用 require.ensure
的方式。
另外就是默认 babel-loader
还是会处理 import
方法的,为了不让其转换 import
方法从而让 webpack2 能够读取到 import
,我们需要设置 babel-loader
:
{
test: /\.js$/,
loader: 'babel-loader',
options: {
presets: [ ['es2015', {module: false}] ]
}
}
后记
总的来看 webpack2 带来的更新都是大势,ES6 和 Promise 的引入让代码更贴近标准,配置项归类的更加合理,特别是文档比以前的真的是好用太多了。而且 webpack 的作者最近都有加大力度在中文社区的推广,https://webpack-china.org webpack 中文社区也在扩张中,推荐大家多多升级交流。
[…]升级到 webpack2 | 公子 | 2017-01-26[…]
这个功能真好。
功能不错
新特性还不错。
jwplayer用这个处理了js才注意到,不过压缩率很一般,好像主要用途不是这个?= =
@羽中 哈哈,是一个 JS/HTML/CSS 资源打包用的,也能用来做压缩。