Back返回博客

Next.js 9.4 版本发布

Next.js 9.4 引入了 React 快速刷新 (Fast Refresh)、增量静态再生 (Incremental Static Regeneration)、 新环境变量支持、内置 Fetch 等多项功能!

今天我们很高兴地推出 Next.js 9.4,主要特性包括:

快速刷新 (Fast Refresh)

快速刷新是一种新的热重载体验,可即时反馈对 React 组件所做的编辑。从 Next.js 9.4 开始,默认启用 所有项目的快速刷新功能。

热重载 早已存在,但 历史上一直 过于脆弱,无法默认在工作流中使用。因此,Next.js 之前实现了一种粗略的热重载形式,会重置整个应用状态。

旧的热重载实现无法应对编译或运行时错误,如果在编辑 CSS 或 JavaScript 时出现拼写错误,会触发应用完全重新加载。这种方式不够理想,会打断开发思路。

快速刷新深度集成到 React 本身(通过 React Refresh),使 Next.js 能够对 React 组件树执行精确的预测性更新。

这意味着 Next.js 只会更新你编辑的文件中的代码,并且仅重新渲染该组件,不会丢失组件状态。这包括样式(内联、CSS-in-JS 或 CSS/Sass Modules)、标记、事件处理程序和效果(通过 useEffect)。

一个包含编译和运行时错误(快速恢复)以及保留状态的编辑会话演示。

作为此体验的一部分,我们完全重新设计了错误覆盖层,使其更有帮助,并使应用对拼写错误或运行时错误更具弹性。包括但不限于:

  • 精确的错误位置,解析为编译前代码的 原始行和列
  • 上下文相关的 源代码片段,支持 点击在编辑器中打开
  • 修复语法错误后 恢复开发会话不丢失应用状态
  • 修复错误后 自动消除 未处理的运行时错误

我们要感谢 Dan Abramov 在实现此功能过程中提供的宝贵贡献和帮助。

增量静态再生 (beta)

Next.js 在 9.3 版本中引入了静态站点生成方法,目标明确:我们应获得 静态化的优势(始终快速、始终在线、全球分发),同时提供 Next.js 所擅长的对动态数据的出色支持。

为了兼顾两者优势,Next.js 支持 增量静态生成,在构建站点后更新静态内容。例如,在 9.3 版本中我们引入了 getStaticPaths 中的 fallback: true 选项,允许在运行时添加 新页面

我们最近 构建了一个示例 展示 Next.js 如何以这种方式静态预渲染无限数量的页面。

今天,我们还推出了 增量静态再生 (beta),这是一种 更新现有页面 的机制,通过在流量到来时在后台重新渲染它们。受 stale-while-revalidate 启发,这确保流量不间断地提供静态内容,新构建的页面仅在生成完成后推送。

pages/blog/[slug].js
export async function getStaticProps() {
  return {
    props: await getDataFromCMS(),
    // 我们将尝试重新生成页面:
    // - 当有请求进入时
    // - 最多每秒一次
    unstable_revalidate: 1,
  };
}

与 SSR 不同,增量静态再生确保你保留静态化的优势:

  • 无延迟峰值。页面始终快速提供。
  • 页面永不离线。如果后台页面重新生成失败,旧页面保持不变。
  • 数据库和后端负载低。页面最多同时重新计算一次。

增量功能(添加页面和惰性更新)以及 预览模式 都已完全支持 next startVercel 边缘平台 开箱即用。

接下来,我们将制定补充 RFC 以解决另外两个增量静态生成能力:

  • 同时重新生成和失效多个页面(如博客索引和特定博客文章)
  • 通过监听事件(如 CMS webhooks)在用户流量到来前重新生成

CMS 示例

在我们宣布 新一代静态站点生成 后,我们希望分享从 Headless CMS API 获取内容并将其渲染为 Next.js HTML 的实际场景。

我们与一些全球最佳 CMS 系统的创建者合作:ContentfulDatoCMSPrismicSanityTakeShape,更多即将推出。

这些示例不仅可以直接使用,100% 开源且采用 MIT 许可,还融入了最佳实践:

DatoCMS 因其内置的图像优化支持而取得了完美效果。

DatoCMS 因其内置的图像优化支持而取得了完美效果。

我们还与 TinaCMS 合作探索 CMS 的新方向:页面内内容编辑查看他们的指南 了解如何为你的项目实现此功能。

新环境变量支持

使用 Next.js 的公司反馈的一个常见问题是,不清楚环境变量何时会内联到浏览器包中,何时仅在 Node.js 环境中可用。

今天我们宣布两个完全向后兼容的功能,将帮助简化此流程。

首先,现在可以在环境变量前添加 NEXT_PUBLIC_ 前缀以将其暴露给浏览器。使用该环境变量时,它将内联到浏览器 JavaScript 包中。

不再需要添加 next.config.js 并设置 env 键来暴露这些变量。

pages/index.js
// 环境变量将暴露给浏览器
console.log('应用版本', process.env.NEXT_PUBLIC_VERSION);
 
