性能优化
1.让资源加载更快
减小资源体积
压缩代码
减少访问次数
资源合并、SSR服务器渲染、浏览器缓存
资源合并**
<script src="a.js"></script>
<script src="b.js"></script>
<script src="c.js"></script>
//合并
<script src="abc.js"></script>
SSR服务器渲染
服务器把需要的组件或页面渲染成 HTML 字符串,然后把它返回给客户端。
浏览器缓存
浏览器缓存其实就是浏览器保存通过HTTP获取的所有资源,是浏览器将网络资源存储在本地的一种行为。
浏览器缓存的分类
- 强缓存,2. 协商缓存
- 强缓存
浏览器在加载资源时,会先根据本地缓存资源的 header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。header 中的信息指的是 expires
和 cahe-control
。Expires
:绝对时间。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。Cache-Control
:相对时间
。Cache-Control:max-age=3600,代表着资源的有效期是 3600 秒。
Cache-Control 与 Expires 可以在服务端配置同时启用,同时启用的时候 Cache-Control 优先级高。
- 协商缓存
当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header 中的部分信息来判断是否命中缓存。如果命中,则返回 304 ,告诉浏览器资源未更新,可使用本地的缓存。
这里的 header 中的信息指的是 Last-Modify/If-Modify-Since
和 ETag/If-None-Match
。Last-Modify/If-Modify-Since
:Last-modify
:浏览器第一次请求资源的时候,服务器返回的 header 中会加上 Last-Modify,标识该资源最后修改的时间。当浏览器再次请求该资源时,request 的请求头中会包含 If-Modify-Since。该值为之前返回的 Last-Modify。服务器收到 If-Modify-Since
后,根据资源的最后修改时间判断是否命中缓存。如果命中缓存,则返回 304,并且不会返回资源内容,并且不会返回 Last-Modify。ETag/If-None-Match
:返回的是一个校验码。ETag 可以保证每一个资源是唯一的,资源变化都会导致 ETag 变化。服务器根据浏览器上送的 If-None-Match 值来判断是否命中缓存。
与 Last-Modified
不一样的是,当服务器返回 304 Not Modified 的响应时,由于 ETag 重新生成过,response header 中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。Last-Modified
与 ETag 是可以一起使用的,服务器会优先验证 ETag,一致的情况下,才会继续比对 Last-Modified,最后才决定是否返回 304。
总结
当浏览器再次访问一个已经访问过的资源时,它会这样做:
- 看看是否命中强缓存,如果命中,就直接使用缓存了。
- 如果没有命中强缓存,就发请求到服务器检查是否命中协商缓存。
- 如果命中协商缓存,服务器会返回 304 告诉浏览器使用本地缓存。
- 否则,返回最新的资源。
参考文章:https://segmentfault.com/a/11...
使用更快的网络
CDN全称内容分发网络。用户在浏览网站的时候,CDN会选择一个离用户最近的CDN边缘节点来响应用户的请求。
当浏览器向CDN节点请求数据时,CDN节点会判断缓存数据是否过期,若缓存数据并没有过期,则直接将缓存数据返回给客户端;否则,CDN节点就会向服务器发出回源请求,从服务器拉取最新数据,更新本地缓存,并将最新数据返回给客户端。 CDN服务商一般会提供基于文件后缀、目录多个维度来指定CDN缓存时间,为用户提供更精细化的缓存管理。
使用DNS预解析
//强制打开a 标签的dns 预解析
<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href-="/host name_ to_ prefetch.com">
在一些浏览器中页面中的a标签默认打开了DNS预解析,但是页面协议是以https开头,很多浏览器默认关闭DNS预解析,通过第一句强制打开a标签的预解析。
2.让页面渲染更快
3.节流和防抖
防抖(debounce)
函数防抖: 指触发事件后在规定时间内函数只能执行一次,如果在规定时间内又触发了事件,则会重新计算函数执行时间。
场景:监听一个输入框,文字变化后触发 change 事件,直接用keyup事件,则会频繁触发change 事件。使用防抖
:用户输入结束或暂停时,才会触发change 事件
debounce.js
let input = document.getElementById("the_input");
//自定义防抖函数
function debounce(fn, delay = 100) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
}
}
input.addEventListener("keyup", debounce(function (e) {
console.log(e.target);
console.log(input.value);
}, 600));
节流(throttle)
节流:限制一个函数在规定时间内只能执行一次。
场景1:拖拽一个元素时,要随时拿到该元素被拖拽的位置。直接用drag 事件,则会频繁触发,很容易导致卡顿。使用节流
:无论拖拽速度多快,都会每隔100ms 触发一次。
场景2:高频点击提交,表单重复提交。
throttle.js
const div1 = document.getElementById('div1')
// 自定义节流
function throttle(fn, delay = 100) {
let timer = null
return function () {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
div1.addEventListener('drag', throttle(function (e) {
console.log(e.offsetX, e.offsetY)
}))
错误监控
错误的捕获方式
1.代码错误
try-catch
try-catch
只能捕获到运行时的非异步错误,而语法错误和异步错误就捕捉不到。比较消耗性能,少用。
window.onerror
当有javaSript脚本运行错误或者资源<img>、<script>加载失败时,都会触发Event接口的error事件
//方式一:
window.onerror = function(error) {
console.log(error);
return true;
}
//方式二:
window.addEventListener('error', (error) => {
console.log(error);
return true;
}, true);
window.onerror只有在返回true时,异常才不会向上抛出,原理是冒泡机制。
window.onerror是无法捕获到网络异常的。
2.资源加载错误
1) object.onerror
2) performance.getEntries()//获取所有已加载资源的加载时长===间接获取没有加载资源的错误。
3) Error事件捕获
跨域的js错误
所有跨域文件的js错误信息:Script error
。
处理方式:
1、在script标签增加 crossorigin属性
2、设置js资源响应头Access-Control-Allow-Origin:*
这样就可以拿到详细的错误信息了。
上报错误的基本原理?
1、采用Ajax通信的方式上报
2、利用Image对象上报(是所有监控体系都在做的事)
<script>
(new Image()).src = "http://vaidu.cpm";
</script>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。