即便我们已经学会了webpack的基本配置,这并不代表我们使用webpack搭建的项目没有优化的空间,事实上,优化webpack项目是一门很深的学问。另一方面是,我们不必因为感到webpack本身很难,就不再对webpack项目考虑优化问题,而将之束之高阁,任何人都可以对webpack项目的一些常见方面进行优化,这似乎是比较简单和容易的。
现在,本文将要讨论是一个比较简单和实用的优化技巧,即利用dll来提升打包速度,并缩小打包文件的体积。
你可能感到困惑,dll是什么,这并不重要,你只需要知道在webpack中他是怎么工作的,而当你熟悉了整个流程之后,你自然就明白它为什么叫做“动态链接库(Dynamic Link Library)”
了。
就默认情况而言,第三方依赖和我们自己的js代码没什么不同,都会被打包到最终的出口文件中。像jquery这样的第三方库,动辄上万行代码,而且他们的内容相对固定,即便我们一分钟内打包了5次,jquery中的上万行代码每次都会被重新加载和打包。
你可能已经在想,像jquery和vue这些依赖是否可以抽取出来,单独打包呢?
答案当然是肯定的,这就是这篇文章的主题。一旦你这样做了,就会发现打包后的文件体积得到很大压缩,并且速度也提升了不少。这便是我们的webpack dll优化技术
。
先看我们优化之前的打包时长和体积:
dll优化之后:
可以看到时间缩短了1/3还多,而体积则只变成原来的零头了。当然,这仅仅是将vue和jquery进行dll处理后的情况,假设你的项目中的库特别多,那么优化效果将更明显。
在我们的项目中,webpack的默认配置文件是webpack.config.js,这自不用说。webpack从其中的entry开始构建,并最终进行输出,我们不妨将其称为默认通道
。
现在,我们可以开辟另外一个通道:
创建额外的配置文件webpack.config.lib.js,这条通道用于生成dll。
即dll通道
(当然这是我自己命的名,不要在意这些细节)。这样,我们打包需要两次,一次是对默认通道进行打包,只需如此即可:
npx webpack
另一次是对dll通道进行打包:
npx webpack --config webpack.config.vue.js
顺序是先对dll通道进行打包,再对默认通道进行打包
。上面的两条命令将在下面两步中分别执行,而现在只是告诉你这个事实。
现在我们需要对dll通道的配置文件webpack.config.lib.js进行补全,这和webpack.config.js中的配置方法是一样的:
const path = require("path");
const webpack = require("webpack");
module.exports = {
mode: "development",
entry: {
lib: ["vue", "jquery"]
},
output: {
filename: "_dll_[name].js",
path: path.resolve(__dirname, "dist"),
library: "_dll_[name]"
},
plugins: [
new webpack.DllPlugin({
name: "_dll_[name]",
path: path.resolve(__dirname, "dist", "manifest.json")
})
]
};
不管多么复杂,事实上默认通道要使用的仅仅是dll通道最终生成的manifest.json文件
,其他配置都可以看做是dll通道内部的配置。现在我将要解释其中的部分参数含义:
用通俗的话讲一遍:
dll通道里面会将vue和jquery打包生成一个动态链接库,文件名称是_dll_lib.js,并且这个动态链接库暴露出一个全局变量_dll_lib。同时生成manifest.json,manifest.json访问的刚好就是全局变量_dll_lib。这样默认通道只需要访问manifest.json就可以访问到vue和jquery。
听起来很绕吧,那就对了!
配置好了,进行第一次打包:
npx webpack --config webpack.config.lib.js
如果你的情况和我完全一样,将得到下面的情况:
看起来似乎比不使用dll优化时的总体积还要大,即便如此,dll还是很有价值的,因为一旦我们生成了一次之后,只要依赖vue和jquery不变,便不需要进行第二次第三次,以后的打包时便可以省略这一个步骤。
现在配置默认通道webpack.config.js:
const path = require("path");
const webpack = require("webpack");
module.exports = {
mode: "development",
entry: { test: "./src/index.js" },
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, "./dist/")
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src")
}
},
plugins: [
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, "dist", "manifest.json")
})
]
};
以上中,仅有一个地方是值得注意的,那就是new webpack.DllReferencePlugin部分:
他表明我们将要通过manifest.json文件引用生成的动态链接库。
现在可以进行默认通道的打包了:
npx webpack
如果你的配置和我完全一样,你就会得到开头的那张效果:
现在,当你修改了自己的js代码时,你是无需再次对dll进行打包的,因此在webpack频繁的打包时,就大大节约了时间和体积。
要最大程度的使用好dll优化,事实上还需要考虑很多问题,譬如:
当然,这不是本文的主题,这也并不妨碍dll作为一个重要优化点的作用!