性能优化加载遇坑记

项目打包体积大,页面首屏加载时间过长,导致页面白屏。因此进行性能优化,性能优化的最终目的是提升用户体验。

1、BundleAnalyzer

作用:展示打包图形化信息,会打开一个html页面,帮助自己分析哪些文件过大,可针对其进行优化,上线前 注释掉

	// 安装 webpack-bundle-analyzer 插件 
	npm install webpack-bundle-analyzer -D
	
	// 在 vue.config.js: 里面:
	// 引入
	const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
	// 展示图形化信息
	chainWebpack: config => {
	  config
	      .plugin('webpack-bundle-analyzer')
	      .use(BundleAnalyzerPlugin)
	}

	// 查看
	npm run build --report

2、排查并移除冗余依赖、静态资源

  • 移除项目模板冗余依赖
  • 将public的静态资源移入assets。静态资源应该放在assets下,public只会单纯的复制到dist,应该放置不经webpack处理的文件,比如不兼容webpack的库,需要指定文件名的文件等

3、压缩CSS(mini-css-extract-plugin)

	// 安装 mini-css-extract-plugin 插件
	npm install mini-css-extract-plugin -D
	
	// 在 vue.config.js里面:
	const MiniCssExtractPlugin = require('mini-css-extract-plugin')
	
	chainWebpack: config => {
	  let miniCssExtractPlugin = new MiniCssExtractPlugin({
	    filename: 'assets/[name].[hash:8].css',
	    chunkFilename: 'assets/[name].[hash:8].css'
	  })
	  config.plugin('extract-css').use(miniCssExtractPlugin)
	}
	// 在module.exports下添加,否则在打包过程出现 报错没有可用于依赖类型的模块 CssDependency
	css: {
	    extract: false
	}

4、构建时压缩图片(image-webpack-loader)

  • install或build时如果出现imagemin库下载失败,可以尝试换源、配置github hosts、install时添加–user=root解决。本人使用cnpm安装成功
  • 卸载插件时注意,npm和cnpm混用卸载回起冲突,使用npm卸载之后compression-webpack-plugin插件不能使用
	// 安装前请先查看上面的两点 install 
	npm i image-webpack-loader -D
	// vue.config.js
	chainWebpack: (config) => {
	    if (isProd) {
	        // 图片压缩处理
	        const imgRule = config.module.rule('images')
	        imgRule
	            .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
	            .use('image-webpack-loader')
	            .loader('image-webpack-loader')
	            .options({ bypassOnDebug: true })
	            .end()
	    }
	}

5、js压缩(uglifyjs-webpack-plugin)

// 安装 uglifyjs-webpack-plugin 插件
npm install uglifyjs-webpack-plugin -D

// 在 vue.config.js里面
chainWebpack: (config) => {
 config.plugin('uglifyjs-plugin').use('uglifyjs-webpack-plugin', [
        {
          uglifyOptions: {
            warnings: false,
            // 生产环境自动删除console
            compress: {
              dead_code: true, // 移除没被引用的代码
              drop_debugger: true, // 移除 debugger
              drop_console: true, // 移除console函数
              pure_funcs: ['console.log']
            }
          },
          sourceMap: false,
          cache: false, // 是否启用文件缓存,默认的缓存路径为: node_modules/.cache/uglifyjs-webpack-plugin.
          parallel: true // 使用多进程并行运行来提高构建速度
        }
 ])
}

6、terser简化表达式和函数等方式来减小代码体积

terser 会通过简化表达式和函数等方式来减小代码体积,和加快运行时的速度、减少运行时内存占用

