introduction

在生产环境中,做出以下努力能够提高用户的体验 ..

通常

  • 应该使用缓存
  • 确保数据以及后端部署在相同来源(同域)
  • 尽可能携带更少量的js代码
  • 延迟加载大量的js打包文件,直到它们真的需要
  • 确保日志配置
  • 确保错误处理配置
  • 配置404未发现和500页面
  • 确保你检测了性能测量
  • 运行Lighthouse用来检测性能,最佳实践,可访问性,SEO ..

为获得最佳效果,请使用 Next.js 的生产版本,并在浏览器中使用隐身功能,这样结果就不会受到扩展程序的影响

  • 回顾,审查支持的浏览器和特性
  • 提升性能 - 通过:
    • next/image以及自动图片优化
    • 自动字体优化
    • 脚本优化
  • 提升加载性能

缓存

ssr-caching 示例

缓存能够提升响应时间以及减少请求外部服务的请求数量,Next.js 自动增加了缓存请求到不可变资源请求上(例如/_next/static上的js ,css,静态图片以及其他媒体 …

  1. Cache-Control: public, max-age=31536000, immutable

Cache-Control请求头设置到next.config.js中可以在生产环境中进行覆盖确保静态的资源能够有效的缓存 …

如果你需要重新验证已经静态生成的页面的缓存,你能够在页面的getStaticProps函数中设置 revalidate,如果你使用next/image,这里也针对默认的图片优化加载器提出了特定的缓存规则 ..

注意: 当你在本地开发环境运行应用时,你的请求头会被覆盖从而阻止本地缓存 ..

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

你能够在getServerSideProps以及API 路由中使用缓存请求头来处理动态响应 …

例如使用stale-while-revalidate

  1. // This value is considered fresh for ten seconds (s-maxage=10).
  2. // If a request is repeated within the next 10 seconds, the previously
  3. // cached value will still be fresh. If the request is repeated before 59 seconds,
  4. // the cached value will be stale but still render (stale-while-revalidate=59).
  5. //
  6. // In the background, a revalidation request will be made to populate the cache
  7. // with a fresh value. If you refresh the page, you will see the new value.
  8. export async function getServerSideProps({ req, res }) {
  9. res.setHeader(
  10. 'Cache-Control',
  11. 'public, s-maxage=10, stale-while-revalidate=59'
  12. )
  13. return {
  14. props: {},
  15. }
  16. }

默认情况下Cache-Control请求头将会依赖于你的页面如何抓取的数据进行设定 …

  • 如果页面使用getServerSideProps或者getInitialProps,它将使用默认的Cache-Control请求头,由next start设置为了阻止意外的响应缓存(不应该缓存的响应 / 不能够缓存的响应) …如果当你使用getServerSideProps你想要使用不同的缓存行为,使用res.setHeader(Cache-Control,value_you_prefer) 在函数内部即可 …
  • 如果页面使用getStaticProps,它将包含一个Cache-Controlheader(s-maxage=REVALIDATE_SECONDS,stale-while-revalidate),或者 如果revalidate是没有被使用的,那么s-maxage=31536000,stale-while-revalidate作为最大缓存时间 …

上述的REVALIDATE_SECONDS 表示多少秒之后进行重新验证 …

你的部署提供器必须支持动态响应的缓存,如果你是自托管的,你需要增加类似使用Redis的key/value 存储,如果你使用Vercel,Edge 缓存工作且无需配置

那么部署提供器到底是什么呢? 留下这个疑问?

减少js 体积

为了减少发送到浏览器的js体积,你能够使用以下工具去理解在每一个js打包中包括了什么?

  • Import Cost 在vscode中显示导入包的尺寸
  • Package Phobia - 发现增加一个新的dev依赖到项目中花费了多少时间 …
  • Bundle Phobia 分析有多少依赖会增加打包尺寸
  • Webpack Bundle Analyzer - webpack 使用可交互的,可缩放的树图 输出文件的可视化尺寸
  • bundlejs 一个在线工具快速的打包并压缩你的项目,然后浏览压缩的 gzip/brotli 打包体积,并在你的浏览器上本地运行这个项目 …

pages/目录中的每一个文件将自动的进行代码分割打包到独立的js 资源集中(在next build执行时),你能够使用动态导入去懒加载组件和库,举个例子可能想要延迟加载你的弹窗代码直到用户点击了open 按钮 ..

日志

由于Next.js 同时运行在客户端和服务器端,有两种日志是支持的 ..

  • console.log在浏览器上是支持的
  • stdout在服务器上支持

如果你想要一个结构化日志包,我们推荐 Pino.如果你使用Vercel,这里已经预置了一个与next.js 兼容的 日志集成

错误处理

当一个未处理的异常发生的时候,你能够控制用户的体验,通过一个 500 页面 … 我们推荐定制它,而不是next.js 默认主题 …

你能够记录和跟踪异常(使用 类似于Sentry的工具),上面的例子展示了如何捕捉并暴露一个错误(同时在客户端和服务器端),使用Sentry针对next.js的SDK,同样也包含了Sentry对Vercel的集成 ..

加载性能

为了提高加载性能,你首先需要决定测量那些以及怎样测量 … Core Web Vitals 是一个好的工业级的标准使用你自己的web浏览器进行测量 .. 如果你不熟悉它的一些指标(衡量标准),参观这一篇博客文章并决定那些特定的指标将被你驱动用来进行加载性能的评估 .. 理想情况下,你可能想要在以下的环境下测量性能:

  • 实验中,使用自己的计算机 或者 模拟器
  • 实战,使用来自实际游客的真实数据
  • 本地,使用一个运行在本地设备的测试
  • 远程,使用一个运行在云上的测试

一旦你能够测量加载性能,使用以下的策略去优化他(一步一步的),因此你能够引用一个策略,测量新的性能并持续调整直到你似乎没有看到任何提升了,然后你能够移动到下一个策略 …

  • 使用的缓存地域最好接近你的数据库或者API 部署的区域 …
  • 正如缓存部分描述的,使用一个state-while-revalidate值将不会覆盖你的后端 …
  • 删除未使用的js,回顾,审视这个博客文章去理解Core web vitals metrics 打包尺寸到底受什么影响并且那些策略我能够用来减少尺寸,例如:
    • 配置我的代码编码器用来浏览import 消耗和尺寸
  • 发现可替代的更小的包
  • 动态加载的组件和依赖
  • For more in depth information, review this guide and this performance checklist.