web 前端性能优化总结(不定期更新)

目录

 

1. 资源合并与压缩

 2. 图片相关的优化

 3. css和js的装载与执行

4. 懒加载与预加载

5. 重绘与回流

 6. 浏览器存储

7. 缓存


1. 资源合并与压缩

http请求过程及潜在的性能优化点

  • 减少http请求的数量
  • 减少请求的大小

 HTML压缩

HTML代码压缩就是压缩这些在文本文件中有意义,但是在HTML中不显示的字符,包括空格、制表符、换行符等,还有一些其他意义的字符,如HTML注释也可以被压缩

 如何进行HTML压缩

  • 使用在线网站进行压缩(一般是构建工具压缩)
  • node.js提供html-minifier工具
  • 后端模板引擎渲染压缩

CSS 压缩

  • 无效代码删除,如注释和无效字符
  • css语义合并

css 压缩方式 

  • 使用在线网站
  • 使用html-minifier 对html中的css进行压缩
  • 使用clean-css 对css压缩

 js压缩与混乱

无效字符的删除  空格、注释、回车等

剔除注释

代码语义的缩减与优化,如变量名缩短等

代码保护

js压缩方式 

  • 在线网站
  • 使用html-minifier对html中的js进行压缩
  • 使用uglifyjs2对js进行压缩

 不合并文件可能存在的问题

  • 文件与文件之间插入的上行请求,增加了N-1个网络延迟
  • 受丢包问题严重
  • 经过代理服务器时可能会被断开

文件合并

公共库的合并

不同页面的合并:不同页面的js要单独打包

 文件合并方法

使用在线网站

构建阶段,使用nodejs进行文件合并

 2. 图片相关的优化

 png8/png24/png32之间的区别

png8    256色 + 支持透明

png24   2^24  + 不支持透明

png32   2^24  + 支持透明

 不同格式图片的特点

jpg有损压缩,压缩率高,不支持透明

png支持透明,浏览器兼容性好

webp压缩程度更好,在iOS webview中有兼容性问题

svg矢量图,代码内嵌,相对较小,图片样式相对简单

 不同格式图片的使用场景

jpg :大部分不需要透明图片的场景

png :大部分需要透明图片的场景

webp:andriod全部(解码速率和压缩率高于jpg和png,但iOS Safari还没支持)

svg:图片相对简单的场景

图片压缩的几种情况

  • 针对真实图片情况,舍弃一些相对无关紧要的色彩信息
  • CSS雪碧图:把网站中用到的一些图片整合到一张单独的图片中

                     优点:减少http请求的数量(通过background-position定位所需图片)

                     缺点:整合图片较大,加载速度较慢

  • Image-inline:将图片的内容嵌到HTML中(减少http请求)

                       base64信息 ,减少网站的http请求,如果图片比较小比较多,时间损耗主要在请求的骨干网路

  • 使用svg矢量图:

                    使用svg进行矢量图的绘制

                    使用icon-font 解决icon问题

  • 在andriod下使用webp

                    webp优势在于压缩率高,能带来更小的图片体积

                    同时具备有损和无损的压缩模式,在JPEG和png上的转化效果都很好 

 3. css和js的装载与执行

网站在浏览器端的渲染过程

 HTML渲染过程中的一些特点

  • 顺序执行,并发加载

词法分析:从上而下依次解析。通过HTML生成token对象(当前节点的所有子节点生成后,才会通过next token获取当前节点的兄弟节点),最终生成token tree

并发加载:资源请求是并发请求的

并发上限:

             浏览器支持并发请求,不同浏览器所支持的并发数量不同(以域名划分),以Chrome为例,并发上限为6个

             优化:把CDN资源分布在多个域名下

  • 是否阻塞

a .  css阻塞

        --  css 在head中通过link引入会阻塞页面的渲染

             css在head中通过link引入,整个页面的渲染都会等待head中的css加载并生成css树,最终和dom整合生成RenderTree之后才会进行渲染

        --  css 不阻塞js的加载,但会阻塞js的执行

        --  css 不阻塞外部脚本的加载

b . js 阻塞

        -- 直接通过<script src="">引入会阻塞后面节点的渲染

             --- html parse 会动态修改文档结构

             --- async  defer  属性

                  ---- defer 属性  延迟执行引入的js脚本,即脚本的加载是不会导致解析的停止,等到document全部解析完                                    毕,defer-script也加载完毕,再执行代码,然后触发documentloaded

                  ---- async 属性  异步执行引入的js脚本,与defer的区别是async会在加载完成后就执行,但不会阻塞解析和渲染。但会阻塞load事,件,所以async-script可能会在DOMcontentloaded触发前或后执行,但一定会在load事件前触发。

 

4. 懒加载与预加载

