跳到内容
返回博客

2020年5月11日,星期一

Next.js 9.4

发布者

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

Fast Refresh

Fast Refresh 是一种新的热重载体验,可让你即时获得对 React 组件所做编辑的反馈。对于 Next.js 9.4 或更高版本上的所有项目,它现在默认启用

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

旧的热重载实现对编译或运行时错误不够健壮,如果你在编辑 CSS 或 JavaScript 时出现拼写错误,它将执行应用程序的完全重新加载。这是不理想的,并且会中断你的思路。

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

这意味着 Next.js 将仅更新你编辑的文件中的代码,并且仅重新渲染该组件,而不会丢失组件状态。这包括样式(内联、CSS-in-JS 或 CSS/Sass 模块)、标记、事件处理程序和效果(通过 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(),
    // 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 Webhooks)在用户流量之前进行重新生成

CMS 示例

在我们发布下一代静态站点生成公告之后,我们想分享从 Headless 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 的公司那里收到的一个常见反馈是,不清楚环境变量何时内联到浏览器 bundle 中,以及何时仅在 Node.js 环境中可用。

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

首先,您现在可以使用 NEXT_PUBLIC_ 前缀环境变量,以将环境变量公开给浏览器。当使用该环境变量时,它将被内联到浏览器 JavaScript bundle 中。

您不再需要添加 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 中,我们宣布了在浏览器中 polyfill fetch() API。今天,此 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 团队推出了 Core Web Vitals。Core Web Vitals 是在 Web 上提供出色用户体验的关键质量信号,著名的 Lighthouse 报告 就是基于此构建的。

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

Chrome 团队发布了一个 Core Web Vitals Chrome 扩展程序,它允许您作为开发人员获得有关页面性能的可视化反馈。

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

为了帮助将 Core Web Vitals 报告给您的分析服务,我们引入了一个新的方法 reportWebVitals与 Google 合作,该方法可以从 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;

要结合您的分析服务使用此方法,请参阅文档的“将结果发送到 Analytics”部分。如果您想了解更多关于 Core 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 Discussions。Discussions 是一个社区空间,您可以在其中与其他 Next.js 用户联系并提出问题。

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

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