如何在Strapi中实现缓存、添加缓存控制头及数据库索引?
Strapi REST API缓存实现与数据库索引优化方案
一、REST API缓存实现(含缓存控制头)
Strapi面板没有直接添加缓存控制头的入口,需通过自定义中间件或服务实现:
1. 全局添加缓存控制头
- 在
src/middlewares/cache-control.js创建中间件文件:
module.exports = (strapi) => { return { initialize() { strapi.app.use(async (ctx, next) => { await next(); // 仅对GET请求设置缓存头,可按需调整缓存时长和规则 if (ctx.method === 'GET') { ctx.set('Cache-Control', 'public, max-age=3600'); // 缓存1小时 } }); }, }; };
- 在
config/middleware.js中注册该中间件,确保执行顺序合理:
module.exports = { load: { before: ['strapi::errors', 'strapi::security'], order: ['cache-control', 'strapi::body', 'strapi::session', 'strapi::favicon', 'strapi::public'], after: ['strapi::logger', 'strapi::query'], }, };
2. 进阶:Redis缓存API响应
针对频繁查询的接口,可实现响应内容缓存,提升性能:
- 安装Redis依赖:
npm install redis - 创建缓存服务
src/services/cache.service.js:
const redis = require('redis'); const client = redis.createClient({ url: 'redis://localhost:6379' }); client.connect().catch(console.error); module.exports = ({ strapi }) => ({ async get(key) { const value = await client.get(key); return value ? JSON.parse(value) : null; }, async set(key, value, ttl = 3600) { await client.setEx(key, ttl, JSON.stringify(value)); }, async del(key) { await client.del(key); }, });
- 在控制器中使用缓存(以文章列表接口为例,
src/api/post/controllers/post.js):
module.exports = { async find(ctx) { const cacheKey = `posts:${JSON.stringify(ctx.query)}`; const cachedData = await strapi.service('cache').get(cacheKey); if (cachedData) { ctx.body = cachedData; return; } const data = await strapi.entityService.findMany('api::post.post', { ...ctx.query, }); await strapi.service('cache').set(cacheKey, data); ctx.body = data; }, };
- 注意:在数据创建/更新/删除时,需清理对应缓存,避免返回旧数据。
二、数据库索引添加优化
Strapi无面板操作索引的功能,可通过以下两种方式实现:
1. 模型配置自动生成索引
在模型的schema.json中,给目标字段添加index: true,重启Strapi后会自动在数据库创建索引:
{ "attributes": { "title": { "type": "string", "index": true // 单字段索引 }, "category": { "type": "relation", "relation": "manyToOne", "target": "api::category.category", "index": true // 关联字段索引 } } }
2. 手动创建复合索引
如需多字段组合索引,直接通过数据库客户端执行SQL:
- PostgreSQL:
CREATE INDEX idx_posts_title_category ON posts (title, category_id);
- MySQL:
CREATE INDEX idx_posts_title_category ON posts (title, category_id);
索引优化建议
- 优先给
WHERE、JOIN、ORDER BY语句中频繁出现的字段加索引 - 避免给高频更新的字段添加过多索引,否则会影响写入性能
- 定期用数据库分析工具(如PostgreSQL的
EXPLAIN)排查慢查询,针对性优化索引
内容的提问来源于stack exchange,提问作者Nitin Dutta
相关产品推荐
相关产品推荐

