Open cheungseol opened 7 years ago
通常使用 webpack 打包的项目,会使用 HtmlWebpackPlugin 在模板中自动插入 script 标签,引入打包文件(script 脚本引入的路径是 output 中的 publicPath)。
new HtmlWebpackPlugin({
title: 'test',
template: '!!raw-loader!' + '/template.html', // 模板文件路径
filename: './server/views/index.ejs', // 生成的文件路径,供 node serve
inject: 'body',
hash: false,
minify: {
removeComments: false,
collapseWhitespace: false,
},
}),
有时候,会将 dll 文件放在 cdn 上,并给 dll 包名以hash值区分。为了在 html 模板文件中自动引入 dll 包文件,需要 AddAssetHtmlPlugin。
webpack.config.js
new AddAssetHtmlPlugin({
includeSourcemap: false,
filepath: path.resolve(__dirname, 'server/static/js/lib.*.js'), // * 符号匹配 dll 哈希名称
}),
webpack 编译时提示 ”...dll.js.map not found“, 需要配置插件选项:includeSourcemap: false,
。
dll.config.js
module.exports = {
entry: {
lib: ['react', 'react-dom', 'react-router-dom', 'react-router-redux', 'react-router-config', 'react-redux'],
},
output: {
path: path.resolve(__dirname, 'server/public/js'),
filename: '[name].[hash:8].js', // 生成的 dll 文件以hash命名
library: '[name]',
},
plugins: [
new webpack.DllPlugin({
path: './manifest.json',
name: '[name]',
context: path.resolve(__dirname, 'client/'),
}),
],
cache: true,
};
参考
webpack 提供了一些 Plugins 来提升打包时的性能。
CommonsChunkPlugin
当 webpack 配置了多个入口文件时,如果这些文件都 require 了相同的模块,webpack 会为每个入口文件引入一份相同的模块,显然这样做,会使得相同模块变化时,所有引入的 entry 都需要一次 rebuild,造成了性能的浪费。
CommonsChunkPlugin 把相同的模块提取出来单独打包,从而减小 rebuild 时的性能消耗。
DLLPlugin 和 DllReferencePlugin
项目中常常会引入许多第三方 npm 包,尽管我们不会修改这些包,但是webpack 仍会要在每次 build 的过程中重复打包,消耗构建性能。
DLLPlugin 通过前置这些依赖包的构建,来提高真正的 build 和 rebuild 的构建效率。
例子:
比如我们的项目中使用了 react ,我们把 react 和 react-dom 打包成为 dll bundle。
DLLPlugin 需要一个单独的 webpack 配置文件:
用 webpack 运行 webpack.dll.config.js 文件后,就会在 dist 目录下生成 dll bundle 和对应的 manifest 文件
manifest 文件的格式大致如下,由包含的 module 和对应的 id 的键值对构成:
在项目的 webpack 配置文件(不是上面的 webpack.dll.config.js )中通过 DLLReferencePlugin 来使用刚才生成的 DLL Bundle。
执行 webpack,会在 dist 下生成 dll-user.bundle.js,约 700K,耗时 801ms:
打包出来的文件大小是 2.01K,耗时 70 ms,大大提高了 build 和 rebuild 的效率。
dll 和 external 的比较
像是 react 这种已经打好了生产包的使用 externals 很方便,但是也有很多 npm 包是没有提供的,这种情况下 DLLBundle 仍可以使用。
如果只是引入 npm 包一部分的功能,比如 require('react/lib/React') 或者 require('lodash/fp/extend') ,这种情况下 DLLBundle 仍可以使用。
如果只是引用了 react 这类的话,externals 因为配置简单所以也推荐使用。
dll 和 entry vendor 的比较
vendor配置本质目的是为了跨页面加载库不必重复。 webpack的资源入口通常是以entry为单元进行编译提取,那么当多entry共存的时候,CommonsChunkPlugin的作用就会发挥出来,对所有依赖的chunk进行公共部分的提取,但是在这里可能很多人会误认为抽取公共部分指的是能抽取某个代码片段,其实并非如此,它是以module为单位进行提取。
参考
Optimizing Webpack build times and improving caching with DLL bundles
https://juejin.im/entry/5769f8dc128fe10057d2f4ae
Webpack的dll功能
彻底解决Webpack打包性能问题
http://dev.dafan.info/detail/329716?p=34-14
用 webpack 实现持久化缓存