export default function HomePage() {
  return <h1>Hello World</h1>;
}

第二个变化是 Next.js 现在默认支持 .env 文件加载。允许你轻松定义开发和生成环境变量。

你可以在 环境变量文档 中阅读更多关于 .env 加载的信息。

这些新功能将通过以下约定简化环境变量的使用:

  • 默认情况下,环境变量仅在 Node.js 环境中可用
  • NEXT_PUBLIC_ 为前缀的环境变量会暴露给浏览器

改进的内置 Fetch 支持

Next.js 9.1.7 中,我们宣布在浏览器中 polyfill fetch() API。今天这个 polyfill 已扩展到 Node.js 环境。

实际上,你不再需要使用任何类型的服务端 fetch polyfill(如 isomorphic-unfetchnode-fetch),因为 Next.js 将在所有环境中自动提供 fetch()

例如,在使用 getStaticProps 时(在构建时由 Next.js 执行):

pages/blog.js
export async function getStaticProps() {
  // 不再需要从 isomorphic-unfetch 导入 fetch
  const res = await fetch('https://.../posts');
  const posts = await res.json();
 
  return {
    props: {
      posts,
    },
  };
}
 
function Blog({ posts }) {
  // 渲染文章...
}
 
export default Blog;

集成 Web 核心指标报告

上周 Google Chrome 团队推出了 核心 Web 指标 (Core Web Vitals)。核心 Web 指标是提供出色 Web 用户体验的关键质量信号,著名的 Lighthouse 报告 即基于此构建。

如果你想使网站或 Web 应用尽可能快,跟踪这些指标非常有用,这也是 Next.js 的核心目标之一。

Chrome 团队发布了 核心 Web 指标 Chrome 扩展,允许开发者直观了解页面性能。

在构建生产 Web 应用时,你还希望了解访问者和(潜在)客户的网站性能。你甚至可能希望跟踪这些指标随时间的改进或退化,以查看更改是否对受众产生预期影响。

为了帮助将核心 Web 指标报告到分析服务,我们 与 Google 合作 引入了一个名为 reportWebVitals 的新方法,可以从 pages/_app.js 导出:

pages/_app.js
// 每个需要报告的指标都会调用一次
export function reportWebVitals(metric) {
  // 这些指标可以发送到任何分析服务
  console.log(metric);
}
 
function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}
 
export default MyApp;

要结合分析服务使用此方法,请参阅文档中的 "发送结果到分析" 部分。如果你想了解更多关于核心 Web 指标的信息,可以参考 web.dev/vitals

绝对导入和别名

如果你正在开发大型项目,一些 import 语句可能会受到 ../../../ 路径混乱的影响:

import Button from '../../../../components/button';

在这种情况下,我们可能希望使用 绝对导入 而不是相对导入。假设 components 目录存在于根目录,我们希望 import 语句如下所示:

import Button from 'components/button';

我们很高兴地宣布,Next.js 9.4 使得为 JavaScript 和 TypeScript 项目设置绝对导入变得非常简单。只需将 baseUrl 配置添加到 jsconfig.json (JS 项目)tsconfig.json (TS 项目)

jsconfig.json / tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "."
  }
}

这将允许从 .(根目录)进行绝对导入。它还集成了 VSCode 和其他编辑器,支持代码导航和其他编辑器功能。

注意: 如果你之前修改过 Webpack 模块别名配置 以启用绝对导入,现在可以删除该配置。

此外,Next.js 9.4 还支持 paths 选项,允许创建自定义模块别名。例如,以下配置允许使用 @/design-system 代替 components/design-system

jsconfig.json / tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/design-system/*": ["components/design-system/*"]
    }
  }
}

然后可以像这样使用别名:

// 导入 'components/design-system/button'
import Button from '@/design-system/button';

如果指定 paths,则必须指定 baseUrl。你可以在 TypeScript 文档 中了解更多关于 paths 选项的信息。

可配置的 Sass 支持

Next.js 9.3 中推出内置 Sass 支持后,我们收到部分用户的反馈,希望配置 sass 编译器。例如配置 includePaths

现在可以通过在 next.config.js 中使用 sassOptions 键实现:

next.config.js
const path = require('path');
 
module.exports = {
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles')],
  },
};

改进的日志输出

我们重新设计了命令行输出,使其更加一致,并减少重复数据的输出,如部署 URL、等待开发服务器启动等。我们还更改了消息类型的间距,使其在消息之间保持一致,不再逐行跳动。

在 9.4 之前版本运行 next dev

在 9.4 版本运行 next dev

社区

我们很高兴看到 Next.js 的采用持续增长:

  • 我们已有超过 1066 位独立贡献者。
  • 在 GitHub 上,项目已获得超过 48,000 次 star。

加入 GitHub Discussions 上的 Next.js 社区。Discussions 是一个社区空间,允许你与其他 Next.js 用户联系并提问。

如果你正在使用 Next.js,欢迎 分享你的项目链接 与社区交流。

我们感谢社区以及所有外部反馈和贡献,帮助塑造了这个版本。