前言
当你打开开发者工具,看到瀑布流里密密麻麻的接口请求时------血压是不是瞬间拉满?前端性能被拖垮、页面卡成PPT、用户疯狂流失...
正文
🚀 请求并发控制
1、并行请求队列
javascript
// 请求队列类
class RequestQueue {
constructor(maxConcurrent = 5) {
this.maxConcurrent = maxConcurrent; // 设最大并发请求数为5
this.queue = []; // 用于存储待处理的请求队列
this.activeCount = 0; // 当前正在处理的请求数
}
add(requestFn, priority = 0) {
return new Promise((resolve, reject) => {
this.queue.push({ requestFn, resolve, reject, priority });
this.queue.sort((a, b) => b.priority - a.priority); // 优先级排序
this._next();
});
}
_next() {
while (this.activeCount < this.maxConcurrent && this.queue.length) {
const { requestFn, resolve, reject } = this.queue.shift();
this.activeCount++;
requestFn()
.then(resolve)
.catch(reject)
.finally(() => {
this.activeCount--;
this._next();
});
}
}
}
// 使用示例
const apiQueue = new RequestQueue(5); // 最大并发5
apiQueue.add(() => fetch('/api/user'), 10); // 高优先级
apiQueue.add(() => fetch('/api/products'), 1); // 低优先级
优化要点:
- 可配置的并发数量(通常建议4-6个)
- 基于优先级的请求调度
- 自动队列管理,无需手动控制
2、智能权衡优先级
关键请求优先 :首屏 数据 > 次要 数据 > 后台预加载
依赖关系处理 :建立请求依赖图,确保顺序执行
🚀 缓存
1、内存
javascript
const apiCache = new Map();
function cachedFetch(url, options = {}) {
const { ttl = 60000 } = options; // 默认缓存1分钟
const cacheKey = generateCacheKey(url, options);
if (apiCache.has(cacheKey)) {
const { data, timestamp } = apiCache.get(cacheKey);
if (Date.now() - timestamp < ttl) {
return Promise.resolve(data);
}
}
return fetch(url, options)
.then(res => res.json())
.then(data => {
apiCache.set(cacheKey, { data, timestamp: Date.now() });
return data;
});
}
function generateCacheKey(url, options) {
return `${options.method || 'GET'}:${url}:${JSON.stringify(options.body)}`;
}
2、智能权衡缓存
IndexedDB持久化缓存 :
大容量数据存储
长期缓存解决方案
CDN边缘缓存 :
配置适当的Cache-Control头
对静态API响应启用CDN缓存
🚀 中间层(BFF)
1、nodejs来做(前端开发人员,有些公司是后端来搭中间层的,不过前端也可以搭,具体情况具体分析)。
bff(英文叫 backend for frontend,中文翻译:
服务于前端的后端
)。
前端用nodejs
来写再合适不过了。
实话说这玩意就是,方便我们前端去自由地 优化性地 去组装后端接口返回来给我们的数据
,可能后端有时候返回来的数据比较随心所欲,我们前端得到数据后就需要大量地大规模地进行各种组装,各种洗数据。
有时候,前端和后端,后端和前端之间的沟通导致口角扯皮等等导致效率降低,还不如前端自行地去决定
数据的各种结构和形态。
所以出现了bff
。
像
ssr
(服务端渲染),返回整个页面的html字符串,浏览器直接显示就好了,不用再经过js各种组装各种render等等,ssr它自己在服务器端直接就渲染好了,一次性打包给前端,可能说到这里,你很熟悉了,没错就是seo 首屏加载的优先选择方案
。
这里呢,如果是前端的小伙伴,要做bff,那么也就是说要做部分后端的工作了,推荐使用nodejs去做。nodejs 服务框架推荐用:express
、Koa
、egg
等等。自行去查看哈。
js
客户端 → BFF → 微服务A
→ 微服务B
→ 微服务C
核心功能 :
接口聚合:合并
多个微服务
调用
数据转换:前端所需的数据格式处理
协议转换:GraphQL/RESTful
适配
2、接口聚合
javascript
// BFF路由示例
router.get('/user-dashboard', async (ctx) => {
const [user, orders, messages] = await Promise.all([
userService.getUser(ctx.userId),
orderService.getRecentOrders(ctx.userId),
messageService.getUnreadMessages(ctx.userId)
]);
ctx.body = {
user,
lastOrders: orders.slice(0, 5),
unreadCount: messages.length
};
});
3、GraphQL配置
graphql
query {
user(id: "123") {
name
email
posts(limit: 5) {
title
comments {
count
}
}
}
}
按需获取数据
减少网络往返
🚀 协议
1、HTTP/2
多路复用 :同域名下所有请求共享一个TCP连接
头部压缩 :减少重复头部传输
服务器推送:主动推送相关资源
2、域名分片
html
<!-- 静态资源分片 -->
<img src="https://static1.example.com/image1.jpg">
<img src="https://static2.example.com/image2.jpg">
<!-- API端点分片 -->
<script>
const API_ENDPOINTS = [
'https://api1.example.com',
'https://api2.example.com'
];
</script>
3、数据压缩
Brotli压缩:比gzip更高的压缩率
nginx
# Nginx配置
brotli on;
brotli_types application/json;
图片等数据压缩: 图片转成data_url、js压缩(丑化处理)
总结
记住,没有放之四海皆准的完美方案,只有最适合当前业务场景的解决方案。