跳至内容
返回博客

2020年1月15日,星期三

Next.js 9.2

发布者

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

  • 内置 CSS 支持全局样式表:应用程序现在可以直接导入 .css 文件作为全局样式表。
  • 内置 CSS 模块支持组件级样式:利用 .module.css 约定,本地作用域 CSS 可以导入并在应用程序中的任何位置使用。
  • 改进的代码分割策略:Google Chrome 团队对 Next.js 的代码分割策略进行了大量优化,从而产生了更小的客户端包。此外,他们最大化了 HTTP/2 的利用率,以提高页面加载速度,而不会影响 HTTP/1.1 的性能。
  • 通配符动态路由:Next.js 的动态路由现在支持通配符路由,支持各种新的用例,例如 CMS 供电的网站。

所有这些好处都是非破坏性的,并且完全向后兼容。您需要做的就是运行以下命令进行更新

终端
npm i next@latest react@latest react-dom@latest

内置 CSS 支持全局样式表

Next.js 5 引入了通过名为 next-css 的自定义插件导入 CSS 的支持,该插件扩展了 Next.js 的行为。

随着时间的推移,我们从 Next.js 的公司和用户那里获得了持续的反馈,他们提到他们最终经常将 next-css 添加到他们的应用程序中。

此外,next-css 在导入 CSS 时缺少一些约束。例如,您可以在项目的每个文件中导入 CSS 文件,但是此导入的 CSS 文件将对整个应用程序全局有效。

为了改善开发人员体验并解决这些不一致问题,我们开始着手默认情况下将 CSS 导入支持引入 Next.js。

我们很高兴地宣布,Next.js 现在原生支持将样式表导入您的应用程序。

要开始在您的应用程序中使用 CSS 导入,请在 pages/_app.js 中导入 CSS 文件。

例如,考虑以下在项目根目录中名为 styles.css 的样式表

body {
  padding: 20px 20px 60px;
  margin: 0;
}

如果尚不存在,请创建一个 pages/_app.js 文件

然后,导入 styles.css 文件

pages/_app.js
import '../styles.css';
 
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

由于样式表本质上是全局的,因此必须在 自定义 <App> 组件 中导入它们。这对于避免全局样式的类名和顺序冲突是必要的。

在开发过程中,以这种方式表达样式表可以让您的样式在您编辑它们时自动更新到页面上。

在生产环境中,所有 CSS 文件将自动连接到一个单独的最小化 .css 文件中。此 CSS 文件将通过 <link> 标签加载,并自动注入到 Next.js 生成的默认 HTML 标记中。

此新功能完全向后兼容。如果您正在使用 @zeit/next-css 或其他与 CSS 相关的插件,则禁用此功能以避免冲突。

如果您目前正在使用 @zeit/next-css,我们建议您从 next.config.jspackage.json 中删除该插件,从而在升级后迁移到内置的 CSS 支持。

内置 CSS 模块支持组件级样式

Next.js 现在支持使用 [name].module.css 文件命名约定的 CSS 模块

与之前在 Next.js 5 中使用 next-css 提供的支持不同,全局 CSS 和 CSS 模块现在可以 **共存** - next-css 要求应用程序中的所有 .css 文件都作为全局或局部处理,但不能同时处理两者。

CSS 模块通过自动创建唯一的类名来本地作用域 CSS。这允许您在不同的文件中使用相同的 CSS 类名,而无需担心冲突。

此行为使 CSS 模块成为包含组件级 CSS 的理想方式。CSS 模块文件 **可以在应用程序中的任何位置导入**。

例如,考虑 components/ 文件夹中可重用的 Button 组件

首先,创建 components/Button.module.css,内容如下

/*
You do not need to worry about .error {} colliding with any other `.css` or
`.module.css` files!
*/
.error {
  color: white;
  background-color: red;
}

然后,创建 components/Button.js,导入并使用上述 CSS 文件

components/Button.js
import styles from './Button.module.css';
 
export function Button() {
  return (
    <button
      type="button"
      // Note how the "error" class is accessed as a property on the imported
      // `styles` object.
      className={styles.error}
    >
      Destroy
    </button>
  );
}

CSS 模块是一个可选功能,仅对扩展名为 .module.css 的文件启用。常规的 <link> 样式表全局 CSS 文件 仍然受支持。

在生产环境中,所有 CSS 模块文件都会自动连接到 **多个最小化和代码分割的 .css 文件** 中。这些 .css 文件表示应用程序中的热执行路径,确保为应用程序的绘制加载最少的 CSS。

与上面一样,此新功能完全向后兼容。如果您正在使用 @zeit/next-css 或其他与 CSS 相关的插件,则禁用此功能以避免冲突。

