网站性能优化概述

一、网络传输性能优化

来自网上
这是navigation timing监测指标图,从图中我们可以看出,浏览器在得到用户请求之后,经历了下面这些阶段:重定向→拉取缓存→DNS查询→建立TCP链接→发起请求→接收响应→处理HTML元素→元素加载完成。

1.1 浏览器存储

浏览器在向服务器发起请求前,会先查询本地是否有相同的文件,如果有,就会直接拉取本地缓存:
在这里插入图片描述
浏览器默认的缓存是放在内存内的,但我们知道,内存里的缓存会因为进程的结束或者说浏览器的关闭而被清除,而存在硬盘里的缓存才能够被长期保留下去。很多时候,我们在network面板中各请求的size项里,会看到两种不同的状态:from memory cache 和 from disk cache,前者指缓存来自内存,后者指缓存来自硬盘。而控制缓存存放位置的,不是别人,就是我们在服务器上设置的Etag字段。在浏览器接收到服务器响应后,会检测响应头部(Header),如果有Etag字段,那么浏览器就会将本次缓存写入硬盘中。

之所以拉取缓存会出现200、304两种不同的状态码,取决于浏览器是否有向服务器发起验证请求。只有向服务器发起验证请求并确认缓存未被更新,才会返回304状态码。

进入nginx的配置文档 nginx.conf

    etag on;   //开启etag验证
    expires 1d;    //设置缓存过期时间为1天

在这里插入图片描述

ps: 在我们配置缓存时一定要切记,浏览器在处理用户请求时,如果命中强缓存,浏览器会直接拉取本地缓存,不会与服务器发生任何通信,也就是说,如果我们在服务器端更新了文件,并不会被浏览器得知,就无法替换失效的缓存。所以我们在构建阶段,需要为我们的静态资源添加hash后缀或者时间戳,避免资源更新而引起的前后端文件无法同步的问题。

1.2资源打包压缩

之前所作的浏览器缓存工作,只有在用户第二次访问我们的页面才能起到效果,如果要在用户首次打开页面就实现优良的性能,必须对资源进行优化。我们常将网络性能优化措施归结为三大方面:减少请求数、减小请求资源体积、提升网络传输速率。

1.2.1 文件压缩(这边针对的是vue-cli3)

    if (IsProduction) {
      config.plugins.push(
        new CompressionPlugin({
          test:/\.js$|\.html|\.css/,
          // 10k数据
          threshold:10240,
          // 是否删除原文件
          deleteOriginalAssets:false
        })
      );
    } else {
      // 开发环境 
    }

在这里插入图片描述
nginx.conf配置gzip

 gzip on;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;

ps: 不要对图片文件进行Gzip压缩!不要对图片文件进行Gzip压缩!不要对图片文件进行Gzip压缩!我只会告诉你效果适得其反,至于具体原因,还得考虑服务器压缩过程中的CPU占用还有压缩率等指标,对图片进行压缩不但会占用后台大量资源,压缩效果其实并不可观,可以说是“弊大于利”,所以请在gzip_types 把图片的相关项去掉。针对图片的相关处理,我们接下来会更加具体地介绍。

感觉这样压缩文件也就差不多了,

最后附上大佬webapack文件压缩,以防后期使用

a.js压缩

    optimization: {
            minimizer: [
                new UglifyJsPlugin({
                    cache: true,
                    parallel: true,
                    sourceMap: true// set to true if you want JS source maps
                }),
                ...Plugins
            ]
        }

b.html压缩

    new HtmlWebpackPlugin({
                template: __dirname + '/views/index.html', // new 一个这个插件的实例,并传入相关的参数
                filename: '../index.html',
                minify: {
                    removeComments: true,
                    collapseWhitespace: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true,
                    removeEmptyAttributes: true,
                    removeStyleLinkTypeAttributes: true,
                    keepClosingSlash: true,
                    minifyJS: true,
                    minifyCSS: true,
                    minifyURLs: true,
                },
                chunksSortMode: 'dependency'
            })
```js

我们在使用`html-webpack-plugin` 自动化注入JS、CSS打包HTML文件时,很少会为其添加配置项,这里我给出样例,大家直接复制就行。据悉,在Webpack5中,`html-webpack-plugin` 的功能会像 `common-chunk-plugin` 那样,被集成到webpack内部,这样我们就不需要再install额外的插件了。

PS:这里有一个技巧,在我们书写HTML元素的`src` 或 `href` 属性时,可以省略协议部分,这样也能简单起到节省资源的目的。(虽然其目的本身是为了统一站内的所有协议)

c. 提取公共资源:

    splitChunks: {
          cacheGroups: {
            vendor: { // 抽离第三方插件
              test: /node_modules/, // 指定是node_modules下的第三方包
              chunks: 'initial',
              name: 'common/vendor', // 打包后的文件名,任意命名
              priority: 10// 设置优先级,防止和自定义的公共代码提取时被覆盖,不进行打包
            },
            utils: { // 抽离自定义公共代码
              test: /\.js$/,
              chunks: 'initial',
              name: 'common/utils',
              minSize: 0// 只要超出0字节就生成一个新包
            }
          }
        }

d.css压缩

    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    module: {
            rules: [..., {
                test: /\.css$/,
                exclude: /node_modules/,
                use: [
                    _mode === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader, {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1
                        }
                    }, {
                        loader: 'postcss-loader',
                        options: {
                            ident: 'postcss'
                        }
                    }
                ]
            }]
        }
```js

