Headless WordPress REST API响应过慢(JavaScript):如何优化?
嘿,我完全懂你的感受——650ms的响应虽然没到不能用的地步,但静态站点本该给人“秒开”的爽感,这个延迟确实会拉低用户体验。既然没法修改后端PHP代码,咱们就把注意力放在客户端JavaScript层面,给你几个立竿见影的优化思路:
1. 给请求结果加客户端缓存
WP API返回的内容大多不会实时高频更新,把响应数据存在localStorage或者sessionStorage里,下次请求先读缓存,只有缓存过期或者不存在时才发起新请求,能直接砍掉大部分重复请求的耗时。
举个简单的实现例子:
async function fetchWPPosts() { const cacheKey = 'wp_posts_cache'; const cacheExpiry = 3600000; // 1小时,根据内容更新频率调整 // 先检查缓存 const cachedData = localStorage.getItem(cacheKey); if (cachedData) { const { data, timestamp } = JSON.parse(cachedData); if (Date.now() - timestamp < cacheExpiry) { return data; // 直接用缓存数据 } } // 缓存失效,发起新请求 const response = await fetch('https://your-wp-site/wp-json/wp/v2/posts'); const data = await response.json(); // 把新数据存入缓存 localStorage.setItem(cacheKey, JSON.stringify({ data, timestamp: Date.now() })); return data; }
2. 只请求你需要的字段
WordPress API默认会返回一大堆你根本用不上的字段(比如作者的所有信息、文章的各种元数据),传输这些冗余数据会增加响应时间。用_fields参数指定只获取需要的字段,能大幅减少数据传输量。
比如你只需要文章ID、标题、内容和发布日期:
fetch('https://your-wp-site/wp-json/wp/v2/posts?_fields=id,title,content,date') .then(res => res.json()) .then(data => { /* 处理数据 */ });
如果需要自定义字段,也可以把它们加进去,比如_fields=id,title,meta.my_custom_field。
3. 利用HTTP缓存头做条件请求
即使没法改后端,你也可以借助服务器返回的ETag或Last-Modified头来做条件请求。如果内容没有变化,服务器会返回304 Not Modified,不用传输完整数据,能省不少时间。
实现方式示例:
async function fetchWPPostsWithConditionalRequest() { const storedETag = localStorage.getItem('wp_posts_etag'); const headers = {}; if (storedETag) { headers['If-None-Match'] = storedETag; } const response = await fetch('https://your-wp-site/wp-json/wp/v2/posts', { headers }); if (response.status === 304) { // 内容没变化,用之前的缓存数据 return JSON.parse(localStorage.getItem('wp_posts_data')); } else { // 内容更新了,存新的ETag和数据 const etag = response.headers.get('ETag'); const data = await response.json(); localStorage.setItem('wp_posts_etag', etag); localStorage.setItem('wp_posts_data', JSON.stringify(data)); return data; } }
4. 并行请求或批量获取数据
如果需要同时获取多种数据(比如文章列表+分类信息),别串行发起请求,用Promise.all()并行处理,能把总等待时间降到最长的那个请求的耗时。另外,WP API支持用include参数一次性获取多个ID的文章,避免多次请求:
并行请求示例:
const postsUrl = 'https://your-wp-site/wp-json/wp/v2/posts'; const categoriesUrl = 'https://your-wp-site/wp-json/wp/v2/categories'; Promise.all([fetch(postsUrl), fetch(categoriesUrl)]) .then(([postsRes, catsRes]) => Promise.all([postsRes.json(), catsRes.json()])) .then(([posts, categories]) => { // 同时拿到文章和分类数据 });
批量获取文章示例:
// 一次性获取ID为1、3、5的文章 fetch('https://your-wp-site/wp-json/wp/v2/posts?include=1,3,5') .then(res => res.json()) .then(data => { /* 处理数据 */ });
5. 给用户触发的请求加防抖/节流
如果你的请求是用户操作触发的(比如搜索框输入、筛选按钮点击),加个防抖或节流函数,避免短时间内重复发起请求,减少不必要的API调用。
简单的防抖函数实现:
function debounce(func, delay = 300) { let timeoutId; return function(...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; } // 防抖后的搜索请求 const debouncedSearch = debounce(async (searchTerm) => { const response = await fetch(`https://your-wp-site/wp-json/wp/v2/posts?search=${searchTerm}`); const data = await response.json(); // 更新搜索结果 }); // 用户输入时调用防抖后的函数 searchInput.addEventListener('input', (e) => debouncedSearch(e.target.value));
这些方法都是纯客户端JS就能实现的,不需要改动后端代码。优先试试缓存和字段过滤,这两个优化的见效最明显,应该能把响应时间压到更舒服的范围。
内容的提问来源于stack exchange,提问作者David