如果您目前正在使用 @zeit/next-css,我们建议您从 next.config.jspackage.json 中删除该插件,从而迁移到内置的 CSS 支持。

改进的代码分割策略

9.2 之前的 Next.js 版本有一组固定的 JavaScript 包需要加载才能使页面具有交互性

  • 页面的 JavaScript 文件
  • 包含通用 JavaScript 的文件
  • Next.js 客户端运行时包
  • Webpack 客户端运行时包
  • 动态导入(通过 next/dynamic 添加,如果使用的话)

为了使页面具有交互性,所有这些包都必须加载,因为它们相互依赖才能在浏览器中启动 React。

由于所有这些捆绑包对于应用程序变得交互式都是必需的,因此尽可能地优化它们非常重要。在实践中,这意味着不要过度下载应用程序其他部分的代码。

出于这个原因,Next.js 使用了一个名为 commons 的捆绑包,其中包含页面之间共用的 JavaScript 代码。旧的捆绑包拆分策略计算生成 commons 的方法是基于使用率启发式算法。如果某个模块在超过 50% 的页面中使用,则会被标记为公共模块。否则,它将被捆绑到该页面的 JavaScript 文件中。

但是,应用程序可能包含许多不同类型的页面。例如,营销页面、博客和仪表盘。如果与其他页面类型相比,营销页面的数量很多,那么 commons 的计算结果将导致优化过分集中在营销页面上。

我们的目标是优化一个应用程序中的所有页面类型。

Alex Castle 提出了一种新的分块方法(创建单独的 JavaScript 文件),该方法允许使用多个文件进行优化的公共分块,包括涉及许多页面类型的情况。

今天,我们很高兴地宣布,Next.js 9.2 中默认启用了这种新的分块行为。我们要对 Google Chrome 团队Alex Castle 为做出此更改表示衷心的感谢。此更改反映了数周的研究、实验室测试、真实环境测试和实施的累积成果。

新的分块实现利用 HTTP/2 传输更多数量的小尺寸块。

在新的启发式算法下,将为以下内容创建块:

  • 每个页面的最小块。
  • 包含 React、ReactDOM、React 的 Scheduler 等的框架块。
  • 任何超过 160kb(预压缩/gzip)的 node_module 依赖项的库块。
  • 所有页面共用代码的公共块。
  • 尽可能多的共享块(由 2 个或更多页面使用),优化整体应用程序大小和初始加载速度。
  • Next.js 的客户端运行时。
  • Webpack 运行时。

让我们看看这在实际应用中意味着什么。

一家率先采用的行业合作伙伴 Barnebys® 发现其整体应用程序大小减少了 23%。

此外,他们最大的 JS 捆绑包减少了 30%——从 605kB 减少到 425kB——无需任何代码更改。

另一家行业合作伙伴 SumUp® 发现其最大的 JS 捆绑包减少了 70%——从 395kB 减少到 122kB——无需任何代码更改。

最大 JavaScript 捆绑包

之前之后变化
Barnebys605kB425kB30% 更小
SumUp395kB122kB70% 更小

新的分块行为不仅减少了整体和初始加载大小,还减少了后续的客户端导航。 Barnebys® 在六 (6) 次页面导航后,加载的 JavaScript 量减少了 87%。

多次客户端转换加载的 JavaScript

之前之后变化
Barnebys136kB18kB87% 更小

此新行为完全向后兼容。升级到最新版本的 Next.js 就是您利用此性能提升所需做的全部工作。

通配符动态路由

随着 Next.js 9 的发布,我们引入了 动态路由片段,目标是在无需自定义服务器的情况下简化 Next.js 中的动态片段。此功能已被 Next.js 用户广泛采用。

动态路由片段功能仍然有一些情况没有涵盖。

其中一种情况是通配符路由。例如,将类似 /post/** 的通配符作为页面进行路由。当您具有由内容源(如 CMS)定义的嵌套结构时,这尤其有用。

您现在可以使用 [...name] 语法创建通配符动态路由。

例如,pages/post/[...slug].js 将匹配 /post/a/post/a/b/post/a/b/c 等。

slug 将作为单个路径部分的数组提供在路由查询对象中。因此,对于路径 /post/foo/bar,查询对象将为 { slug: ['foo', 'bar'] }

社区

我们非常高兴地看到 Next.js 采用率的持续增长。

  • 我们拥有超过 880 位独立贡献者。
  • 在 GitHub 上,该项目已被加星标超过 44,000 次。
  • 示例目录 拥有超过 220 个示例。

Next.js 社区现在拥有超过 13,800 名成员。 加入我们!

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