写在前面:
参考了许多资料,都差不多的,但是并不是很全,过程有点头疼
项目前提:
index.html文件(在主目录下的)
1、在build目录下新建:
文件webpack.dll.config.js
const path = require("path");
const webpack = require("webpack");
//读取package.json里的依赖,normalize.css除外,打包会报错
const package = require('../package.json');
let dependencies = Object.keys(package.dependencies) || [];
//如果使用了chrome的vue-devtool,那打包的时候把vue也排除掉,因为压缩过的vue是不能使用vue-devtool的
dependencies = dependencies.length > 0 ? dependencies.filter(item => item !== 'vue') : [];
module.exports = {
devtool: 'source-map',
entry: {
vendor: dependencies // "vendor"这个名字是自己定义的
},
output: {
path: path.join(__dirname, "../common/js"), // 输出的文件放在common/js中
filename: "[name].js", // 其中[name]就是entry中的vendor,因此filename就是vendor.js
library: "[name]" // vendor.js中暴露出的全局变量名
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, ".", "[name]-manifest.json"), // DllReferencePlugin使用该json文件来做映射依赖性。(这个文件会告诉我们的哪些文件已经提取打包好了)
name: "[name]", // 暴露出的dll的函数名;此处需要和 output.library 的值一致
context: __dirname
}),
new webpack.optimize.UglifyJsPlugin({ // 压缩
compress: {
warnings: false
}
})
]
};
DllPlugin是在一个额外的独立的 webpack 设置中创建一个只有 dll 的 bundle(dll-only-bundle)。 这个插件会生成一个名为 manifest.json
的文件,这个文件是用来让DllReferencePlugin映射到相关的依赖上去的。
2、在package.json的脚本中,添加如下脚本
"build:dll": "webpack --config build/webpack.dll.config.js"
3、运行npm run build:dll会生成两个文件:build文件夹下的vendor-manifest.json和common/js下的vendor.js
4、然后,在webpack.prod.config.js(生产环境)中添加以下代码:
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./vendor-manifest.json')
}),
DllReferencePlugin,是在 webpack 主配置文件中设置的, 这个插件把只有 dll 的 bundle(们)(dll-only-bundle(s)) 引用到需要的预编译的依赖。
此时输入命令npm run dev,会发现项目编译的时间缩短(特别是之前项目编译时间越久变化越明显)
我看到不同的资料里,这段代码被放在生产环境或者webpack主配置文件中了,因此,我尝试将这段代码放在webpack.base.config.js中。此时再次输入命令npm run dev编译,会发现项目编译的时间又缩短了
5、之后我们在打包项目的时候,发现报错:vendor.js is undefined
这是因为vendorjs没有被打包到目标文件内,并且没有添加到HtmlWebpackPlugin生成的html文件(的script脚本链接)
解决方式:
6、安装插件: "add-asset-html-webpack-plugin"
在安装之前需要注意对应的html-webpack-plugin的版本要在2.10.0以上:
运行下面语句安装:
npm install [email protected] --save-dev
注意:在这里有一个坑,要安装一个合适版本的插件,高版本的这个插件会报如下错误:
Cannot read property 'compilation' of undefined
笔者降低了版本才得以解决,现在最新的是3.1.3,降低来安装了2.1.2版本的
7、安装之后,在webpack.pro.config.js(生产环境)中添加如下代码:
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
module.exports = {
...
plugins: {
new AddAssetHtmlPlugin({
filepath: path.resolve(__dirname, '../common/js/vendor.js'),
outputPath: path.posix.join('', '../common/js'),
publicPath: '/common/js',
includeSourcemap: false
}),
}
}
在这里,笔者也碰到了一些坑:
filepath接收的是String或Glob类型,是dllPlugin打包生成js(即vendor.js)的绝对路径
outputpath是输出的路径,posix是为了兼容,跨平台,path.join拼接路径;(参考https://blog.csdn.net/wbiokr/article/details/73612207 学习node的path模块)
publicPath:接收的是String类型,官网解释:If set, will be used as the public path of the script or link tag.也就是说是用于脚本或者链接的公共路径,笔者这里原来是下面这样写的:
publicPath: path.join('', '/common/js'),
但是每一次打包之后,生成的目标index.html中的引用脚本的斜杠会被转义为反斜杠:
这样子很不好看,而且可能会带来潜在问题(具体啥问题还不清楚)
后面使用了字符串(本来接收的就是字符串,汗-_-||)
includeSourcemap应该被设置为false,设置为true时,在打包过程中,vendor.js文件会被添加上.map的后缀,导致报错说找不到vendor.js.map文件。
8、最后成功打包
参考资料:
https://www.jianshu.com/p/ec86c9e64560
https://blog.csdn.net/wxl1555/article/details/80196180
https://www.jianshu.com/p/862c56479456
推荐:Webpack 打包优化之体积篇
感觉能够帮助我们了解项目应该做哪些优化