基于webpack自身配置的优化,不涉及到happypack和DLL.
总述
webpack自身是单进程的。优化的总思路是,时间上,小范围,扫描次数少;空间上,能分离即分离,能不打包不打包,在http请求数与文件大小之间找到平衡。
1.entry
根据指定目录下动态生成entry对象,可根据不同场景区分entry中的数量。间接提高开发效率。
或者遍历文件夹,生成entry对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| let srcDir = path.resolve(process.cwd(), 'static/\$dev') let componentsDir = path.resolve(process.cwd(), 'static/\$dev/components') let entries = (() => { let entryFiles = (process.env.NODE_ENV === 'production') ? glob.sync(srcDir+"/+(index|service|tryout|app|user|stat|knowledge|doc|plan|tech|example|semservice|semutterance)/*.js") : glob.sync(srcDir+"/+(index|semservice|semutterance|knowledge|app)/*.js") let map = {} entryFiles.forEach(function(filepath){ let filename = filepath.substring(filepath.lastIndexOf('\/') + 1,filepath.lastIndexOf(".")) map[filename] = filepath; }); return map }())
|
2.resolve
modules默认只包括node_modules,如果需要添加其他的目录,需要保证node_modules在最后一位。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| resolve:{ modules: [path.resolve(__dirname, "src"), "node_modules"], extensions: ['.js', '.vue'], alias:{ echarts:"components/echarts.min.js", citySelector:"components/citySelector.js" } }, import echarts from 'echarts';
|
3.module中的rules
总的来说就是,尽量添加include, exclude,限定范围。
在rules进行test时,尽量精准匹配,比如如果没有jsx的文件,只有js的,test就可以写为/.js$/,而不是/.jsx?$/。(具体正则匹配的效率上,没有实际验证过。。)
其中babel, babel对文件的编译时间是比较久的,里面东西比较多,这里简单说几点。
配置中可以开启cache,这样在文件没有修改的时候,babel不会重新编译,以节约时间。
另一个是,babel-pollyfill
和transform-runtime
。
1 2 3 4 5 6
| { test: /\.js$/, loader: 'babel-loader?cacheDirectory', include: [path.resolve(__dirname, "src")], exclude: [path.resolve(__dirname, "src", "assets"), /node_modules/] }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| .babelrc { "presets": [ [ "es2015", { // 对modules语法不做转换,defaults to 'commonjs' "modules": false }], // 0 -> n, 0打包后的代码量最大。 "stage-0" ], // 动态对babel不能转换的新的API进行‘填补’ "plugins": ["transform-runtime"], "comments": false }
|
4.module中的noParse
1 2 3 4 5 6 7 8
| module{ noParse:['jquery', 'lodash'], rules: [ .... ] }
|
5.只在production环境下的,tree-shaking
实际验证现阶段(2017.7.27)tree-shaking之后,文件大小变化并不明显。主要受写法限制。尤其是引用大量第三方非ES6写法的库,其实作用不是很大。如果是从头自己写,在遵循ES6标准的基础上,控制性更好些。
同时uglify本身时间还比较长。用时间换空间的性价比不高。
因为tree-shaking必须配置一些压缩插件才能实现,默认是使用webpack-uglifyJS,但是由于是单进程的,处理比较慢。可选用webpack-parallel-uglify-plugin,多核处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| new UglifyJsparallelPlugin({ cacheDir: '.cache/', workerCount: os.cpus().length, uglifyJS: { // 可以用uglifyJS自身的配置 // 这里用于支持低版本IE supper_ie8: true, compress: { screw_ie8: false, properties: false, warnings: false }, output: { screw_ie8: false, beautify: true, quote_keys: true }, mangle: { screw_ie8: false }, sourceMap: false } })
|
6. 只在dev环境下
module.exports.devtool = '#cheap-module-eval-source-map';
7. 编译成es3
关于在IE低版本下运行,这里会遇到一些坑,另开一篇具体说说。
1
| const es3ifyPlugin = require('es3ify-webpack-plugin');
|
好了,做完上述优化,你会发现时间上变化并不明显。。。其实最主要的还是需要DLL,拆分,分步。
webpack.optimize.CommonsChunkPlugin
1 2 3 4 5 6 7 8
| entry中, vendor: ["vue", "vue-router", "axios"] new CommonsChunkPlugin({ name: 'vendor', filename: "vendor.js" })
|
其他一些常用配置
package.json
npm run build
1 2 3 4
| -- -- -- -- -- ... -- , ...- -- --- -- -- ,
|
查看打包后的文件大小
http://alexkuz.github.io/webpack-chart/
webpack –json –profile > stats.json
webpack-dev-server
与webpack -w 的区别
webpack -w 增量打包,在界面不会有任何体现,需要手动刷新。
webpack-dev-server,基于express的8080 Node服务器。可以设置代理等等。
具有HMR(热替换), LiveReload(自动刷新整个页面)。
实时编译,在内存中的。比webpack -w更快。
打包的静态资源路径相对于publicPath,如果不设置,相对于当前目录下。publicPath的优先级高于content-base的
这里面有个content-base, 还没弄清楚干啥的??。。
content-base是webpack-dev-server的HTTP服务启动后的根目录。最直接的就是如何访问到那个index.html的途径,与其物理存放位置的关系。