写点什么

我是如何把 vue 项目启动时间从 70s 优化到 7 秒的

  • 2021 年 12 月 17 日
  • 本文字数:2961 字

    阅读完需:约 10 分钟

我是如何把vue项目启动时间从70s优化到7秒的

可怕的启动时间公司的产品是一个比较大的后台管理系统,而且使用的是 webpack3 的 vue 模板项目,单次项目启动时间达到了 70s 左右


启动个项目都够吃一碗豆腐脑了,可是没有豆腐脑怎么办,那就优化启动时间吧!


考虑到升级 webpack 版本的风险还是比较大的,出了一点问题都得找我,想想还是先别冒险,稳妥为主,所以我选择了通过插件来优化构建时间。


通过查阅资料,提升 webpack 的构建时间有以下几个方向:


多进程处理文件,同一时间处理多个文件预编译资源模块,比如把长时间不变的库提取出来做预编译,构建的时候直接取编译结果就好缓存,未修改的模块直接拿到处理结果,不必编译减少构建搜索和处理的文件数量针对以上几种优化方向,给出以下几种优化方案。


多进程构建 happypackhappypack 的作用就是将文件解析任务分解成多个子进程并发执行。


子进程处理完任务后再将结果发送给主进程。所以可以大大提升 Webpack 的项目构件速度。


查看 happypack 的 github,发现作者已经不再维护该插件,并且作者推荐使用 webpack 官方的多进程插件 thread-loader,所以我放弃了 happypacy,选择了 thread-loader。


thread-loaderthread-loader 是官方维护的多进程 loader,功能类似于 happypack,也是通过开启子任务来并行解析文件,从而提高构建速度。


把这个 loader 放在其他 loader 前面。不过该 loader 是有限制的。示例:


loader 无法发出文件。loader 不能使用自定义加载器 API。loader 无法访问网页包选项。每个 worker 都是一个单独的 node.js 进程,其开销约为 600 毫秒。还有进程间通信的开销。在小型项目中使用 thread-loader 可能并不能优化项目的构建速度,反而会拖慢构建速度,所以使用该 loader 时需要明确项目构建构成中真正耗时的过程。


我的项目中我主要是用该 loader 用来解析 vue 和 js 文件,作用于 vue-loader 和 babel-loader,如下代码:


const threadLoader = {loader: 'thread-loader',options: {workers: require('os').cpus().length - 1,}}


