首屏加载优化

194 阅读2分钟

利用webpack打包分析插件分析打包后的文件,发现chunk-vender中打包的有比较大的第三方组件echarts。为了减少首屏加载时间,我们可以从以下几个方面着手。

一、排除第三方库

我们可以把这些第三方的框架或者组件从chunk-vender中排除,以减小chunk-vender的体积,利用webpack的externals来把echarts从chunk-vender中排除,然后在index.html中把我们排除的内容通过cdn引入

chainWebpack: (config) => {    config    .plugin('webpack-bundle-analyzer')    .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)    //忽略的打包文件    config.externals({      'vue': 'Vue',      'vue-router': 'VueRouter',      'vuex': 'Vuex',      'axios': 'axios',      'echarts': 'echarts',      'moment': 'moment',      'element-ui': 'ELEMENT',    });  },

二、组件懒加载

通过组件懒加载,来减小app.js的体积,需要注意的是每个组件webpackChunkName后面的名字不能相同,如果相同,就会打包进同一个同名文件中

            {                path: '/connection/apply/test',                name: '测试',                meta: {                    i18n: ''                },                component: () => import( /* webpackChunkName: "test" */ '@/views/connection/apply/test')            },

三、压缩js、css,以及图片压缩

压缩功能webpack5+自带

// vue.config.js
const TerserJSPlugin = require('terser-webpack-plugin');
....
chainWebpack: (config) => {
    // 开启js、css压缩
    config.plugin('TerserJSPlugin')
      .use(new TerserJSPlugin({
        terserOptions: {
          output: {
            comments: false // 去掉注释
          },
          warnings: false,
          compress: {
            // eslint-disable-next-line camelcase
            drop_console: true,
            // eslint-disable-next-line camelcase
            drop_debugger: true,
            // pure_funcs: ['console.log'] // 移除console
          }
        }
      }));
}

四、http缓存

可以和运维同学商讨http的缓存策略(1、强缓存2、协商缓存),如有需要请移步 http缓存详解

五、开启http压缩

# nginx前端静态资源配置
server { 
    listen 8080; 
    server_name _;
    gzip_static on; // 开启gzip压缩
    client_max_body_size 500m; 
    root /data/****/web/dist; 
    index index.html; 
    location ^~ /api { 
        proxy_pass http://***.**.**.***:8080/; 
        proxy_set_header Host ***.**.**.***; 
    } 
}

六、拆解业务代码包

使用webpack的optimization,

// vue.config.js
....
chainWebpack: (config) => {
    ...
    config.optimization && config.optimization.splitChunks({
        // 拆包配置 
        chunks: 'all', //三选一:"initial" 初始化,"all"(默认就是all),"async"(动态加载) 
        minSize: 30000, // 形成一个新代码块最小的体积,只有 >= minSize 的bundle会被拆分出来 30000
        maxSize: 0, //拆分之前最大的数值,默认为0,即不做限制
        minChunks: 1, //引入次数,如果为2 那么一个资源最少被引用两次才可以被拆分出来
        maxAsyncRequests: 5, // 按需加载的最大并行请求数
        maxInitialRequests: 3, // 一个入口最大并行请求数
        automaticNameDelimiter: '~', // 文件名的连接符
        name: true,
        cacheGroups: {
        // node_modules模块包
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: 'chunk-vendors',
          // name(module) {
          //   const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
          //   return `chunk.${packageName.replace('@', '')}`;
          // },
          chunks: 'all',
          priority: -10,
        },
        // 共享模块
        common: {
          name: 'chunk-common',
          minChunks: 2,
          maxSize: 1024, //拆分之前最大的数值,默认为0,即不做限制
          priority: -20,
          reuseExistingChunk: true
        }
        }
    });
    ...
}