前端性能优化之超简单配置让你的项目性能提升60%

写在前面

本文的所描述的性能优化包括nginx、webpack等工具的配置,不包括前端的具体业务代码。这是前端新人的第一次性能优化尝试,标题说的提升60%和项目是否已经优化、机器性能关系非常大,仅供参考。欢迎大佬指出文章中的不足。

准备

优化需要有一些指标,对比优化前后的数据,才能知道优化是否成功。
这里使用chrome或者edge自带的lighthouse进行优化。
然后选择一个vue项目,尽量选择体积大一些的,这样效果明显。我用的是一个后台管理项目,这个项目基本没有考虑性能优化。
使用一个只有初始配置的nginx启动这个打包后的vue项目
记录初始数据:
image

开始优化

下面是lighthouse给的一些优化建议
image

gzip

启用gzip

下面是nginx中关于gzip的配置
nginx.conf

http {
    # `gzip` Settings
    #开启和关闭gzip模式
    gzip on;
    #gizp压缩起点,文件大于10k才进行压缩
    gzip_min_length 10k;
    # 配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
    gzip_disable "MSIE [1-6]\.";
    # 设置压缩所需要的缓冲区大小,以4k为单位,如果文件为7k则申请2*4k的缓冲区
    gzip_buffers 2 4k;
    # 设置gzip压缩针对的HTTP协议版本
    gzip_http_version 1.1;
    # gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
    gzip_comp_level 6;
    # 进行压缩的文件类型。
    gzip_types application/javascript text/css;
    #nginx对于静态文件的处理模块,开启后会寻找以.gz结尾的文件,直接返回,不会占用cpu进行压缩,如果找不到则不进行压缩
    gzip_static on;
    # 是否在http header中添加Vary: Accept-Encoding,建议开启
    gzip_vary on;
}

然后重启nginx,在nginx目录下输入命令
./nginx -s reload
再次记录性能
image
可以看到加载速度有了大幅度的提高,从8.1秒提升到了3.6秒

关于使用gzip的思考

如何判断gzip on生效?

响应头出现Content-Encoding: gzip的时候,说明gzip on生效。lighthouse关于性能的指标都有进步也可以侧面体现。
image

使用gzip是会占用服务器资源的,这个影响大吗?

我在本地的任务管理器里看了一下,影响很小吧,也可能是我本地访问的原因?或者我这个访问量太少了。不过后台管理项目实际上的访问量也不会太高。当然作为一个初学者,我还是尝试尽可能优化一下,gzip_static可以在本地对应文件有.gz文件的时候直接发了.gz文件,省去了压缩的步骤。
image

怎么确认gzip_static on命令生效是否生效?生成的.gz文件放在哪?

我原本以为这个命令的意思的是找到.gz文件的直接发送,没找到的压缩一下发送的同时,也保存到本地,下次再收到请求就不需要压缩了。然后翻了一下nginx目录,没有看到.gz文件。查了一下好像.gz文件是需要自己压缩的。

webpack配置生成.gz文件

安装依赖,我vue版本是2.6如果安装最新版本会报错

npm install compression-webpack-plugin@5 --save-dev

配置vue.config.js

const CompressionPlugin = require('compression-webpack-plugin');