我这里配置预处理器postcss,但是我把相关配置提取到了单独的文件`postcss.config.js`里了,其中**cssnano**是一款很不错的CSS优化插件。

e.将webpack开发环境修改为生产环境:

在使用webpack打包项目时,它常常会引入一些调试代码,以作相关调试,我们在上线时不需要这部分内容,通过配置剔除:

    devtool: 'false'
1.3 图片资源

1.3.1.不要在HTML里缩放图像

当你需要用多大的图片时,就在服务器上准备好多大的图片,尽量固定图片尺寸。

1.3.2.使用雪碧图(CSS Sprite)
自动化生成雪碧图的工具:链接地址

只要你添加相关资源文件,他就会自动帮你生成雪碧图以及对应的CSS样式。

其实我们在工程中还有更为自动的方法,便是一款雪碧图生成插件webpack-spritesmith,自行尝试,因为我也不会,第一次接触。

1.3.3.使用字体图标(iconfont)

网址:www.iconfont.cn/,自己的UI组件一般也会有常用的

1.3.4.使用WebP

WebP格式,是谷歌公司开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器带宽资源和数据空间。

网址:www.upyun.com/webp

1.4.网络传输性能检测工具——Page Speed

除了network版块,其实chrome还为我们准备好了一款监测网络传输性能的插件——Page Speed,咱们的文章封面,就是用的Page Speed的官方宣传图(因为我觉得这张图再合适不过了)。我们只需要通过下面步骤安装,就可以在chrome devtools里找到它了:chrome菜单→更多工具→拓展程序→chrome网上应用商店→搜索pagespeed后安转即可。

只需要打开待测试的网页,然后点击Page Speed里的 Start analyzing按钮,它就会自动帮我们测试网络传输性能了。

二、页面渲染优化
2.1.浏览器渲染过程(Webkit)

在这里插入图片描述
在渲染方面我们要减少重排和重绘,因为他们会影响浏览器性能

2.2.DOM渲染层与GPU硬件加速

一个页面是有许多许多层级组成的,他们就像千层面那样,你能想象出这个页面实际的样子吗
在这里插入图片描述
对,你没看错,页面的真实样子就是这样,是由多个DOM元素渲染层(Layers)组成的,实际上一个页面在构建完render tree之后,是经历了这样的流程才最终呈现在我们面前的:

①浏览器会先获取DOM树并依据样式将其分割成多个独立的渲染层
②CPU将每个层绘制进绘图中
③将位图作为纹理上传至GPU(显卡)绘制
④GPU将所有的渲染层缓存(如果下次上传的渲染层没有发生变化,GPU就不需要对其进行重绘)并复合多个渲染层最终形成我们的图像

2.3.重排与重绘

①重排(reflow):渲染层内的元素布局发生修改,都会导致页面重新排列,比如窗口的尺寸发生变化、删除或添加DOM元素,修改了影响元素盒子大小的CSS属性(诸如:width、height、padding)。
②重绘(repaint):绘制,即渲染上色,所有对元素的视觉表现属性的修改,都会引发重绘。

重排是由CPU处理的,而重绘是由GPU处理的,CPU的处理效率远不及GPU,并且重排一定会引发重绘,而重绘不一定会引发重排。所以在性能优化工作中,我们更应当着重减少重排的发生。

在这里插入图片描述

2.4.优化策略

(一)CSS属性读写分离:浏览器每次对元素样式进行读操作时,都必须进行一次重新渲染(重排 + 重绘),所以我们在使用JS对元素样式进行读写操作时,最好将两者分离开,先读后写,避免出现两者交叉使用的情况。最最最客观的解决方案,就是不用JS去操作元素样式,这也是我最推荐的。
(二)通过切换class或者style.csstext属性去批量操作元素样式
(三)DOM元素离线更新:当对DOM进行相关操作时,例如innerHTML、appendChild等都可以使用Document Fragment对象进行离线操作,待元素“组装”完成后再一次插入页面,或者使用display:none 对元素隐藏,在元素“消失”后进行相关操作。
(四)将没用的元素设为不可见:visibility: hidden,这样可以减小重绘的压力,必要的时候再将元素显示。
(五)压缩DOM的深度,一个渲染层内不要有过深的子元素,少用DOM完成页面样式,多使用伪元素或者box-shadow取代。
(六)图片在渲染前指定大小:因为img元素是内联元素,所以在加载图片后会改变宽高,严重的情况会导致整个页面重排,所以最好在渲染前就指定其大小,或者让其脱离文档流。
(七)对页面中可能发生大量重排重绘的元素单独触发渲染层,使用GPU分担CPU压力。(这项策略需要慎用,得着重考量以牺牲GPU占用率能否换来可期的性能优化,毕竟页面中存在太多的渲染层对于GPU而言也是一种不必要的压力,通常情况下,我们会对动画元素采取硬件加速。)

三、js阻塞性能

JavaScript在网站开发中几乎已经确定了垄断地位,哪怕是一个再简单不过的静态页面,你都可能看到JS的存在,可以说,没有JS,就基本没有用户交互。然而,脚本带来的问题就是他会阻塞页面的平行下载,还会提高进程的CPU占用率。更有甚者,现在node.js已经在前端开发中普及,稍有不慎,我们引发了内存泄漏,或者在代码中误写了死循环,会直接造成我们的服务器奔溃。在如今这个JS已经遍布前后端的时代,性能的瓶颈不单单只是停留在影响用户体验上,还会有更多更为严重的问题,对JS的性能优化工作不可小觑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值