这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战
dll的作用
dll的作用是将项目中一些不常改变的依赖单独打包,DllReferencePlugin通过DllPlugin生成的manifest.json文件去引用对应的依赖。
优点
- 一旦生成dll文件,只要依赖不变,dll文件就不会改变
- dll中的依赖包只需要在文件生成的时候进行一次编译打包,以后的构建过程就可以跳过这些依赖,加快构建过程
缺点
- 需要增加一份生成dll文件的webpack配置,并且要修改原来的配置项去引入dll文件
- 需要多余的一次webpack构建,打破原先的项目构建流程
- 在dll中的依赖有版本改变的时候,需要重新生成dll文件
总结:
dll的功能就是对代码分割的一种高级应用,将项目中很少变动的依赖先配置出来,提前打包在一个文件中,然后以script标签的方式注入到index.html文件中,接着在build配置中引入打包好的dll配置,这样build执行时会跳过dll中已经打包的模块,从而加快了build的打包时间
实操:
1:首先,我们需要为dll单独写一个配置文件,以vue-cli为例,我们在build中新建一个名为webpack.dll.conf.js文件
var path = require("path");
var webpack = require("webpack");
module.exports = {
// 你想要打包的模块的数组
entry: {
vendor: ['vue', 'lodash', 'vuex', 'axios', 'vue-router', 'element-ui']
},
output: {
path: path.join(__dirname, './static/js'), // 打包后文件输出的位置
filename: '[name].dll.js',
library: '[name]_library'
// vendor.dll.js中暴露出的全局变量名。
// 主要是给DllPlugin中的name使用,
// 故这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, '.', '[name]-manifest.json'),
name: '[name]_library',
context: __dirname
}),
// 压缩打包的文件,与该文章主线无关
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]
};
重点:这里引入的Dllplugin插件,该插件将生成一个manifest.json文件,该文件供webpack.config.js中加入的DllReferencePlugin使用,使我们所编写的源文件能正确地访问到我们所需要的静态资源(运行时依赖包)。
-
path:manifest.json生成的文件夹及名字,该项目让它生成在了根目录下。
-
name:和output. library保持一致即可。
-
context:选填,manifest文件中请求的上下文,默认为该webpack文件上下文。 (!!!我在学习这个插件时一直没有成功的坑点之一!!,这个上下文必须必须同webpack.config.js中DllReferencePlugin插件的context所指向的上下文保持一致!!)
编写该webpack配置之后,我们就可以预打包资源文件了!!
// package.json文件
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress",
"dll": "webpack --config ./webpack.dll.config.js"
},
完成打包后就可以看见生成的vendor.dll.js文件了,除此之外根目录中还生成了vendor-manifest.json
现在我们已经不再需要将使用的那些包同源文件一起打包了,但是这也需要在源文件的webpack中配置DllReferencePlugin使用vendor-manifest.json来引用这个dll。
step 4:打包源文件
这一步我们只需要改写vue-cli为我们生成好的webpack.config.js即可:
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
// ...(省略未复制,并不是删除了module里的东西)
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
devServer: {
historyApiFallback: true,
noInfo: true
},
performance: {
hints: false
},
devtool: '#eval-source-map',
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./vendor-manifest.json')
})
]
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}
该文件里主要是添加了plugins配置:
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./vendor-manifest.json')
})
]
- context:与Dllplugin里的context所指向的上下文保持一致,这里都是指向了根目录。
- manifest:引入Dllplugin所生成的的manifest。
你以为完了? 其实还没有。
我们需要手动在根目录的index.html里引入所生成的dll库
<html lang="en">
<head>
<meta charset="utf-8">
<title>dll-test</title>
</head>
<body>
<div id="app"></div>
<script src="./static/js/vendor.dll.js"></script>
<script src="/dist/build.js"></script>
</body>
</html>
这里也很讲究,也是我之前失败的原因之一!!我之前直接把<script src="./static/js/vendor.dll.js"></script>写到了<script src="/dist/build.js"></script>的后面,导致一直报错!其实这里稍微动动脑筋就能明白,我们在main.js中引入的各种包,而main.js最终被打包为了build.js,那么我们肯定要先把包引进来才能正确使用build.js啊!所以vendor.dll.js必须放在build.js之前引入。
激动人心的时刻到来了!!我们只需要npm run dev就可以了!