html网页性能优化,网页页面性能优化总结

js性能优化是前端面试一个常问知识点。所以我结合我个人一些经验,加上看了其他一些文章点分析。作了一些总结。

一,主要从用户输入网址到页面渲染完成。及与用户交互到方面来分析。

过程:

用户输入网址请求资源 => 将请求到的资源渲染成页面 => 渲染完成的页面交互 => 其他方面的优化

一,用户输入网址请求资源

当用户输入一个域名网址时,浏览器会将这个域名发送到DNS服务器

(这一过程中,我们可以通过改变我们host的配置,将域名配置为我们开发环境的服务器ip。实现远程开发);

通过DNS服务器进行域名解析,拿到对应的服务器ip地址;

浏览器拿到服务器的ip后,找到对应的服务器;

=>这个过程可以做个http缓存优化(见下文——http缓存)

获取服务器js,html等资源;

二,将请求到的资源渲染成页面

=>http页面加载及渲染过程的优化(见下文——页面加载及渲染过程)

三,渲染完成的页面交互

=>页面交互过程的优化(见下文——页面交互过程的优化)

四,其他方面的优化

=>其他方面的优化的优化(见下文——其他方面的优化)

二,http缓存及优化

http缓存:强制缓存和协商缓存

强制缓存

不会向服务器发送请求,直接从缓存中读取资源,

在chrome控制台的network选项中可以看到该请求返回200的状态码,

并且size显示from disk cache或from memory cache;

复制代码设置强制缓存的方式:

在响应头设置:

Catch-Control优先级 > Expires优先级

Catch-Control:

比如Cache-Control:max-age=300(秒)

代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存

Expires:

比如Expires:Thu,21 Jan 2020 23:39:02 GMT

response header里的过期时间,浏览器再次加载资源时,如果在这个过期时间内,则命中强缓存。

它的值为一个绝对时间的GMT格式的时间字符串;

存在一个缺点:但由于服务端时间和客户端时间可能有误差,这也将导致缓存命中的误差,因此现在常用这个;

复制代码协商缓存

协商缓存:向服务器发送请求,服务器会根据这个请求的request

header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response

header通知浏览器从缓存中读取资源;另外协商缓存需要与cache-control共同使用。;

复制代码设置协商缓存的方式:

在响应头设置:

Etag优先级 > Last-Modified优先级

Etag:

服务器响应请求时,通过此字段告诉浏览器当前资源在服务器生成的唯一标识(生成规则由服务器决定);

If-None-Match: 再次请求服务器时,浏览器的请求报文头部会包含此字段,后面的值为在缓存中获取的标识。

服务器接收到次报文后发现If-None-Match则与被请求资源的唯一标识进行对比:

a. 不同,说明资源被改动过,则响应整个资源内容,返回状态码200。

b. 相同,说明资源无心修改,则响应header,浏览器直接从缓存中获取数据信息。返回状态码304.

c. 但是实际应用中由于Etag的计算是使用算法来得出的,而算法会占用服务端计算的资源,

所有服务端的资源都是宝贵的,所以就很少使用Etag了。

Last-Modified: Fri, 22 Jul 2020 01:47:00 GMT

服务器在响应请求时,会告诉浏览器资源的最后修改时间;

if-Modified-Since:

浏览器再次请求服务器的时候,请求头会包含此字段,后面跟着在缓存中获得的最后修改时间。

服务端收到此请求头发现有if-Modified-Since,则与被请求资源的最后修改时间进行对比,

如果一致则返回304和响应报文头,浏览器只需要从缓存中获取信息即可。

从字面上看,就是说:从某个时间节点算起,是否文件被修改了:

a. 如果真的被修改:那么开始传输响应一个整体,服务器返回:200 OK

b. 如果没有被修改:那么只需传输响应header,服务器返回:304 Not Modified

if-Unmodified-Since:

从字面上看, 就是说: 从某个时间点算起, 是否文件没有被修改

如果没有被修改:则开始继续传送文件: 服务器返回: 200 OK

