静态依赖打包可以去掉很多无用的代码,减少文件体积。下面两张图片是楼主打包的两个文件,一个是使用tree shaking,一个是没使用的,都是为了引用一个方法encodeHTML。对比下生成文件的差异。
普通require模式引入
es6 tree shaking
可以看到tree shaking 只打包了我们需要的那个方法。楼主的demo支持打包多页面,地址在最下面,各位小伙伴可以自己clone下来看看。
看完了tree shaking的效果,下面我们来讨论以下几点
1. 如何开启webpack2的tree shaking功能
2. Webpack2配置注意事项
3. ES6模块编写注意事项
4. 一些配置优化点
如何开启webpack2的tree shaking功能
首先,只有es6模块才能使用webpack2做静态依赖解析。因为现在大部分浏览器还不支持es6模块语法,所以我们得下载babel,利用babel对代码进行编译。正常使用Babel 6来转换,一般设置presets: ['es2015']。但是这种方式使用的 transform-es2015-modules-commonjs插件意味着Babel会将es6模块通过commonJs模块转换输出,然后webpack 2就不能进行tree-shaking分析了。我的办法是修改babel的设置
//关键代码,只有去掉babel的cjs模块,才能做tree shaking打包
test: /\.js$/,
loader:'babel',
query: {
cacheDirectory: true,
plugins: [
'transform-es2015-template-literals',
'transform-es2015-literals',
'transform-es2015-function-name',
'transform-es2015-arrow-functions',
'transform-es2015-block-scoped-functions',
'transform-es2015-classes',
'transform-es2015-object-super',
'transform-es2015-shorthand-properties',
'transform-es2015-computed-properties',
'transform-es2015-for-of',
'transform-es2015-sticky-regex',
'transform-es2015-unicode-regex',
'check-es2015-constants',
'transform-es2015-spread',
'transform-es2015-parameters',
'transform-es2015-destructuring',
'transform-es2015-block-scoping',
'transform-es2015-typeof-symbol',
['transform-regenerator', {async: false, asyncGenerators: false}]
]
}
exclude: /node_modules/
Webpack2配置注意事项
Webpack2相对webpack1做了一些配置的更改,更改的配置比较多,这里只是简单的介绍下几个影响构建的部分
Resolve option
webpack1中,文件路径查找的resolve.root属性被删除了,取代的是resolve.module属性。
Plugins
//webpack.optimize.OccurenceOrderPlugin插件不再需要配置
//ExtractTextPlugin配置方式变更, ExtractTextPlugin需要更新到2.0版本。新老配置方式对比:
Webpack1 : ExtractTextPlugin.extract('css!postcss!sass')
Webpack2: ExtractTextPlugin.extract({
fallbackLoader: "style-loader",
loader: "css-loader?minimize"
})
//CommonsChunkPlugin配置方式变更
Webpack1:CommonsChunkPlugin('common/common','js/[name].js')
Webpack2:CommonsChunkPlugin({name:'commonFile',filename:'js/[name].[hash:8].js' })
HMR communication
在 Webpack 1 中,更新信号用的是Web Messaging API(postMessage)。而Webpack 2将使用一个标准的事件触发器来传递事件信号。这表示WebSocket必须内联到打包文件中。webpack-dev-server必须使用新版本
更多配置可以看楼主的demo和下文参考资料中的链接
ES6模块编写注意事项
Webpack2支持新的异步加载模块方法System.import。使用这个方法可以返回一个promise对象,模块加载失败可以被捕获,支持动态模块名,每个动态模块都会产生新的chunk文件。异步加载的文件,没必要分别导出模块的方法。
示例代码
function route(path, query) {
return System.import("./routes/" + path + "/route")
.then(route => new route.Route(query));
}
这会为每种可能的路径组合都创建一个对应的chunk。
非异步的模块,使用export关键字,导出函数和变量,在构建时,才可以分析依赖进行构建。
示例代码
export function encodeHTML(str) {
if (typeof str == 'string') {
var ar = ['&', '&', '<', '<', '>', '>', '"', '"'];
for (var i = 0; i < ar.length; i += 2) {
str = str.replace(new RegExp(ar[i], 'g'), ar[1 + i]);
}
return str;
}
return str;
}
export var a = ['hello world'];
//引用
import {encodeHTML} from 'util/string_es6'
一些配置优化点
UglifyJsPlugin配置output.max_line_len属性,指定压缩文件的单行最大长度,方便在线上代码出现js问题的时候可以快速定位到出错的代码位于哪一行。
webpack.DllPlugin打包不怎么改动的文件,提高构建速度。
babel打包默认会加上use strict,如果使用了argument.callee等js代码。会导致一些语法错误。可以使用插件babel-plugin-transform-remove-strict-mode或者用gulp全局替换下。
demo地址:https://github.com/xyc-cn/webpack2-demo/tree/master
参考资料
Babel use strict https://github.com/shanggqm/blog/issues/1
Webpack1 to webpack2 https://github.com/cssmagic/blog/issues/58
Webpack2 tree shaking http://www.2ality.com/2015/12/webpack-tree-shaking.html
Webpack2 demo https://github.com/phiphou/webpack-es6-demo