vue打包优化 —— 持续更新2022/03/29

1,060 阅读3分钟

项目 :vue.config.js

引入打包加速插件,引入打包进度插件

npm install hard-source-webpack-plugin
npm install progress-bar-webpack-plugin
npm install chalk

image.png

image.png

通过 externals 加载外部 CDN 资源

vue.config.js 的 chainWebpack 属性中,判断若打包环境为生产环境,则设置 externals配置打包时需跳过的资源

chainWebpack: config => {
    if (IS_PROD) {
        config.set('externals', {
            vue: 'Vue',
            'vue-router': 'VueRouter',
            vuex: 'Vuex',
            axios: 'axios'
        })
    }
}

前往 public\index.html 文件中,把刚刚移除的资源通过链接的方式进行加载

<script src="https://cdn.staticfile.org/axios/0.21.4/axios.min.js"></script>
<script src="https://cdn.staticfile.org/vue-router/3.5.2/vue-router.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="https://cdn.staticfile.org/vuex/3.6.2/vuex.min.js"></script>

优化前

image.png

优化后(后续项目越大,加载的第三方包越多,该优化越明显)

image.png

仅在开发环境下使用mock,利用tree shaking属性给打包瘦身

在 src\main.js 项目入口文件中,对mock数据的引入时,必须加上环境的判断 尽在开发环境下使用mock模块 vue-cli自身打包时即会利用webpack的tree shaking属性跳过使用过的代码

// 仅在开发环境时引入mock
if (process.env.NODE_ENV === "development") {
  require("./request/mock/index.js"); // 模拟普通请求状态的mock
}

优化前

image.png

优化后

无需任何额外操作,整个mock模块消失不见 image.png

启用gzip

在vue.config.js 文件中的的 configureWebpack 配置中新增内容

image.png

但gzip除了本地配置以外还需要nginx进行配置支持的
在服务器的nginx配置中,在该项目的nginx匹配项中新增 gzip_static on 指令

lQLPDhrhSqeH6nTM0M0Br7CkSbYLi2pSsgGeXE_OgFgA_431_208.png

验证开启成功与否,可以看看文件请求时Content-Encoding这个响应头

image.png

启用和不启用 gzip 的项目大小是有上多倍的压缩区别的,所以一定要配置!!

组件库按需引入

以引入elementUI为例,使用官网推荐的 babel-plugin-component 插件

npm install @babel/preset-env --save-dev
npm install babel-plugin-component --save-dev

在项目中新增 .babelrc 文件

{
    "presets": [["@babel/preset-env", { "modules": false }]],
    "plugins": [
      [
        "component",
        {
          "libraryName": "vvic-element-ui",  // 组件库的名字
          "styleLibraryName": "theme-chalk" // css目录的名字
        }
      ]
    ]
  }

然后在 main.js 项目的入口文件中实现对组件的按需引入
实际项目中,通常会把项目中使用范围较广的组件进行全局注入,如:

import {Message, Dialog, Button, Pagination, Select} from 'element-ui';

Vue.prototype.$message = Message;
Vue.use(Button);
Vue.use(Dialog);
Vue.use(Pagination);
Vue.use(Select);

然后后续各个地方中要引入其他组件库组件再各自 import {组件} from 'element-ui'即可

webpack分割代码块加载,大大提高页面加载速度

configureWebpack 配置中,新增下列属性,可实现公共代码块抽离,第三方库抽离,UI组件库抽离 使她们实现了独立的分包打包并用作为缓存

config.optimization = {
      // 分割代码块
      splitChunks: {
        chunks: 'all', /**
      * initial 入口 chunk,对于异步导入的文件不处理
        async 异步 chunk,只对异步导入的文件处理
        all 全部 chunk
      */
        cacheGroups: {
          //公用模块抽离
          libs: {
            name: 'chunk-libs',
            test: /[\\/]node_modules[\\/]/,
            priority: 10,
            chunks: 'initial', // only package third parties that are initially dependent
          },
          //第三方库抽离
          vendor: {
            test: /node_modules/,
            chunks: 'initial',
            priority: 5,
            reuseExistingChunk: true,
            minSize: 0, //大于0个字节(模块的大小限制)
            minChunks: 3, //在分割之前,这个代码块最小应该被引用的次数
                          //(最少复用过几次,只要命中一次,就把他作为单独的模块)
          },
          elementUI: {
            name: 'chunk-elementUI', // split elementUI into a single package
            priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
            test: /[\\/]node_modules[\\/]_?vvic-element-ui(.*)/, // in order to adapt to cnpm
          },
        },
      },
    };

动态加载路由

configureWebpack 配置中,新增下列属性,可实现对页面级别的代码抽离,加载对应页面时再加载对应的chunk.[hash].js 实例中执行的是如果是非本地环境,则使用普通hash,否则就使用contentHash

具体区别可参考:blog.csdn.net/weixin_3440…

// 加js的hash
    config.output.filename = IS_PROD ? `vvic_[name].[contenthash].js` : `vvic_[name].[hash].js`;
    config.output.chunkFilename = IS_PROD
      ? `vvic_[name].[contenthash].js`
      : `vvic_[name].[hash].js`;

vueRouter中路由配置中,对模块进行命名区分

image.png 这样子就能实现仅在 webpack 请求该模块的 chunk 时才会加载,即只有在用户访问时加载,然后被请求的模块和其应用的所有子模块都会分离到同一个异步 chunk 中