美文网首页
你的前端项目启动速度和打包产物都该优化了吧?

你的前端项目启动速度和打包产物都该优化了吧?

作者: 超人s | 来源:发表于2022-08-01 16:38 被阅读0次

    前端项目启动慢?项目打包体积大?跟着陈教练一起,项目的肥油咔咔掉。


    肥油咔咔掉.GIF

    1. 背景

    项目经过几年的迭代,项目的启动速度随着项目的迭代,肉眼可见的变慢,打包的产物也是一天比一天大。启动项目的时间、打包的时间是越来越久了。如同一个胖子,速度跟不上,体重蹭蹭涨。

    接下来就跟着陈教练来两套健身操,减减脂,去去油。

    2. 项目启动提速

    第一套健身操 —— 提速操

    所有的优化,都是需要针对问题进行优化,少数的优化是通用优化。

    首先要知道,项目启动的慢,是因为什么慢。

    开始前,先看一波目前我手上这个巨大项目的启动时间: before.png

    将近190s,3分10秒+,陈教练已经跟着刘畊宏教练跳了一首《本草纲目》了!

    2.1. speed-measure-webpack-plugin

    直接上工具 speed-measure-webpack-plugin, 跟着配置完后,运行项目既可看到如下的分析报告:

    SpeedMeasurePlugin.png
    从分析报告可以看出,项目诸多 loader 占用了大半的时间,而 loader 一般又是基本不会变的,于是乎第一个针对本项目的优化方案就出来了,那就是给这些 loader 加上缓存,方法也很简单,就是使用 cache-loader 进行缓存。
    npm install --save-dev cache-loader
    

    在 webpack 配置文件内对需要缓存的 loader 进行缓存

    
    const cacheLoader = {   // 新增代码
      loader: 'cache-loader'   // 新增代码
    }   // 新增代码
    module.exports = {
      module: {
        rules: [
          {
            test: /\.vue$/,
            use: [
              cacheLoader, // 新增代码
              {
                loader: 'vue-loader',
                options: vueLoaderConfig
              }
            ]
          },
          {
            test: /\.js$/,
            use: [
              cacheLoader, // 新增代码
              {
                loader: 'babel-loader',
              }
            ],
            include: [
              resolve('src'),
            ]
          },
          ... ...
          ... ...
        ]
      }
    }
    

    或者也可以像下面,我写的这样,在配置文件内劫持 webpack 的配置,调用 dynamicWebpackConfig 方法,批量缓存

    /**
     * 
     * @param {*} rules 
     * @returns rules
     * @description 按需缓存需要缓存的loader
     */
    function rules (rules) {
      const shouldCache = ['vue-loader', 'eslint-loader', 'babel-loader']
      const cacheLoader = {
        loader: 'cache-loader'
      }
      rules = rules.map(rule => {
        if (
          rule.use && 
          rule.use[0] && 
          shouldCache.includes(rule.use[0].loader)
        ) {
          rule.use.unshift(
            cacheLoader
          )
        }
        return rule
      })
      return rules
    }
    
    /**
     * 
     * @param {*} devWebpackConfig 
     * @returns devWebpackConfig
     * @description 完整的webpack配置
     */
    
    function dynamicWebpackConfig (devWebpackConfig) {
      devWebpackConfig.module.rules = rules(devWebpackConfig.module.rules)
      return devWebpackConfig
    }
    
    module.exports = dynamicWebpackConfig
    
    做完这一步,需要正常启动一次项目,此时会建立 loader 的缓存。缓存内容在可以在 node_modules/.cache 下看到。再次启动项目,看看启动时间: after.png

    提速了近80秒!此时不知道你是否还记得,在上面我说的这样一句话:

    “所有的优化,都是需要针对问题进行优化,少数的优化是通用优化。”

    针对问题的优化,已经举了一个例子说明了,那么有没有通用优化的?

    通用优化,他来了

    2.2. hard-source-webpack-plugin

    hard-source-webpack-plugin 中间缓存,不管三七二一,只要 webpack 配置不变,通通缓存,这种这种提速方法过于简单暴力,有其他个性化的需求可以看文档进行配置
    hard-source-webpack-plugin

    要注意: ip变化,端口变化也是 webpack 配置的变化

    使用方法也很简单:

      const hardSourceWebpackPlugin = require('hard-source-webpack-plugin')
      ... ...
      ... ...
    
      plugins: [
        new hardSourceWebpackPlugin({
          cachePrune: {
            maxAge: 7 * 24 * 60 * 60 * 1000, // 默认2天,现改7天删除
            sizeThreshold: 500 * 1024 * 1024 // 默认50,现修改为500,目前项目启动后占用400MB的空间
          }
        }), //
      ... ...
      ]
    

    同样,这些额外的配置,也可以跟我上面劫持修改 webpack 配置一样,写在一起,方便维护:

    /**
     * 
     * @param {*} plugins 
     * @returns plugins
     * @description 按需push插件
     */
    function plugins (plugins) {
    
      const hardSourceWebpackPlugin = require('hard-source-webpack-plugin')
    
      plugins.push(
        new hardSourceWebpackPlugin({
          cachePrune: {
            maxAge: 7 * 24 * 60 * 60 * 1000, // 默认2天,现改7天删除
            sizeThreshold: 500 * 1024 * 1024 // 默认50,现修改为500,目前项目启动后占用400MB的空间
          }
        }), //
      )
    
      return plugins
    }
    
    /**
     * 
     * @param {*} rules 
     * @returns rules
     * @description 按需缓存需要缓存的loader
     */
    function rules (rules) {
      const shouldCache = ['vue-loader', 'eslint-loader', 'babel-loader']
      const cacheLoader = {
        loader: 'cache-loader'
      }
      rules = rules.map(rule => {
        if (
          rule.use && 
          rule.use[0] && 
          shouldCache.includes(rule.use[0].loader)
        ) {
          rule.use.unshift(
            cacheLoader
          )
        }
        return rule
      })
      return rules
    }
    
    /**
     * 
     * @param {*} devWebpackConfig 
     * @returns devWebpackConfig
     * @description 完整的webpack配置
     */
    
    function dynamicWebpackConfig (devWebpackConfig) {
        devWebpackConfig.plugins = plugins(devWebpackConfig.plugins)
        devWebpackConfig.module.rules = rules(devWebpackConfig.module.rules)
    
        return devWebpackConfig
    }
    
    module.exports = dynamicWebpackConfig
    
    由于该优化方案还是缓存,所以还是需要正常启动一次项目后,建立缓存。缓存内容在可以在 node_modules/.cache 下看到。再次启动,查看启动时间: afteragine.png

    第一套健身操昨完,项目的启动速度已经从 180s 提速至 30s。

    累了的同学可以先休息一会儿

    3. 项目打包优化

    休息结束,跟上第二套健身操 ——— 打包体积优化操

    经过第一套的健身操之后,打包速度上,也会沾了缓存的光,打包速度也会有提升。但是,我们打包的体积还是那么大,怎么办?

    开始前,还是需要看一看,我们打完包后的产物体积: image.png

    还是那句话,“所有的优化,都是需要针对问题进行优化,少数的优化是通用优化。”

    那么,如何找到问题呢?

    3.1 webpack-bundle-analyzer

    这时候就需要用到一个很常见的工具,webpack 打包分析插件 webpack-bundle-analyzer,简单配置完后,重新运行打包命令,可以在本地的8888端口看到如下效果:

    image.png

    每个颜色的快,就是打包产物内的代码块,图中占面积越大的文件,其文件的大小越大,部署到服务器之后,在浏览器中加载的时间越长。我们可以根据这个图,去优化

    通过这个分析图,我们可以知道:

    • 了解 bundle 包中的真正内容
    • 找出哪些模块尺寸最大
    • 查找误引入的模块
    • 优化项目

    具体优化就看各位同学的眼力和优化方向了。这边我举一个例子:
    譬如,我发现在 app、outer-form 两个个模块内,有一块公共的代码,分别打入这两个个模块


    image.png

    此时可以在 webpack 配置优化打包如下:

        new webpack.optimize.CommonsChunkPlugin({
            name: 'common',
            chunks: ['app', 'outer-form'] // 抽取commons chunk
        }),
    

    打包后体积略有减小,因为这个地方属于略有优化。


    image.png

    动动眼睛动动手,其实还可以发现更多的优化点,再比如:


    image.png

    OK,点到为止!

    4. 最后

    希望大家身上的肥油也咔咔掉

    相关文章

      网友评论

          本文标题:你的前端项目启动速度和打包产物都该优化了吧?

          本文链接:https://www.haomeiwen.com/subject/mfdrwrtx.html