背景
笔者最近发现本地打包太慢,大概需要3分钟左右,于是在网上找了百度了下 发现就是2个点
dll
hard-source-webpack-plugin
看了下文章就说用了hard-source-webpack-plugin
之后能提升 90% 的构建速度,于是乎我满心欢喜的用上了了,发现第一次构建3分半,,第二次 还是3分半 ,于是乎我就好奇,为什么呢??
由于公司的内网不能上掘金,也不能发表文章,所以笔者是在家里研究这个问题的,项目也是网上随便找的。所以实际的数据可能和真正的公司的项目有偏差,但是此文章的目的只是引导大家遇到问题的时候如何去思考以及解决他
本文章分析的源码是基于@vue/cli 4.5.11
创建的都是默认配置,代码不重要,重要的是分析的过程
分析
一直以来计时都是用手机计时,那么我是不是需要一个工具来帮我计算这个时间,可以用speed-measure-webpack-plugin
但是时间信息不是在最后一行输出,为了方便看时间,那么就自己写一个计算打包时间的webpack
插件CountTimePlugin
统计webpack打包时间插件CountTimePlugin
这个插件的编写逻辑就是利用webpack
的stats
的endTime
和startTime
做一个减法就出来了打包时间
// CountTimePlugin.js
module.exports = class CountTimePlugin {
constructor() {}
apply(compiler) {
compiler.hooks.done.tap("ConsoleTime", stats => {
const times = stats.endTime - stats.startTime;
const minute = Math.floor(times / 1000 / 60);
const second = Math.floor(times / 1000 - minute * 60);
setTimeout(() => {
console.log(
"the build time:\n" + minute + " minute , " + second + " second \n"
);
},2000)
});
}
}
复制代码
使用统计时间插件
连续打了2次包发现时间都是27 秒左右,查看了一下speed-measure-webpack-plugin
打包的日志都是如下
首先2次打包之间我是没有对代码进行修改的,那么cache-loader没有生效?
检查是否启用了cache-loader
使用 vue inspect > projectConfig.txt
查看这个配置文件我们可以发现.vue
文件和test: /\.m?jsx?$/,
的文件都是用cache-loader
的
这个时候思路就有点乱了有使用cache-loader
为什么没有换成呢?这个时候脑袋中突然想到每次打包都有hash
难不成不一样?这个想法一下子就好像打开了通往成功的大门
检查cache-loader的hash
我有一次的再命令行输入vue inspect > projectConfig2.txt
对比了一下 发现cacheIdentifier 真的不一样,为什么呢?
定位问题
如何调试
调试的方法有很多,比如装一个debugger-for-chrome
,但是笔者还是喜欢用编辑器调试代码,控制台新建一个JavaScript Debug Terminal
输入
node ./node_modules/@vue/cli-service/bin/vue-cli-service.js build
复制代码
找到cacheIdentifier在哪里生成的
我们的入口文件是node_modules/@vue/cli-service/bin/vue-cli-service.js
// 刚开始是一个构造器,第32行调用了一个生成插件的方法
this.plugins = this.resolvePlugins(plugins, useBuiltIn)
// 142行
resolvePlugins(){
const idToPlugin = id => ({
id: id.replace(/^.\//, 'built-in:'),
apply: require(id)
})
let plugins
const builtInPlugins = [
'./commands/serve',
'./commands/build',
'./commands/inspect',
'./commands/help',
// config plugins are order sensitive
'./config/base',
'./config/css',
'./config/prod',
'./config/app'
].map(idToPlugin)
//... 省略
// 看了下builtInPlugins数组中的文件,其中./config/base 就是生成vue-loader cache-loader配置的地方
// ctrl+f 搜一下plugins 就能看到 init方法中有使用
// apply plugins.
this.plugins.forEach(({ id, apply }) => {
if (this.pluginsToSkip.has(id)) return
apply(new PluginAPI(id, this), this.projectOptions)
})
// 再打断点可以知道 执行的是node_modules/@vue/cli-service/lib/commands/build/index.js的方法
}
复制代码
我们在 node_modules/@vue/cli-service/lib/commands/build/index.js
第三个参数中增加断点得知,最后调用的是
node_modules/@vue/cli-service/lib/commands/build/resolveAppConfig.js
的方法,
到这里终于回去了。我们回到 service.js
再继续断点可以跳转到node_modules/@vue/cli-service/lib/PluginAPI.js
的genCacheConfig
方法
调试genCacheConfig
通过前面的步骤我们可以得知,我们总算找到了生成cacheIdentifier
的地方就是在genCacheConfig
中
const cacheIdentifier = hash(variables)
复制代码
通过这段代码可以知道 唯一的变量就是variables
const variables = {
partialIdentifier,
'cli-service': require('../package.json').version,
'cache-loader': require('cache-loader/package.json').version,
env: process.env.NODE_ENV,
test: !!process.env.VUE_CLI_TEST,
config: [
fmtFunc(this.service.projectOptions.chainWebpack),
fmtFunc(this.service.projectOptions.configureWebpack)
]
}
复制代码
于是我们看一下我们项目的webpack
配置
const childProcess = require('child_process')
// 分支名 因为平安都是标装机自带全局的git工具
const branch = childProcess.execSync('git rev-parse --abbrev-ref HEAD')
configureWebpack: {
plugins: [
new CountTimePlugin(),
new webpack.BannerPlugin(`分支名: ${branch}, 打包时间: ${new Date().toLocaleString()}`),
new HardSourceWebpackPlugin()
],
},
复制代码
就可以发现 我们的项目用了一个bannerPlugin,因为项目都是本地打包,会有多个版本并行,然后只有一个环境,会发生抢环境的问题,于是我就把所有的静态资源,加一个日志 把git分支名,以及打包时间打包到静态资源中了,这样可以解决开发人员快速辨别当前的测试环境的代码是哪个分支的,没想到随手增加的打包时间反而导致了hard-source-webpack-plugin
不起作用,找到这个原因之后,处理起来就很简单了。就把打包时间去掉就好了。
效果
第一次打包时间如下:
第二次打包时间如下:
结语
经过这一次的失误
之后还是让自己成长许多,并不是每一次百度好的一些优化配置都适用于自身系统,可能自身系统本身就有一些有害
的配置会使得其他人的优化做无用功