浏览器方面:
减少HTTP请求
HTTP 请求是指客户端(例如浏览器)向服务器发出的请求消息,用于获取特定资源或执行特定操作
为什么能够优化性能?
减少网络延迟:每次发起HTTP请求都需要经过网络传输,而网络传输存在一定的延迟。当页面中存在大量的HTTP请求时,这些请求之间会产生较多的延迟,导致页面加载速度变慢。
减少服务器负载:每个HTTP请求都需要服务器处理和响应,服务器的处理能力是有限的。当页面中存在大量的HTTP请求时,服务器可能会面临较大的负载压力。
节省带宽消耗:每个HTTP请求都需要占用一定的带宽资源。
带宽是什么?
带宽指的是网络传输数据的能力,表示单位时间内从一个点到另一个点所能传输的数据量
使用HTTP2.0
HTTP/2.0(简称HTTP2)是HTTP协议的一种更新版本,它改进了旧版本的HTTP协议,提供了更快的页面加载速度和更高的效率
为什么能够优化性能?
多路复用:HTTP/2使用二进制分帧机制,允许多个请求同时在同一个连接上进行,避免了过多的连接建立和消耗,提高了请求的效率。
头部压缩:HTTP/2使用HPACK算法对请求和响应头部进行压缩,减少了数据传输的大小,降低了带宽消耗
HTTPS 不等于 HTTP2.0
HTTPS 是一种通过加密和认证来保护网络通信安全的协议,而 HTTP/2 是一种基于 HTTP 协议之上的新版本
如果想要使用 HTTP/2,必须使用 HTTPS 来保证数据传输的安全性;而HTTPS使用的是HTTP/2协议或更早版本的HTTP协议都是可能的
浏览器缓存策略
浏览器缓存一般分为两类:强缓存(也称本地缓存)和协商缓存(也称弱缓存)
强制缓存
使用 Expires
字段:设置一个未来的过期时间
使用 Cache-Control
字段:设置缓存的最大有效时间
// 设置 Expires 字段,缓存过期时间为 1 小时
response.setHeader('Expires', new Date(Date.now() + 3600000).toUTCString());// 设置 Cache-Control 字段,缓存最大有效时间为 1 小时
response.setHeader('Cache-Control', 'max-age=3600');
缓存过期时间和最大有效时间 有什么区别
当缓存过期时间和最大有效时间同时存在时,浏览器会优先使用最大有效时间(Cache-Control)来判断缓存是否有效。如果 max-age 指定的时间已过或者没有设置该字段,浏览器才会检查 Expires 字段
ajax示例:
// 发起 AJAX GET 请求,并设置强制浏览器缓存
$.ajax({
url: 'https://api.example.com/data',
type: 'GET',
cache: true, // 开启缓存
headers: {
'Expires': new Date(Date.now() + 3600000).toUTCString(),
'Cache-Control': 'max-age=3600'
},
success: function(responseData) {
// 请求成功,处理响应数据
console.log(responseData);
},
error: function(xhr, status, error) {
// 请求失败,处理错误信息
console.error('Request failed. Status:', status, 'Error:', error);
}
});
协商缓存
使用 Last-Modified
字段:服务器返回资源的最后修改时间,例如 Last-Modified: Wed, 20 Nov 2023 08:00:00 GMT
。浏览器会在后续请求中发送 If-Modified-Since
字段,表示资源的上次修改时间,服务器可以根据这个值判断是否返回新的资源
使用 ETag
字段:服务器返回资源的唯一标识符,例如 ETag: "abc123"
。浏览器会在后续请求中发送 If-None-Match
字段,表示资源的标识符,服务器可以根据这个值判断是否返回新的资源
ajax示例:
$.ajax({
url: 'https://api.example.com/data',
type: 'GET',
cache: true, // 开启缓存
headers: {
'If-Modified-Since': lastModified, // lastModified 为资源的最后修改时间
'If-None-Match': etag // etag 为资源的唯一标识符
},
success: function(responseData, textStatus, xhr) {
// 请求成功,处理响应数据
console.log(responseData);
},
error: function(xhr, status, error) {
if (xhr.status === 304) {
// 缓存命中,直接使用缓存
console.log('Cache hit.');
return;
}
// 请求失败,处理错误信息
console.error('Request failed. Status:', status, 'Error:', error);
}
});
Last-Modified 和 ETag 都是在发送请求时自动获取的
白屏时间做加载动画
资源
静态资源cdn
一种通过分布在全球不同地点的服务器来加速静态资源传输的网络服务。CDN 旨在提高静态资源(如图片、CSS、JavaScript 文件等)的加载速度和用户体验
当使用 CDN 时,静态资源会被缓存到位于全球各地的服务器节点上。当用户请求访问网站时,CDN 会根据用户的地理位置,自动选择距离用户最近的服务器节点来提供静态资源,从而减小网络延迟和提高访问速度
例如:阿里云CDN、腾讯云CDN、Fastly、Cloudflare... ...
静态资源单独域名
静态资源单独域名是指将网站中的静态资源,例如图片、样式表、JavaScript等,放在一个独立的域名下。这个独立的域名通常是通过CDN服务提供商获得的,例如阿里云CDN、腾讯云CDN、百度云加速等。
为什么有效?
静态资源单独域名可以有效地减少DNS解析和请求次数,从而加速页面加载速度。同时,将静态资源与动态内容分开存放,还可以降低源服务器负载压力,提高网站的可用性和稳定性。
gzip压缩
Gzip压缩是一种常用的数据压缩算法,用于减小文件的大小以节省网络带宽和提高传输效率;它使用了Lempel-Ziv编码算法和哈夫曼编码算法,能够在不丢失数据的前提下大幅度减小文件的大小
express代码实现 gzip压缩
const express = require('express');
const compression = require('compression');
const app = express();
// 使用compression中间件启用Gzip压缩
app.use(compression());
// 定义路由
app.get('/', (req, res) => {
// 发送响应数据
const responseData = 'Hello World!';
res.send(responseData);
});
// 启动服务器
const port = 3000;
app.listen(port, () => {
console.log(`Server is listening on port ${port}`);
});
服务端渲染(SSR)
是一种将网页内容在服务器端生成并直接发送给浏览器的技术。与传统的客户端渲染(Client-Side Rendering,CSR)相比,SSR 在服务器端处理页面的渲染,然后将最终的 HTML 内容发送给客户端,客户端只需负责显示接收到的页面
图片
字体图标代替图片图标
建议font-class 格式,方便简单
精灵图
一些带有企业特色的小图标,如淘宝购物车,笑脸娃娃,可以使用精灵图,让一张图上带有多个小图,然后使用css背景定位来显示出合适的位子,能大大减少请求
图片懒加载
图片可设置一张加载图代替,当页面在可视区域内时在替换为正真的图片
如果有首屏很大的高清图,可先渲染清晰度低的缩略图,在首页基本构建完成下一次事件循环再去替换为高清图
图片预加载
可以在window.onload之后请求一些其他地方需要的图片资源
比如我们有一个活动页使用了高清图,我们可以在它的入口前的首页就加载它,当我们进去页面时,浏览器就会从缓存里读取这张图片
代码
减少重绘回流
重绘指的是当某个元素的样式发生变化,但它的布局没有改变,浏览器会重新绘制这个元素,并更新到页面上。例如,当修改元素的颜色、背景图像、阴影等样式属性时,就会触发重绘操作。
回流(也称为重排)指的是当某个元素的尺寸、位置或布局发生变化时,浏览器需要重新计算页面中所有元素的大小和位置,然后更新到页面上。例如,当增加、删除或隐藏元素时,或者当修改元素的宽度、高度、边距、定位等样式属性时,就会触发回流操作。
代码展示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>重绘和回流示例</title>
<style>
.box {
width: 100px;
height: 100px;
background-color: red;
position: relative;
}
</style>
</head>
<body>
<div class="box"></div>
<button onclick="changeColor()">改变颜色</button>
<button onclick="changeSize()">改变尺寸</button>
<script>
function changeColor() {
const box = document.querySelector('.box');
box.style.backgroundColor = 'blue'; // 触发重绘
}
function changeSize() {
const box = document.querySelector('.box');
box.style.width = '200px';
box.style.height = '200px'; // 触发回流
}
</script>
</body>
</html>
节流、防抖
节流函数:确保在指定的时间间隔内只触发一次函数调用
防抖函数:不管如何触发,只在最后一次触发后才执行
// 节流函数
function throttle(func, delay) {
let timeoutId;
return function (...args) {
if (!timeoutId) {
timeoutId = setTimeout(() => {
func.apply(this, args);
timeoutId = null;
}, delay);
}
};
}
// 防抖函数
function debounce(func, delay) {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}