思涯谷

  • 首页
  • 探索
  • 标签
  • 关于
思涯谷 ©2025
京ICP备2022030312号GitHub User's stars

Next.js笔记:缓存、缓存和缓存

随着vercel挖走react核心团队,服务端渲染已成为react的事实标准。nextjs@15引进的"use cache",很有可能成为下一代React的规范设计模式。React带来了自由度极高的前端构建模式,接踵而至的便是一系列rerender等性能灾难问题。

...
标签:全栈开发Next.jsReact
点赞(0)
返回顶部

相关内容

  • Taro和JS笔记系列
  • VSCode笔记
  • 面试笔记
2024-12-26
Next.js笔记:缓存、缓存和缓存
Next.js笔记:缓存、缓存和缓存

留言

路由

  1. App模式的api与Page模式不同,请查阅官方文档,建议使用App router。

缓存

  1. 使用import { cache } from "react"或fetch可以避免generateMetadata和default重复发送请求。在nextjs15中,可以使用"use cache"。
  2. 使用revalidatePath("/", "layout")可以立即重新构建所有页面缓存,但revalidateTag(·)只会让缓存失效,并不会(也不能)立即构建所有相关函数。
  3. nginx设置静态资源的强缓存
# 上传目录,全是静态文件
location /uploads/ {
    alias /app/public/uploads/;
    try_files $uri @nextjs;
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# 对css、图片和字体等进行强缓存
location ~ ^/_next/static/(.*\.(css|jpg|jpeg|avif|png|webp|gif|svg|ico|woff2))$ {
    alias /app/runtime/.next/standalone/.next/static/$1;
    try_files $uri $uri/ @nextjs;
    expires 1y;
    add_header Cache-Control "public, immutable";
}

样式

  1. 使用.markdown-body,.markdown-body * { all: revert;}可以撤销所有tailwindcss的样式。
  2. 在css中使用@import "@/assets/(...).module.css";可以实现将Module CSS当全局CSS用。

部署

  1. 官方文档的编译部分异常简陋,是nextjs官方有意而为之,为的是让nextjs用户倾向于使用vercel进行部署。
  2. 在所有的静态路由页面下,如果涉及到访问数据库的地方,请考虑将页面分割成多个部分,将数据库依赖的组件进行抽离,从而保证其他部分能够被静态化处理。若编译阶段无法访问数据库操作,请使用try {return getDataFromDB()} catch{return []}类似的写法。
  3. 降低数据库连接超时时间,以防编译阶段超时。
  4. 编译成standalone时,需要处理static目录:
COPY --from=builder /app/.next/standalone ./.next/standalone
COPY --from=builder /app/.next/static ./.next/standalone/.next/static
  1. 编译时所有的process.env.xxx会被编译器替换成环境变量。若xxx以NEXT_PUBLIC开头,则会在客户端组件和服务端组件均生效,否则会在客户端组件中仅使用运行时的环境变量。

后端

  1. 同上,所有process.env.xxx的变量,会在编译阶段替换成常量,因此动态配置可以通过数据库+缓存来实现。
  2. nextjs的runtime分为edge和node,总体上类似于serverless模式,需要和一般的服务端区分开,因此定时任务和消息队列考虑使用额外的脚本实现,通过pm2进行管理。
  3. Mongoose表存在依赖关系的话,需要在数据库初次连接时动态导入:
export default async function Init() {
  // 数据库初始化
  console.log("Database connected. Start initializing...")
  // 导入有可能被引用的模型
  await import("@/models/user")
  await import("@/models/post")
  await import("@/models/tag")
  await import("@/models/session")
  await import("@/models/comment")
}
  1. 在服务端使用一些common node库时,需要将其标记为External,即:
/* next.config.js */
{
  ...
  serverExternalPackages: ["mongoose", "@node-rs/jieba", "ip2region"]
  ...
}

反向代理

  1. nextjs下,正确使用nginx反向代理的方式:
location /_next/static/ {
        alias /app/runtime/.next/standalone/.next/static/;
        try_files $uri $uri/ @nextjs;
}

location / {
        alias /app/public/;
        try_files $uri @nextjs;
}

location @nextjs {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
}

RSS

  1. 定义generateRSS()函数,从数据库获取内容,返回rss/xml并写入到./public/rss.xml。

  2. 在编译构建阶段和内容发生变化时,调用generateRSS()重新生成rss.xml文件。

  3. 通过@/app/rss/route.ts作为rss.xml生成失败的fallback。

  4. 在nextjs的配置文件中,将动态请求/rss.xml时重写至/rss处理。

  async rewrites() {
    return {
      beforeFiles: [
        { source: "/rss.xml", destination: "/rss" },
      ]
    }
  }
  1. 在nginx的配置文件中,配置/rss和/rss.xml的请求指向/app/public/rss.xml文件,如果文件不存在再使用nextjs动态生成。
location = /rss {
    alias /home/uilq-next-app/public;
    try_files /rss.xml @nextjs;
}
location = /rss.xml {
    alias /home/uilq-next-app/public;
    try_files /rss.xml @nextjs;
}