- 有几种方式可以实现存储功能,分别有什么优缺点,什么是 Service Worker?
特性 | cookie | localStorage | sessionStorage | indexDB |
---|---|---|---|---|
数据生命周期 | 一般由服务器生成,可以设置过期时间 | 除非被清理,否则一直存在 | 页面关闭就清理 | 除非被清理,否则一直存在 |
数据存储大小 | 4K | 5M | 5M | 无限 |
与服务端通信 | 每次都会携带在 header 中,对于请求性能影响 | 不参与 | 不参与 | 不参与 |
IndexedDB是为了能够在客户端存储大量的结构化数据,并且使用索引高效检索的API。
- Service Worker
是运行在浏览器背后的独立线程,一般可以用来实现缓存功能,因为 Service Worker 中涉及到请求拦截,所以必须使用 HTTPS 来保证安全
实现步骤:
- 注册 Service Worker
- 监听 install 事件后缓存需要的文件
- 下次用户访问的时候通过拦截请求的方式查询是否存在缓存,如果存在直接读取缓存文件,否则去请求数据
// 代码实现如下:
// index.js
if(navigator.serviceWorker) {
navigator.serviceWorker
.register('sw.js')
.then(function(registration) {
console.log('Service Worker 注册成功')
})
.catch(function(error) {
console.log('Service Worker 注册失败')
})
}
// sw.js 监听 install 事件,回调中缓存所需文件
self.addEventListener('install', e => {
e.WaitUtil(
caches.open('my-cache').then(function(cache) {
return cache.addAll(['./index.html', './index.js'])
})
)
})
// 拦截所有请求事件,如果缓存中有请求的数据直接使用,否则去请求数据
self.addEventListener('fetch', e => {
e.responseWith(
caches.match(e.request).then(function(response) {
if(response) {
return response
}
console.log('fetch source')
})
)
})
浏览器缓存
-
优化缓存可以显著减少网络传输所带来的损耗
对于一个数据请求来说,可以分为发起网络请求,后端处理数据,浏览器响应三个步骤。浏览器缓存可以帮助我们在第一、三步中优化性能,如果浏览器中有缓存就不发起请求,发起了请求如果后端数据和前端缓存数据一致也没有必要将数据传回来,这样就减少了响应数据 -
浏览器的缓存位置根据优先级
- Service Worker
- Memory Cache
内存中的缓存,读取高效、持续时效短,会随着进程释放而释放 - Disk Cache
硬盘中的缓存,对比 Memory Cache 读取速度慢但是容量大存储时效长 - Push Cache
HTTP/2 中的内容,时效短只在会话 Session 中存在,一旦会话结束就会被释放 - 网络请求
一般来说现在都会运用工具进行打包,我们可以对文件进行 hash 处理,只有当代吗修改后才会生成新的文件名,文件名改变才会去下载最新的代码文件,否则一直使用缓存。
浏览器渲染原理
- 接收 html 文件并解析成 dom 树
- 接受 css 文件并解析成 cssom 树
- 将 dom 和 cssom 合并生成 Render Tree
- Layout 环节,浏览器出计算各个节点的位置
- Painting 到屏幕上
- 重绘 RePaint 节点需要更改外观而不影响布局的,比如改变 color
- 回流 ReFlow 布局或者几何属性需要改变
减少重绘和回流
- 使用 transform 代替定位改变 top
<div class="test"></div>
<style>
.test {
position: absolute;
top: 10px;
width: 100px;
height: 100px;
background: red;
}
</style>
<script>
setTimeout(() => {
// 引起回流
document.querySelector('.test').style.top = '100px'
}, 1000)
</script>
- 使用 visibility 代替 display:none 因为前者只会引发重绘,而后者因为改变了布局而引发回流
- 不要把节点的属性放在一个循环里,当成循环的变量
for(let i = 0; i < 1000; i++) {
// 获取 offsetTop 会导致回流,因为需要去获取正确的值
console.log(document.querySelector('.test').style.offsetTop)
}
- 动画实现速度的选择,动画速度越快回流次数越多,可以选择使用 requestAnimationFrame
- css 选择符从左往右查找避免层级过多
- 将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点。比如对于 video 标签来说,浏览器会自动将该节点变为图层。
我们可以通过 will-change 属性 video、iframe 标签生成新图层
- 提示如何加速:
1.从文件大小考虑
2.从 script 标签使用上来考虑,当 script 标签加上 defer 属性以后,表示该 JS 文件会并行下载,加上 async 属性,表示 JS 文件下载和解析不会阻塞渲染。
3.从 CSS、HTML 的代码书写上来考虑
4.从需要下载的内容是否需要在首屏使用上来考虑
网友评论