性能优化
可以以web的生命周期为切入点
加载阶段
提升资源加载速度
- 使用Preload、DNS Prefetch等,关键资源提升加载优先级
- 最基本的使用CDN
- 使用浏览器缓存,设置强缓存、协商缓存
- js、css、图片资源的压缩,可以使用雪碧图、base64等,同时也可以拼接oss参数,按需使用。
- js适当分包,减少不必要的js的请求的同时,也可以利用浏览器的并发请求,提升加载速度。
- 减少不必要的请求,比如说图片懒加载、懒加载、按需加载等。
提升DOM的渲染解析速度
- css选择器、DOM的深度不要太深
- script标签放在body底部,或者使用defer、async异步加载
- css放在head里
运行时
- 减少重排重绘,比如说使用transform代替top、left等,媒体资源宽高固定
- 不用的实例即时销毁,避免内存泄漏
- 节流、防抖
- 使用requestAnimationFrame、requestIdleCallback等,减少主线程的压力
- 避免 async await 使用不当,阻塞后面的代码执行
引入第三方机制
- 使用web worker、webAssembly等,做复杂的计算,减少主线程的压力
- 使用 PWA、serviceWorker 支持离线缓存和访问,
- 使用离线包机制,首先后台维护包的上传、版本管理等。端侧首次打开时,会请求下发打包后生成的文件包,然后通过file协议或者本地启个代理服务器来跑。包版本更新时,对包内文件进行差分diff,增量更新。
- SSR
引申
Web Worker
Web Worker 它允许在浏览器后台,独立于主执行线程运行 JavaScript。这意味着可以执行复杂的计算或处理大量数据,而不会阻塞 UI 或用户交互。
需要注意的是,Web Worker 不能访问 DOM,也不能使用某些与窗口或者文档相关的 JavaScript API,因为它们在主线程之外运行。但是,它们可以使用网络请求(XMLHttpRequest 和 Fetch)、定时器(setTimeout 和 setInterval)、以及其他一些功能。
以下是一个使用 Web Worker 计算斐波那契数列的例子:
// 创建一个新的 Worker
const worker = new Worker('worker.js');
// // 向 Worker 发送数据
worker.postMessage(10);
// worker.js
self.onmessage = function(event) {
var n = event.data;
var result = fibonacci(n);
self.postMessage(result);
};
function fibonacci(n) {
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
Service Worker
Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能,以及离线运行等。
Service Worker 作为一种浏览器技术,其生命周期与页面分离,因此可以在页面关闭后继续运行。这使得 Service Worker 可以实现离线缓存、消息推送等功能。
// 在主线程中注册 Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js').then(function(registration) {
console.log('Service Worker 注册成功');
}).catch(function(err) {
console.log('Service Worker 注册失败:', err);
});
}
// service-worker.js
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('my-cache').then(function(cache) {
return cache.addAll([
'/',
'/index.html',
'/styles.css',
'/script.js',
'/logo.png',
]);
})
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
WebAssembly
WASM 是二进制文件,作为一种低级虚拟机,能够更接近硬件,从而实现更高的执行效率。
WASM运行时包括模块、内存、表格、全局变量等组件。其中,模块是WASM的基本单位,包含了函数、数据段等信息。内存和表格则用于在WASM与JavaScript之间共享数据。全局变量则为WASM提供了一种在模块间共享状态的机制。
优势:
- 高性能:WASM代码更接近硬件层,因此在执行效率上优于JavaScript。此外,WASM支持线性内存和表格等数据结构,可以显著提高数据处理速度。
- 可移植性:WASM作为一种通用的二进制代码格式,可以被多种编程语言(如C、C++、Rust等)编译生成。这意味着开发者可以使用自己熟悉的语言来编写高性能的Web应用。
- 安全性:WASM运行在一个沙箱环境中,确保了代码的安全执行。同时,WASM的类型系统和结构化控制流提高了代码的可靠性。
应用场景:
- 图形渲染:WASM可以有效提高图形渲染速度,尤其在3D渲染、游戏开发等领域具有显著优势。
- 音频处理:WASM可以实现实时音频处理,为音频合成、音频编辑等应用提供高性能解决方案。
- 数据压缩与解压:利用WASM优化数据压缩和解压算法,提高在Web应用中处理大数据的速度。
- 机器学习:WASM可以为机器学习模型提供高效的运行环境,降低模型在浏览器中的运行成本。
SSR
概念:通过在服务器端将应用程序渲染成HTML等静态资源,然后将这些资源发送到客户端进行展示。
优点:提高应用程序的性能和搜索引擎优化(SEO),提高首次加载速度和可访问性等。
vue ssr做的是在页面中请求url的时候,会从服务端渲染返回一个渲染好的html字符串,将首屏所需要的数据异步请求,填充发到前端展示,而不是发一个壳子,ssr是一份代码运行在两个环境里面(服务端、客户端),服务端先运行好之后,把模板渲染成html页面,然后返回给前端,前端再载入js文件,完成激活,后续的操作就是spa了,这样第一个页面是服务端渲染的带数据的,seo爬虫就能获取到数据,同时因为首屏只渲染一个页面,后续激活spa是发生在浏览器端,首屏渲染问题也得到解决。
实现方式:模板引擎或React/Vue等框架的服务器端渲染功能,或使用Node.js等后端技术等。
注意事项: 1、避免使用浏览器特定的API 代码是在服务器端执行的,因此不能使用浏览器特定的API,如window、document等。需要使用其他适合在服务器端执行的替代方案。
应用场景:比如电商网站、新闻网站等需要SEO优化的网站,或对首屏渲染速度有要求的应用程序。
预加载&预请求
预加载: 客户端开一个webview预加载url。做的更深入一点,可以后台维护一个表,有一个url的资源映射,和相应的加载时机。客户端冷启动时,拿到这个数据,在相应时间使用webview加载这些资源。 预请求:还是一个表。一个url的接口请求映射。当打开这个url的webview时,端侧同时请求接口。将接口数据存下来,webview加载后,发起请求,端侧将该数据返回。
长列表滚动
虚拟无限列表:只渲染可视区域内的列表项,当向上或向下滚动时,重新计算显示的列表项,同时移除原来不再显示的项。这种方法可以显著减少DOM节点数量,优化页面性能。
Intersection Observer API 实现:这个API是H5提供的一种可以监听元素与父容器或viewport的交叉状态的接口。