多层缓存协同工作流程
这三层缓存会像洋葱一样,从外到内,逐层保护您的应用:
第一层:CDN/浏览器缓存 (HTTP 缓存) - 最外层,离用户最近,也是最快的。
第二层:页面级缓存 (服务器内存) - 当CDN缓存未命中时,由您的服务器快速响应。
第三层:组件级缓存 (Vue SSR) - 当页面缓存也未命中时,在渲染新页面时尽可能复用组件,加快渲染速度。
const Koa = require('koa');const path = require('path');const Router = require('koa-router');const {
createBundleRenderer
} = require('vue-server-renderer');const {
LRUCache
} = require('lru-cache'); // 引入 lru-cache
// --- 1. 初始化所有缓存实1例 ---
// a. 用于组件级缓存const componentCache = new LRUCache({max: 1000,ttl: 1000 * 60 * 5, // 缓存5分钟});
// b. 用于页面级缓存const pageCache = new LRUCache({max: 100,ttl: 1000 * 60, // 缓存1分钟});
// ... (devConfig, PORT, app, router 等初始化) ...const devConfig = require('./build/dev.config.js');const PORT = 3003;let renderer;const app = new Koa();const router = new Router();
// --- 2. 注入组件级缓存 ---const createRenderer = (bundle, options) => {
renderer = createBundleRenderer(
bundle,
Object.assign(options, {
runInNewContext: false,
cache: componentCache, // 注入组件缓存
}));};
if (process.env.NODE_ENV === 'production') {const template = require('fs').readFileSync('./src/index.template.html', 'utf-8');const serverBundle = require('./dist/vue-ssr-server-bundle.json');const clientManifest = require('./dist/vue-ssr-client-manifest.json');createRenderer(serverBundle, {
template,
clientManifest,});} else {const template = path.resolve(__dirname, './src/index.template.html');devConfig(app, template, (bundle, options) => {
createRenderer(bundle, options);});}// --- 3. 实现页面缓存和HTTP缓存头的中间件 ---const render = async (ctx, next) => {const url = ctx.url;
// 设置HTTP缓存头,对所有请求生效// public: 响应可以被CDN等中间缓存存储// max-age=300: 缓存有效期5分钟
ctx.set('Cache-Control', 'public, max-age=300');
// 检查页面缓存const cachedPage = pageCache.get(url);if (cachedPage) {
console.log(`[Page Cache HIT] for ${url}`);
ctx.set('Content-Type', 'text/html');
ctx.body = cachedPage;
return next();}
console.log(`[Page Cache MISS] for ${url}`);
// 页面缓存未命中,执行渲染
ctx.set('Content-Type', 'text/html');const context = {
url: url,
title: '服务端渲染',
meta: `
`,};
try {
// 调用 renderToString 时,组件级缓存会自动生效
const html = await renderer.renderToString(context);
ctx.body = html;
// 将新渲染的页面存入缓存
pageCache.set(url, html);} catch (err) {
console.log(err);
ctx.status = 500;
ctx.body = 'Internal Server Error';}next();};
router.get('*', render);
app.use(router.routes()).use(router.allowedMethods());
app.listen(PORT, () => {
console.log(`server started at http://localhost:${PORT}`);});
确认评论邮箱
邀请制评论