module.exports = {module:{rules: [{test: /.vue/,use: [threadLoader, // vue-loader前使用该loader{loader: 'vue-loader',options: vueLoaderConfig}],},{test: /.js/,use: [threadLoader, // babel-loader 前使用该 loader{loader: 'babel-loader',options: {cacheDirectory: true}}]}]}}


复制代码配置了 thread-loader 后,重新构建试试,如下图所示,大概缩短了 10 秒的构建时间,还不错。


利用缓存提升二次构建的速度虽然使用了多进程构建项目使构建时间缩短了 10 秒,但是一分钟的构建时间依然让人无法接受,这种挤牙膏似的优化方式多少让人有点不爽,有没有比较爽的方法来进一步缩短构建时间呢?


答案是有的,使用缓存。


缓存,不难理解就是第一次构建的时候将构建的结果缓存起来,当第二构建时,查看对应缓存是否修改,如果没有修改,直接使用缓存,由此,我们可以想象,当项目的变化不大时,大部分缓存都是可复用的,拿构建的速度岂不是会有质的飞跃。


cache-loader 说到缓存,当然百度一查,最先出现的就是 cache-loader,github 搜索下官方文档,得到如下结果:


该 loader 会缓存其他 loader 的处理结果,把该 loader 放到其他 loader 的前面,同时该 loader 保存和读取缓存文件也会有开销,所以建议在开销较大的 loader 前使用该 loader。


文档很简单,考虑到项目中的 vue-loader,babel-loader,css-loader 会有比较大的开销,所以为这些 loader 加上缓存,那么接下来就把 cache-loader 加到项目中吧:


const cacheLoader = {loader: 'cache-loader'}


const threadLoader = {loader: 'thread-loader',options: {workers: require('os').cpus().length - 1,}}


module.exports = {module:{rules: [{test: /.vue/,use: [cacheLoader,threadLoader, // vue-loader前使用该loader{loader: 'vue-loader',options: vueLoaderConfig}],},{test: /.js/,use: [cacheLoader,threadLoader, // babel-loader 前使用该 loader{loader: 'babel-loader',options: {cacheDirectory: true}}]}]}}


复制代码在 util.js 文件中,该文件主要是生成 css 相关的 webpack 配置,找到 generateLoaders 函数,修改如下:


const cacheLoader = {loader: 'cache-loader'}


function generateLoaders(loader, loaderOptions) {// 在 css-loader 前增加 cache-loaderconst loaders = options.usePostCSS ? [cacheLoader, cssLoader, postcssLoader] : [cacheLoader, cssLoader]


if (loader) {  loaders.push({    loader: loader + '-loader',    options: Object.assign({}, loaderOptions, {      sourceMap: options.sourceMap    })  })}
// Extract CSS when that option is specified// (which is the case during production build)if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader', // 添加这句配置解决element-ui的图标路径问题 publicPath: '../../' })} else { return ['vue-style-loader'].concat(loaders)}
复制代码


}复制代码如上配置完成后,再次启动项目,可以发现,现在的启动时间没什么变化,然后我们二次启动项目,可以发现现在的启动时间来到了 30s 左右,前面我们已经说过了,cache-loader 缓存只有在二次启动的时候才会生效。


虽然项目启动时间优化了一半还多,但是我们的欲望是无限大的,30 秒的时间离我们的预期还是有点差距的,继续优化!


hard-source-webpack-pluginHardSourceWebpackPlugin 是一个 webpack 插件,为模块提供中间缓存步骤。为了查看结果,您需要使用此插件运行 webpack 两次:第一次构建将花费正常的时间。第二次建设将大大加快。


话不多说,直接配置到项目中:


const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');module.exports = {//...plugins: [new HardSourceWebpackPlugin()]}复制代码


二次构建时,我们会发现构建时间来到了个位数,只有短短的 7 秒钟。


在二次构建中,我发现了一个现象,构建的进度会从 10% 一下跳到 80%,甚至是一瞬间就完成了中间构建过程。这正验证了该插件为模块提供中间缓存的说法。


为模块提供中间缓存,我的理解是 cache-loader 缓存的是对应 loader 的处理结果 ,而这个插件甚至可以缓存整个项目全部的处理结果,直接引用最终输出的缓存文件,从而大大提高构建速度。


其他优化方法 babel-loader 开启缓存 babel-loader 自带缓存功能,开启 cacheDirectory 配置项即可,官网的说法是,开启缓存会提高大约两倍的转换时间。


module.exports = {module: {rules: [{test: /.js$/,use: [...{loader: 'babel-loader',options: {cacheDirectory: true // 开启缓存}}]}]}}


复制代码 uglifyjs-webpack-plugin 开启多进程压缩 uglifyjs-webpack-plugin 或是其他的代码压缩工具都提供了多进程压缩代码的功能,开启可加速代码压缩。


总结至此,我们完成了项目构建时间从 70s 到 7s 的优化过程,文中主要使用:


工具 作用 优化效果 thread-loader 多进程解析文件 70s -> 60scache-loader 缓存部分高开销的 loader 60s -> 30shard-source-webpack-plugin 缓存模块中间过程 30s -> 7s 最后如果你觉得此文对你有一丁点帮助,点个赞。或者可以加入我的开发交流群:1025263163 相互学习,我们会有专业的技术答疑解惑


如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点 star: https://gitee.com/ZhongBangKeJi/CRMEB不胜感激 !

用户头像

还未添加个人签名 2021.11.02 加入

CRMEB就是客户关系管理+营销电商系统实现公众号端、微信小程序端、H5端、APP、PC端用户账号同步,能够快速积累客户、会员数据分析、智能转化客户、有效提高销售、会员维护、网络营销的一款企业应用

评论

发布
暂无评论
我是如何把vue项目启动时间从70s优化到7秒的