// 在 vue.config.js里面
chainWebpack: (config) => {
    config.optimization.minimizer('terser').tap(args => {
        args[0] = {
          test: /\.m?js(\?.*)?$/i,
          chunkFilter: () => true,
          warningsFilter: () => true,
          extractComments: false, // 注释是否单独提取成一个文件
          sourceMap: true,
          cache: true,
          cacheKeys: defaultCacheKeys => defaultCacheKeys,
          parallel: true,
          include: undefined, // 对哪些文件生效
          exclude: undefined,
          minify: undefined, // 自定义minify函数
          // 完整参数见 https://github.com/terser/terser#minify-options
          terserOptions: {
            compress: {
              arrows: true, // 转换成箭头函数
              collapse_vars: false, // 可能有副作用,所以关掉
              comparisons: true, // 简化表达式,如:!(a <= b) → a > b
              computed_props: true, // 计算变量转换成常量,如:{["computed"]: 1} → {computed: 1}
              drop_console: true, // 去除 console.* 函数
              hoist_funs: false, // 函数提升声明
              hoist_props: false, // 常量对象属性转换成常量,如:var o={p:1, q:2}; f(o.p, o.q) → f(1, 2);
              hoist_vars: false, // var声明变量提升,关掉因为会增大输出体积
              inline: true, // 只有return语句的函数的调用变成inline调用,有以下几个级别:0(false),1,2,3(true)
              loops: true, // 优化do, while, for循环,当条件可以静态决定的时候
              negate_iife: false, // 当返回值被丢弃的时候,取消立即调用函数表达式。
              properties: false, // 用圆点操作符替换属性访问方式,如:foo["bar"] → foo.bar
              reduce_funcs: false, // 旧选项
              reduce_vars: true, // 变量赋值和使用时常量对象转常量
              switches: true, // 除去switch的重复分支和未使用部分
              toplevel: false, // 扔掉顶级作用域中未被使用的函数和变量
              typeofs: false, // 转换typeof foo == "undefined" 为 foo === void 0,主要用于兼容IE10之前的浏览器
              booleans: true, // 简化布尔表达式,如:!!a ? b : c → a ? b : c
              if_return: true, // 优化if/return 和 if/continue
              sequences: true, // 使用逗号运算符连接连续的简单语句,可以设置为正整数,以指定将生成的最大连续逗号序列数。默认200。
              unused: true, // 扔掉未被使用的函数和变量
              conditionals: true, // 优化if语句和条件表达式
              dead_code: true, // 扔掉未被使用的代码
              evaluate: true // 尝试计算常量表达式
              // passes: 2, // compress的最大运行次数,默认是1,如果不在乎执行时间可以调高
            },
            mangle: {
              safari10: true
            }
          }
        }
        return args
      })
  }

7、代码分块

首屏加载文件太大,将文件分割出来

// 在 vue.config.js里面
chainWebpack: (config) => {
  config.optimization.splitChunks({
        chunks: 'all',
        maxInitialRequests: 5, // 默认3
        maxAsyncRequests: 6, // 默认5
        cacheGroups: {
          commons: {
            name: 'chunk-commons',
            chunks: 'initial',
            test: resolve('src/components'), // can customize your rules
            minChunks: 2, //  表示被引用次数,默认为1
            maxInitialRequests: 5, // 一个入口最大的并行请求数,默认为3
            minSize: 60000, // 大小超过60kb的模块才会被提取,防止一堆小chunck
            priority: 1,
            reuseExistingChunk: true,
            enforce: true
          },
          libs: {
            name: 'chunk-libs',
            test: /[\\/]node_modules[\\/]/,
            priority: 2,
            reuseExistingChunk: true, //  如果当前代码块包含的模块已经有了,就不在产生一个新的代码块
            chunks: 'initial' // only package third parties that are initially dependent
          },
          elementUI: {
            name: 'chunk-elementUI', // split elementUI into a single package
            priority: 3, // the weight needs to be larger than libs and app or it will be packaged into libs or app
            test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
            reuseExistingChunk: true,
            enforce: true
          },
          agoraRtcSdkNg: {
            name: 'chunk-agora-rtc-sdk-ng', // split elementUI into a single package
            priority: 4, // the weight needs to be larger than libs and app or it will be packaged into libs or app
            test: /[\\/]node_modules[\\/]_?agora-rtc-sdk-ng(.*)/, // in order to adapt to cnpm
            reuseExistingChunk: true,
            enforce: true
          },
        }
      })
  }

8、Gzip压缩传输(compression-webpack-plugin)

Gzip压缩是一种强力压缩手段,针对文本文件时通常能减少2/3的体积。

Nginx配置Gzip

#开启和关闭gzip模式
gzip on;
#gizp压缩起点,文件大于1k才进行压缩
gzip_min_length 1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
gzip_comp_level 6;
# 进行压缩的文件类型。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript ;
# nginx对于静态文件的处理模块,开启后会寻找以.gz结尾的文件,直接返回,不会占用cpu进行压缩,如果找不到则不进行压缩
gzip_static on;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.1;

构建时生成gzip文件
虽然上面配置后Nginx已经会在响应请求时进行压缩并返回Gzip了,但是压缩操作本身是会占用服务器的CPU和时间的,压缩等级越高开销越大,所以我们通常会一并上传gzip文件,让服务器直接返回压缩后文件

  • 不要使用最新版本,使用最新版本会报错
  • 插件的默认压缩等级是9,最高级的压缩
  • 图片文件不建议使用gzip压缩,效果较差
	// 安装 compression-webpack-plugin 插件 (不要使用最新版本)
	npm i compression-webpack-plugin@6.1.1 -D
	
	// vue.config.js
	const CompressionPlugin = require('compression-webpack-plugin')
	// gzip压缩处理
	chainWebpack: (config) => {
	    if(isProd) {
	        config.plugin('compression-webpack-plugin')
	            .use(new CompressionPlugin({
	                test: /\.js$|\.html$|\.css$/, // 匹配文件名
	                threshold: 10240, // 对超过10k的数据压缩
	                deleteOriginalAssets: false // 不删除源文件
	            }))
	    }
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值