懒加载

  • 图片进入可视区域后请求图片资源
  • 对于电商等图片很多,页面很长的业务场景适用
  • 减少无效资源的加载
  • 并发加载的资源过多会阻塞js的加载,影响网站的正常使用

注: img src 被设置之后,webkit解析到后才会去请求这个资源。所以图片到达可视区之后,src真正的图片才会被设置进去,没有达到可视区前,没有真正的src,类似于一个占位符

应用场景:电商图片

懒加载实现:原生js

先将img标签中的src链接设为同一张图片(空白图片),将其真正的图片地址存储在img标签的自定义属性中(比如data-src)中。当js监听到该图片元素进入可视区域时,将自定义属性中的地址存储到src属性中去,达到懒加载的效果

<div class="image-list">
    <img src="" class="image-item" lazyload = "true" data-original = "xxxxx">
    <img src="" class="image-item" lazyload = "true" data-original = "xxxxx">
    <img src="" class="image-item" lazyload = "true" data-original = "xxxxx">
    <img src="" class="image-item" lazyload = "true" data-original = "xxxxx">
    <img src="" class="image-item" lazyload = "true" data-original = "xxxxx">
    <img src="" class="image-item" lazyload = "true" data-original = "xxxxx">
</div>


var viewHeight = document.docunmentElement.clientHeight;

function lazyLoad(){
    var eles = document.querySelectorAll('img[data-original][lazyload]')

    Array.prototype.forEach.call(eles,function(item,index){

        var rect;
        if(item.dataset.original === '') return;
        rect = item.getBoundingClientRect();

        if(rect.bottom >= 0 && rect.top < viewHeight){
            !function(){

                var img = new Image();
                img.src = item.dataset.url;
                img.onload = function(){
                    item.src = img.src;
                }
                item.removeAttribute('data-original');
                item.removeAttribute('lazyload');
            }()
         }
    })
}

lazyload()
documment.addEventListener('scroll',lazyload);

 

预加载

  • 图片等静态资源在使用前的提前请求
  • 资源使用到的时候能从缓存中加载,提升用户体验
  • 页面展示的依赖关系维护

应用场景:抽奖

预加载实现:

a.直接请求下来

<img src="https://user-gold-cdn.xitu.io/2019/2/21/1690d1b216cbfa18" style="display: none"/>

b. image对象

var image = new Image();
image.src = "www.pic26.com/dafdafd/safdas.jpg";

 c. xmlhttprequest

var xmlhttprequest = new XMLHttpRequest();

xmlhttprequest.onreadystatechange = callback;

xmlhttprequest.onprogress = progressCallback;

xmlhttprequest.open("GET","http:www.xxx.com",true);

xmlhttprequest.send();

function callback(){
    if(xmlhttprequest.readyState == 4 && xmlhttprequest.status == 200){
        var responseText = xmlhttprequest.responseText;
    }else{
        console.log("Request was unsuccessful:" + xmlhttprequest.status);
    }
}

function progressCallback(){
    e = e || event;
    if(e.lengthComputable){
        console.log("Received"+e.loaded+"of"+e.total+"bytes")
    }
} 

5. 重绘与回流

CSS性能让JavaScript变慢?

将css通过head引入,加载css时会阻塞整个页面的渲染,同样执行js代码的时候也会阻塞,如,js死循环

一个线程    ==》  JavaScript解析

一个线程    ==》   UI渲染

这两个线程互斥,当UI渲染的时候,js执行终止,当js执行时,UI线程被冻结,所以css性能会让JavaScript变慢

 什么是回流 (reflow)

当render-tree中的部分或全部因为元素尺寸、布局、隐藏等改变而需要重新构建,就构成回流

当页面布局和几何属性改变时,就需要回流

什么是重绘(repaint)

 当render-tree中的元素需要更新新的属性,而这些属性只会影响到元素的外观、风格,而不会影响到布局,需要重绘

 二者关系

回流必将引起重绘,而重绘不一定引起回流

 触发页面布局的一些css属性

  • 盒子模型相关属性会触发重布局
width
height
padding
margin
display
border-width
border
min-height
  • 定位属性及浮动也会触发重布局
top
bottom
left
right
position
float
clear
  • 改变节点内部文字结构也会触发回流
text-align
overflow
font-weight
font-family
line-height
vertical-align
white-space
font-size

 

  • 只触发重绘不触发回流的元素
color
border-style/border-radius
visibility
text-decoration
background/backgroud-image/background-position/backgroud-repeat/background-size
outline
box-shadow

 chrome创建图层的条件