如果文件被修改:则不传输,服务器返回: 412 Precondition failed (预处理错误);

这两个的区别是一个是修改了才下载一个是没修改才下载。

Last-Modified 说好却也不是特别好,因为如果在服务器上,一个资源被修改了,但其实际内容根本没发生改变,

会因为Last-Modified时间匹配不上而返回了整个实体给客户端(即使客户端缓存里有个一模一样的资源)。

为了解决这个问题,HTTP1.1推出了Etag。

复制代码强制缓存优先级 > 协商缓存优先级;

刷新

用户行为对浏览器缓存的影响

1.地址栏访问,链接跳转是正常用户行为,将会触发浏览器缓存机制;

2.F5刷新,浏览器会设置max-age=0,跳过强缓存判断,会进行协商缓存判断;

3.ctrl+F5刷新,跳过强缓存和协商缓存,直接从服务器拉取资源。

复制代码缓存的优点

a. 减少了冗余的数据传递,节省宽带流量

b. 减少了服务器的负担,大大提高了网站性能

c. 加快了客户端加载网页的速度 这也正是HTTP缓存属于客户端缓存的原因。

复制代码

三,页面加载及渲染过程(HTML,Js,css等资源的加载与执行)

当浏览器在解析dom树的时候,如果遇到script标签。会阻塞其他任务的执行。直到script标签加载,解析完成;

这个时候页面会一片空白。用户体验很不好,可以使用以下做法;

=> A, 将script标签放在body的最底部,保证js文件最后加载并执行;同时不影响页面加载;

=> B, 或者使用defer,如下写法。这种方式可以使浏览器解析到script标签时,也会加载js。但他会等到dom树解析完成后再去执行js(DomContentLoader之前执行),因此不会阻塞浏览器执行;

复制代码=> C, 动态的插入script标签来加载脚本,比如通过以下代码(参考);

function loadScript(url, callback){

const script = document.createElement('script');

script.type = 'text/javascript';

// 处理IE

if (script.readyState) {

script.onreadystatechange = function (){

if (script.readyState === 'loaded' || script.readyState === 'complete') {

script.onreadystatechange = null;

callback();

}

}

} else {

// 处理其他浏览器的情况

script.onload = function (){

callback();

}

}

script.src = url;

document.body.append(script);

}

// 动态加载js

loadScript('file.js', function (){

console.log('加载完成');

});

复制代码解析css时。不会操作html元素。因此不会阻塞dom树的渲染;同时dom树和css都解析完成后,合并生成渲染树;

浏览器按照从上到下,从左到右的顺序。绘制生成渲染树。展示页面给用户;

四,渲染完成的页面交互

滚动条调用接口时,可以用节流throttle等优化方式,减少http请求;

输入搜索时,可以用防抖debounce等优化方式,减少http请求;

减少dom元素对操作次数(参考);

// 优化前

const el = document.getElementById('test');

el.style.borderLeft = '1px';

el.style.borderRight = '2px';

el.style.padding = '5px';

// 优化后,一次性修改样式,这样可以将三次重排减少到一次重排

const el = document.getElementById('test');

el.style.cssText += '; border-left: 1px ;border-right: 2px; padding: 5px;'

复制代码使用事件委托;

应该尽可能的减少对象成员的查找次数和嵌套深度;

降低循环遍历次数(特别对于多维数组的匹配时);

let arr1 = [{id: 12, name: 'aa'}, {id: 33, name: 'aa'}];// => {12: {id: 12, name: 'aa', 33: {id: 12, name: 'aa'}};

let arr2 = [{id: 12, age: '18'}, {id: 33,age: '22' }];

复制代码

五,其他方面的优化

对js,css等资源进行源码压缩,减小文件大小;

合理控制图片大小,对长期固定图片使用base64编码,使用雪碧图等;

设置样式时,尽量使用className,少用style;

少用全局变量,避免全局搜索;

方便时多使用原生方法;

使用第三方资源时。尽量做到按需加载;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值