跳到内容
返回博客

2020年5月11日 星期一

Next.js 9.4

发布者

我们今天很高兴推出 Next.js 9.4,其特点包括:

快速刷新

快速刷新是一种全新的热重载体验,可让您即时反馈对 React 组件所做的编辑。现在,对于 Next.js 9.4 或更高版本的所有项目,它都默认启用

热重载 已经存在很长时间,但 历史上一直 过于脆弱,无法在您的工作流程中默认启用。因此,Next.js 之前实现了一种粗糙的热重载形式,会重置整个应用程序的状态。

旧的热重载实现对编译或运行时错误不具备弹性,如果您在编辑 CSS 或 JavaScript 时打错了字,它将对您的应用程序执行完全重载。这并非最佳选择,并打断了您的思路。

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

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

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

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

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

我们要感谢 Dan Abramov 对实现此功能所做的宝贵贡献和帮助。

增量静态再生(测试版)

Next.js 在 9.3 中引入了静态网站生成方法,其目标明确:我们应该获得 静态化的好处(始终快速、始终在线、全球分发),同时对动态数据提供出色的支持,而这正是 Next.js 的闻名之处。

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

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

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

pages/blog/[slug].js
export async function getStaticProps() {
  return {
    props: await getDataFromCMS(),
    // we will attempt to re-generate the page:
    // - when a request comes in
    // - at most once every second
    unstable_revalidate: 1,
  };
}

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

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

两个增量功能(添加页面和延迟更新它们)以及 预览模式,都已通过 next startVercel 边缘平台 开箱即用全面支持。

接下来,我们将致力于制定一份补充 RFC,以解决两个额外的增量静态生成功能:

  • 同时重新生成和失效多个页面(例如您的博客索引和某个博客文章)
  • 通过监听事件(例如 CMS webhook),在用户流量到来之前重新生成

CMS 示例

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

我们与一些世界上最好的 CMS 系统开发者合作:ContentfulDatoCMSPrismicSanityTakeShape,更多 CMS 正在开发中。

这些示例不仅可以直接使用,100% 开源并采用 MIT 许可,而且它们还包含了最佳实践:

DatoCMS achieves impeccable results due to their built-in image optimization support.
DatoCMS 由于其内置的图像优化支持,实现了无可挑剔的效果。

DatoCMS 由于其内置的图像优化支持,实现了无可挑剔的效果。

我们还与 TinaCMS 合作,在 CMS 方面探索一个激动人心的新方向:页面内内容编辑查看他们的指南,了解如何在您的项目中实现它。

新的环境变量支持

我们从使用 Next.js 的公司那里得到的一个常见反馈是,环境变量何时内联到浏览器包中以及何时仅在 Node.js 环境中可用尚不清楚。

今天,我们宣布了两项完全向后兼容的功能,它们将有助于简化此过程。

首先,您现在可以使用 NEXT_PUBLIC_ 作为环境变量的前缀,以将环境变量暴露给浏览器。当使用该环境变量时,它将被内联到浏览器 JavaScript 包中。

您不再需要添加 next.config.js 并添加 env 键来公开这些变量。

pages/index.js
// The environment variable will be exposed to the browser
console.log('My Application Version', 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 中,我们宣布了在浏览器中对 fetch() API 的 Polyfill。今天,这个 Polyfill 也已扩展到 Node.js 环境。

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

例如,当使用 getStaticProps 时,它会在构建时使用 Next.js 执行:

pages/blog.js
export async function getStaticProps() {
  // fetch no longer needs to be imported from isomorphic-unfetch
  const res = await fetch('https://.../posts');
  const posts = await res.json();
 
  return {
    props: {
      posts,
    },
  };
}
 
function Blog({ posts }) {
  // Render posts...
}
 
export default Blog;

集成 Web Vitals 报告

上周,Google Chrome 团队推出了 核心 Web Vitals。核心 Web Vitals 是在网络上提供出色用户体验的关键质量信号,著名的 Lighthouse 报告 就是以此为基础构建的。

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

Chrome 团队发布了一款 Core Web Vitals Chrome 扩展程序,让您作为开发人员可以获得页面性能的视觉反馈。

在构建生产 Web 应用程序时,您还需要了解您的网站对访问者和(潜在)客户的表现如何。您甚至可能希望随着时间的推移跟踪这些指标的改进或退步,以便查看您的更改是否对受众产生了预期影响。

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

pages/_app.js
// Will be called once for every metric that has to be reported.
export function reportWebVitals(metric) {
  // These metrics can be sent to any analytics service
  console.log(metric);
}
 
function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}
 
export default MyApp;

要将此方法与您的分析服务结合使用,请参阅文档的“将结果发送到分析”部分。如果您想了解有关核心 Web Vitals 的更多信息,可以参考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/*"]
    }
  }
}

然后,您可以像这样使用您的别名

// Imports '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 次。

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

如果您正在使用 Next.js,请随时与社区分享您的项目 URL

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