module.exports = {
  configureWebpack: {
      plugins: [
        new CompressionPlugin({
        algorithm: 'gzip', // 使用gzip压缩
        test: /\.js$|\.css$/, // 匹配文件名
        filename: '[path].gz[query]', // 压缩后的文件名(保持原文件名,后缀加.gz)
        minRatio: 1, // 压缩率小于1才会压缩
        threshold: 10240, // 对超过10k的数据压缩
        deleteOriginalAssets: false // 是否删除未压缩的源文件,谨慎设置,如果希望提供非gzip的资源,可不设置或者设置为false(比如删除打包后的gz后还可以加载到原始资源文件)
      }),
    ],
}

然后build,看到类似下图说明gzip打包成功了
image

对比是否使用gzip_static on

然后放到nginx里替换一下,刷新,测评分
image
对比前面没有使用预压缩的,可以看到没有明显提升,甚至阻塞时间还增加了?
波动的影响应该存在,也可能是打包后的体积变大了?这个.gz文件的体积应该没影响吧?
补充一下,服务器动态压缩的请求头ETag是W/开头

启用浏览器缓存

最快的请求是没有请求,使用强缓存在浏览器本地能访问到对应资源的时候直接使用浏览器缓存,可以大幅度提高用户二次访问的速度,降低服务器压力。或者使用协商缓存,多一个请求确认资源是否更新的过程,但对较大文件的访问速度也可以有效提高。下图是强缓存和协商缓存同时使用的情况
image
浏览器第一次加载资源时,服务器返回200,浏览器从服务器下载资源文件,并缓存资源文件和响应头,供下次访问使用,nginx可以配置浏览器缓存的原理就是给资源加上对应响应头。

关于浏览器缓存的一些思考

e-tag的命名规则是怎么样?

查到的资料都是说e-tag是根据文件内容生成的唯一标识,内容没改的话,e-tag也不会改。但是还有一些说法是e-tag和环境也有关系,那在使用多服务器负载均衡的时候上就不能使用e-tag了,因为不同的服务器对同一资源生成的e-tag不一样,就失去了协商缓存的意义了。

浏览器默认的缓存策略是怎么样的呢?

我看了一下nginx的初始配置是没有cache-control的部分的,响应头也没有cache-control的字段,但实际上浏览器是会有默认缓存策略的。我有点好奇,查了一下资料好像没有看到很权威的说法,有一些人说是强缓存,目前看来是比较符合的,因为我在不设置缓存策略的请求中没有看到过304,那么应该是强缓存或者是强缓存/协商缓存共同使用。
image

用户因为强缓存没能及时获取最新资源怎么办。

对vue项目,nginx可以给index.html设置协商缓存,给其他资源设置强缓存。
webpack打包时根据文件哈希值生成文件名,这样获取获取到的就是最新的资源了。

nginx配置

根据自己的需要给不同类型的文件设置不同的缓存策略。还有听说不同服务器对相同文件生成的e-tag不一样,这个我还没验证,如果不一样的话,对配置了负载均衡的时候,去掉e-tag比较好。

location / {
  root html;
  index index.html index.htm;
  # add_header Cache-Control no-cache;
}
location /index.html {
  add_header Cache-Control "no-cache";
}
location ~* ^.+\.(css|js)$ {
  #   add_header Cache-Control max-age=360000000;
  expires 30d;
  #   去掉e-tag,
  #   etag off;
}
location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {
  expires 30d;
}

webpack配置

output: {
  path: path.join(__dirname, '../public/vendor'),
  libraryTarget: 'umd',
  filename: '[name]_[contenthash].dll.js',
  library: '[name]_[contenthash]'
},
plugins: [
  new CleanWebpackPlugin(),
  new webpack.DllPlugin({
    // context:  process.cwd(),
    name: '[name]_[contenthash]',
    path: path.join(__dirname, '../public/vendor', '[name]_[contenthash]-manifest.json')
  }),
  new UglifyJSPlugin()
]

最终优化效果

image
下面的部分没有实际操作,因为改动太大,也怕改出问题,因为即使是仅理论部分我也没理清楚。等新的项目开始时,我再尝试一下吧,希望到时能出一篇好文章。

减少未使用的js,css

使用了gzip和配置缓存过后,看看lighthouse新的优化建议
image

我如何知道哪些js文件是未使用的?

尝试找了一下教程,好像没有说的比较明白的,我按照所学做一下简单理解吧。如果是传统的前端项目,每个页面都是单独的html文件,js和css通过内嵌标签引入,比如引入jq,还是能很容易区分哪些文件没使用的。vue项目的话就是不要进行import但是不引用吧,还有就是vue是单页面应用,默认是会把所有文件下载到浏览器,可以配置路由懒加载,还有就是异步组件。

移除阻塞渲染资源

这个“移除阻塞渲染的资源”是lighthouse给的标题,实际上不是让我们把这些资源去掉,而且在把这些资源变得不造成阻塞渲染。

什么是阻塞渲染?什么是阻塞渲染资源?

MDN-PerformanceResourceTiming.renderBlockingStatus
阻塞渲染就是在浏览器解析html文档时,遇到需要加载的文件(js、css),在获取到这些文件之前(如果是js默认情况还会执行再继续解析html),不会在屏幕上渲染任何像素。只有需要引入外部文件才会造成阻塞渲染,内部的script和style标签是不会造成阻塞的
阻塞渲染资源包括js、css、字体文件。有些观点认为图片也是阻塞渲染资源,按照规范的定义是不算的,因为图片请求慢不会阻止其他资源的渲染,可能他是把这个和首屏加载优化弄混了。

如何解决阻塞渲染

js优化

给script标签加上async或者defer属性,注意不要影响到页面交互,在确保加上它们没有问题的时候再加上。不了解这两个属性的可以看看下面的文章。
async vs defer attributes

css优化

首先看一下css在style标签和link标签的表现
1.style标签中的样式
(1). 由html解析器进行解析;
(2). 不阻塞浏览器渲染(可能会产生“闪屏现象”);
(3). 不阻塞DOM解析;

2.link引入的外部css样式
(1). 由CSS解析器进行解析。
(2). 阻塞浏览器渲染(可以利用这种阻塞避免“闪屏现象”)。
(3). 阻塞其后面的js语句的执行;
(4). 不阻塞DOM的解析

在css代码少的时候,可以写到style标签并且放在body前。然后link标签是没有async、defer这些字段的,那么只能按需引入,css代码压缩。而且link标签不阻塞DOM的解析,那么它的表现是有点类似script标签的async的 (或者说是完全并行的),可以将体积较大的css文件拆分成多个较小的css文件。

参考

一文读懂nginx gzip_static

怎么使用vue打包gzip压缩

如何做到Google PageSpeed Insights测试满分

MDN-渲染页面:浏览器的工作原理

Nginx控制浏览器缓存

浏览器原理篇

posted @ 2023-03-02 15:21  初学者-xjr  阅读(118)  评论(0编辑  收藏  举报