将频繁重绘回流的DOM元素单独作为一个独立的图层,那么这个DOM 元素的重绘和回流的影响只会在这个图层中

  • 3D或透视变换
  • CSS属性使用加速视频解码的<video>元素
  • 拥有3D(webGL)上下文或加速
  • 2D上下文的<canvas>元素
  • 进行opacity、transform动画的元素拥有加速
  • 元素有一个z-index较低且包含一个复合层的兄弟元素

 总结:

  • 尽量避免使用触发回流、重绘的CSS属性
  • 将重绘、回流的影响范围限制在单独的图层之内
  • 图层合成过程中消耗很大的页面性能,这是要均衡考虑

 实现优化点总结

  • 用translate替代top属性
  • 用opacity代替visibility

       - opacity不会触发回流重绘,只是改变图层的alpha值,但是需将图片独立出一个图层

       - visibility会触发重绘

  • 不要一条一条修改DOM样式,预先定义好class,然后修改dom的className
  • 把DOM离线后修改,如DOM给display:none,然后修改100次,然后再把他显示出来
  • 不要把DOM节点的属性值放在循环里当成循环变量
  • 不要使用table布局,可能很小的改动都会造成整个table的重新布局
  • 动画实现的速度选择

        - 选择合适的动画速度

        - 根据performance量化性能优化

  • 对于动画新建图层
  • 启用GPU硬件加速,GPU加速意味着数据需要从cpu总总线到GPU传输,需要考虑传输损耗

 6. 浏览器存储

cookies

因为http请求无状态,所以需要cookie去维持客户端状态

cookie的生成方式:

           http --> response header  --> set-cookie

           js 中通过document.cookie可以读写cookie

cookie的用处:

          -- 用于浏览器端和服务器端的交互(用户状态)

          -- 客户端自身数据的存储

expire:过去时间

cookie的限制:

         -- 作为浏览器存储,大小在4KB左右

         -- 需要设置过期时间 expire

重要属性:httponly  不支持js读写(防止收到模拟请求攻击)

不太作为存储方案而是用于维护客户关系

优化点: cookie在相关域名下面

         -- cdn 的流量消耗

         解决方案:cdn的域名和主域名要分开

localStorage

 HTML5设计出来专门用来浏览器存储

大小在5M左右

仅在客户端使用,不和服务期间通信

接口封装较好

浏览器本地缓存方案

sessionStorage

 会话级别的浏览器存储

大小在5M左右

仅在客户端使用,不和服务器通信

接口封装好

对于表单信息的维护

indexDB

 indexDB 是一种低级API,用于客户端存储大量结构化数据。该API使用索引来实现对该数据的高性能搜索。

PWA

 PWA (progressive web apps)是一种web app新模型,并不是具体指某种前言技术,是一个渐进式的web app,通过一系列新的web特性,配合优秀的UI交互设计,逐步增强web app的用户体验。

检测是不是PWA

        -- 当前手机在弱网环境下能不能加载出来

        -- 离线环境下能不能加载出来

特点:

        -- 可靠:在没有网络情况下也能提供基本的页面访问

        -- 快速:针对页面渲染和网络数据访问有较好的优化

        -- 融入:应用可以被增加到手机桌面,并且和普通应用一样有全屏、推送等特性

service worker

 service worker是一个脚本,浏览器独立于当前页面,将其在后台运行,有一首要特性,就是拦截和处理网络请求的能力,包括以编程方式来管理被缓存的响应。

service worker网络拦截能力,存储catch storage ,实现离线应用

7. 缓存

强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况

  • 协商缓存生效,返回304和Not Modified

  • 协商缓存失效,返回200和请求结果

缓存机制:

强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存

httpheader

可缓存性:

public :表明响应可以被任何对象缓存

private:响应只能被单个用户缓存,不能作为共享缓存(代理服务器不能缓存)

no-catch:强制所有缓存了该响应的缓存用户,在使用已存储的缓存数据之前,发送带验证器的请求到原始服务器

only-if-cached:表明如果缓存存在,只是用缓存,无论原始服务器的数据是否有更新

到期:

max-age=<seconds> : 设置缓存存储的最大周期,超过这个时间缓存会被认为过期,与expire相反,时间是相对于请求的时间。max-age优先级高于expires,当有max-age时expires可能会被忽略。

s-maxage=<seconds>:覆盖max-age或expire,但是仅用于public

last-modified 和If-Modified-since

基于客户端和服务端协商的缓存机制

last-modified  --> response header

if-modified-since  --> request header

需要与catch-control共同使用

Etag 和 If-none-match

 文件内容的hash值

etag  --> response header

if-none-match  -->  request header

需要和catch-control共同使用

好处:比if-modified-since更加准确,优先级比last-modified更高

 

 流程图:

enter image description here

看到一篇很好的关于浏览器缓存的文章:https://juejin.cn/post/6844904053223358471#heading-6 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值