• 博客
  • 项目
  • 碎碎念
  • 留言板
  • 关于我
服务端渲染缓存处理
更新时间:2025/07/02 分类:编程技术
多层缓存协同工作流程

这三层缓存会像洋葱一样,从外到内,逐层保护您的应用:

第一层: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}`);
});

服务端渲染
联系我