这段时间在对公司的打包构建速度和app.js文件大小进行优化。使用到了webpack的DllPlugin和DllReferencePlugin。今天就来简单讲讲它们的使用。
其实对于这两个插件网上已经有很多各种各样的文章了。不过笔者认为,那些文章都写得很棒,但是对于部分需要注意的地方都没有说明。这里笔者就根据自己的理解讲讲个人的理解。如果有什么不对的地方希望能有人指出,小弟在此先谢过了。
DllPlugin
首先我们来讲讲DLLPlugin这个插件吧。这个插件的作用是创建dll文件和manifest文件。dll文件就是就是我们需要引入的文件,manifest文件是引导webpack引入到当前项目的文件。好吧,直接贴代码:
webpack.dll.conf.js
var path = require('path')
var webpack = require('webpack')
var CleanWebpackPlugin = require('clean-webpack-plugin')
var config = require('../config')
var __root = xxx // 这里是你的根路径
// 这里是静态资源路径,如果使用vue-cli的,就是根目录下的static目录;
// 如果使用@vue/cli的就是根目录下的public目录。使用其他的脚手架需要根据具体情况考虑。
var static = xxx
module.exports = {
context: __root, // 这里配置的context就是后面dll的context
entry: {
'core': ['vue', 'vue-router', 'vuex'],
'asset': ['axios', 'fastclick']
},
output: {
path: path.resolve(static, 'lib'),
filename: '[name]-[chunkhash:7].dll.js',
library: 'lib_[name]',
// *** 这里不要添加libraryTarget,否则webpack打包时会出错。
// (提示是__WEBPACK__EXTERNAL__MODULE__xxx未定义) ***
// libraryTarget: 'umd'
},
resolve: {
modules: [path.resolve(__root, 'node_modules')],
extensions: ['.js', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
// 这里没有写loaders,如果有需要可以自行添加loaders
plugins: [
// *** 这里很关键 ***
new webpack.DllPlugin({ // 因为上面写了context,所以这里可以不指定context
// 这里manifest的名字必须要有变量,因为类似上面的core和asset会分别创建一个manifest,
// 如果名称相同,manifest会生成不规范的json,在引用时会报错。
path: path.resolve(__root, 'static/manifest/[name].manifest.json'),
name: 'lib_[name]' // *** 这里的名字必须与output.library一致 ***
}),
// 这个是用来稳定hash值,防止出现webpack的hash出现莫名的变化
new webpack.HashedModuleIdsPlugin(),
new webpack.NamedChunksPlugin()
... 其他插件
]
}
上面就是webpack.dll.conf.js的主要配置。执行之后会在static文件夹(在vue-cli生成的项目中用于存放不需要webpack构建的静态文件【@vue/cli中的目录名为Public】)下生成两个文件夹(lib文件夹和mainfest文件夹)。其中lib下的文件为我们已经打包好的组件库,mainfest下的文件在引入项目时有用(是一个JSON文件)。
DllReferencePlugin
webpack.conf.js
var path = require('path')
// 获取dll文件的manifest
function getDllManifest () {
var plugins = []
Object.keys({
'core': ['vue', 'vue-router', 'vuex'],
'asset': ['axios', 'fastclick']
}).forEach((name) => {
plugins.push(
new webpack.DllReferencePlugin({
context: __root, // 这里的context必须与DllPlugin中的context保持一致
manifest: path.resolve(__root, 'static/manifest/[name].manifest.json').replace(/\[name\]/gi, name)
})
)
})
return plugins
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: path.resolve(__dirname, '..')
filename: 'js/[name]js'
},
... 其他代码
plugins: [
// *** 所以这里可能会引入多个DllReferencePlugin,具体要看有几个manifest文件了。***
...getDllManifest(),
new HtmlWebpackPlugin({
filename: utils.assetsPath('page/retail.html'),
template: path.join(config.dev.page, 'retail.html'),
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// dll文件需要插件将其引入到html文件中,以方便后续使用
new HTMLWebpackIncludeAssetsPlugin({
append: false,
publicPath: config.build.assetsPublicPath,
assets: [{
path: config.build.assetsSubDirectory,
glob: '**/*.js',
globPath: config.dll.static
}],
}),
// 将dll文件拷贝到你的dist目录下
new CopyWebpackPlugin([
{
// 这里是dll文件当前所在的文件目录
from: static,
// 这里是生产环境的资源地址
to: config.build.assetsSubDirectory,
// 过滤static中的部分文件
ignore: ['.*', 'manifest/*']
}
])
]
}
getDllManifest方法是将打包好的库引入到项目中(就是在html中生成script标签的方式引入,它会在app.js之前生成,保证代码执行顺序的正确性),并保证构建工具不会再次对它进行打包。以上就是生成和引用dll文件的配置。
注:
-
output.library
必须与DllPlugin
配置中的name
字段保持统一。 - 不要使用
libraryTarget
,否则在运行时会报__WEBPACK__EXTERNAL__MODULE__xxx is not defined
错误。 -
DllPlugin
的context
和DllReferencePlugin
的context
要保持一致。 -
manifest
的名字最好是可配置的,这样方便生成多个dll文件。 - 如果有多个dll文件,需要添加多个DllReferencePlugin插件去分别处理。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。