前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Next.jsSSR页面缓存

Next.jsSSR页面缓存

作者头像
用户6256742
发布2022-07-06 14:58:57
3.5K0
发布2022-07-06 14:58:57
举报
文章被收录于专栏:网络日志

背景

SSR相对于静态页面是非常消耗服务器资源的,所以在网站访问量较大时通常会将前端页面进行缓存,在Next.js中我们需要渲染AJAX的内容需要在前端使用getServerSideProps进行动态内容的渲染。很多网页的数据变化不是很频繁通常不需要每次都发起请求和渲染,所以本文来讲解如何缓存Next.js渲染的SSR页面。如果有同学不清楚服务器缓存的原理可以看之前发布的Express使用服务端缓存

Next.js内置的SSR本身不提供内置的缓存方案(有兴趣同学可以了解一下ISR),但是提供了一个自定义服务器方案,我们可以自己来设置启动和网站进入到返回渲染结果的流程。

安装插件

自定义缓存使用Express来做路由系统,使用lru-cache做缓存

代码语言:javascript
复制
npm i express lru-cache nodemon
//or
yarn add express lru-cache nodemon

编写

1.首先在根目录下创建一个server.js文件(命名不固定,别的也行)

2.代码:

代码语言:javascript
复制
const express = require('express');
const next = require('next');
const LRUCache = require('lru-cache');

const port = 5678; //端口
const isDev = process.env.NODE_ENV === 'development';
const app = next({
    dev: isDev
});

// nextjs原生请求处理函数
const handle = app.getRequestHandler();

// 缓存工具初始化
const ssrCache = new LRUCache({
    max: 100,
    ttl: 1 * 60 * 60 * 1000, // 1小时缓存
});

//渲染和处理缓存
function renderAndCache(req, res) {
    let pagePath = req.path;
    let queryParams = req.query;
    const key = req.url;
    // 如果缓存中有直出的html数据,就直接将缓存内容响应给客户端
    if (ssrCache.has(key)) {
        res.send(ssrCache.get(key));
        return
    }
    // 如果没有当前缓存,调用renderToHTML生成直出html
    app.renderToHTML(req, res, pagePath, queryParams)
        .then((html) => {
            if (res.statusCode === 200) {
                // 使用缓存工具将html存放
                ssrCache.set(key, html);
            } else {
                ssrCache.delete(key);
            }
            // 响应直出内容
            res.send(html);
        })
        .catch((err) => {
            app.renderError(err, req, res, pagePath, queryParams)
        })
}
async function main() {
    await app.prepare(); //准备(初始化)

    const server = express();
    server.listen(port, (err) => {
        if (err) throw err;
        console.log(`>开始运行于: http://localhost:${port}`);
    });

    //对哪些页面进行缓存
    server.get('/article/*', (req, res) => renderAndCache(req, res));
    server.get('*', (req, res) => handle(req, res));
}
main()

讲解

主要流程也十分简单,使用缓存插件并且配置好,在每次被访问时判断缓存中是否存在,如果存在就返回缓存中的内容,如果不存在,就返回实时渲染的内容,并且缓存起来。

我在项目中使用,基本就是这个样子,我在项目中只对/article/*路径进行了缓存。对于_next路径的静态文件或者public下的图片不要和缓存路由重合。需要使用handle函数进行渲染(handle函数是Next.js内置的服务器渲染函数)

例:

代码语言:javascript
复制
server.get('/robots.txt', (req, res) => handle(req, res));

package.json配置

代码语言:javascript
复制
  "scripts": {
    "dev": "cross-env NEXT_PUBLIC_ENV=development next dev -p 5678",
    "dev:cache": "cross-env NEXT_PUBLIC_ENV=development nodemon server.js",
    "build": "cross-env NEXT_PUBLIC_ENV=production next build",
    "build:test": "cross-env NEXT_PUBLIC_ENV=development next build",
    "start": "cross-env NEXT_PUBLIC_ENV=production nodemon server.js",
    "start:no-cache": "cross-env NEXT_PUBLIC_ENV=production next start -p 5678",
    "start:test": "cross-env NEXT_PUBLIC_ENV=development next start -p 5678",
    "analyze": "cross-env ANALYZE=true next build",
    "analyze:server": "cross-env BUNDLE_ANALYZE=server next build",
    "analyze:browser": "cross-env BUNDLE_ANALYZE=browser next build"
  },

我在package中设置了很多命令,开发、打包、启动运行、统计。其中包括了测试环境的打包和运行,以及两个环境的统计。server.js中的代码我使用dev:cache来启动。需要注意的是我设置环境变量使用的是NEXT_PUBLIC_ENV而非NODE_ENV,server.js中是我为了迎合默认变量名而修改的,如果你复制package.json的代码记得修改一下,以便统一环境变量

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档