今天我们很高兴地发布 Next.js 9.3,主要特性包括:
- 新一代静态站点生成 (SSG) 支持:通过新的数据获取方法实现内置优化的静态生成
- 预览模式:绕过静态生成页面以显示来自 CMS 的草稿内容
- 全局样式表的原生 Sass 支持:应用现在可以直接导入
.scss
文件作为全局样式表 - 组件级样式的 Sass CSS 模块支持:通过
.module.scss
约定,可以在应用中任何位置导入和使用局部作用域的 CSS - 404 页面的自动静态优化:通过静态提供 404 页面提升速度和可靠性
- 运行时体积减少 32 kB:通过强力优化使所有 Next.js 应用的运行时体积更小
- GitHub Discussions 上的 Next.js 社区:现在可以直接在 Next.js 的 GitHub 仓库中讨论和提问
所有这些改进都是非破坏性的且完全向后兼容。要更新只需运行:
新一代静态站点生成 (SSG) 支持
构建网站或 Web 应用时通常需要在两种策略间选择:静态生成 (SSG) 或服务端渲染 (SSR)。
Next.js 是首个混合框架,允许您根据每个页面的具体情况选择最适合的技术。
Next.js 9.0 引入了自动静态优化的概念。当页面没有阻塞性数据获取需求(如 getInitialProps
)时,它会在构建时自动渲染为 HTML。
更多情况下,即使有阻塞性数据获取需求,您可能仍希望在构建时将页面渲染为静态 HTML。例如由 (无头) 内容管理系统 (CMS) 驱动的营销页面或网站的博客部分。
我们与 SSG 和 next export
的重度用户(如 HashiCorp)合作,并通过 Next.js 历史上评论最多的 RFC 与社区深入讨论了正确的约束条件,以创建数据获取和静态生成的新统一方式。
今天我们非常激动地宣布两个新的数据获取方法:getStaticProps
和 getServerSideProps
。我们还提供了一种为动态路由静态生成页面时提供参数的方式:getStaticPaths
。
这些新方法相比 getInitialProps
模型有许多优势,因为它们在 SSG 和 SSR 之间有明确的区分:
getStaticProps
(静态生成):在构建时获取数据getStaticPaths
(静态生成):基于数据指定要预渲染的动态路由getServerSideProps
(服务端渲染):在每次请求时获取数据- 这些改进是 API 的补充。所有新功能完全向后兼容并可逐步采用。没有引入弃用,
getInitialProps
将继续按当前方式工作。我们鼓励在新页面和项目中采用这些新方法
getStaticProps
如果从页面导出名为 getStaticProps
的 async
函数,Next.js 将在构建时预渲染此页面。这在您希望从 CMS 渲染特定静态页面时特别有用。
getStaticProps
始终在 Node.js 环境中运行,代码会自动从浏览器包中进行 tree-shaken,确保发送到浏览器的代码更少。这样您就不必担心数据获取代码在 Node.js 和浏览器环境中的执行不一致问题。
这允许您使用任何异步甚至同步的数据获取技术,包括 fetch
、REST、GraphQL 或直接访问数据库。
context
参数是包含以下键的对象:
params
:对于使用动态路由的页面,params
包含路由参数。例如,如果页面名称是[id].js
,则params
将类似{ id: ... }
。更多信息请查看动态路由文档。这应与getStaticPaths
一起使用,我们稍后会解释。
以下示例使用 getStaticProps
从 CMS 获取博客文章列表:
何时使用 getStaticProps?
在以下情况下应使用 getStaticProps
:
- 渲染页面所需的数据在用户请求前的构建时可用
- 数据来自无头 CMS
- 数据可以公开缓存(非用户特定)
- 页面必须预渲染(为了 SEO)且速度极快 ——
getStaticProps
生成 HTML 和 JSON 文件,两者都可以通过 CDN 缓存以提高性能
有关 getStaticProps
的更多信息,请参阅数据获取文档。
getStaticPaths
如果页面有动态路由并使用 getStaticProps
,则需要定义在构建时需要渲染为 HTML 的路径列表。
如果从使用动态路由的页面导出名为 getStaticPaths
的 async
函数,Next.js 将静态预渲染 getStaticPaths
指定的所有路径。
paths 键(必需)
paths 键决定哪些路径将被预渲染。例如,假设您有一个使用动态路由的页面 pages/posts/[id].js
。如果从此页面导出 getStaticPaths
并为 paths 返回以下内容:
那么 Next.js 将使用 pages/posts/[id].js
中的页面组件在构建时静态生成 posts/1
和 posts/2
。
注意每个 params
的值必须与页面名称中使用的参数匹配:
- 如果页面名称是
pages/posts/[postId]/[commentId]
,则params
应包含postId
和commentId
- 如果页面名称使用全捕获路由,例如
pages/[...slug]
,则params
应包含slug
(一个数组)。例如,如果此数组是['foo', 'bar']
,则 Next.js 将在/foo/bar
静态生成页面
fallback 键(必需)
getStaticPaths
返回的对象必须包含布尔值 fallback
键。
fallback: false
如果 fallback
为 false
,则任何未由 getStaticPaths
返回的路径都将导致 404 页面。这在您知道所有路径都将在构建时已知时很有用。
以下示例预渲染名为 pages/posts/[id].js
的每篇博客文章页面。博客文章列表将从 CMS 获取并由 getStaticPaths
返回。然后,对于每个页面,使用 getStaticProps
从 CMS 获取文章数据。
fallback: true
如果 fallback
为 true
,则 getStaticProps
的行为会发生变化,Next.js 将在构建时将提供的路径渲染为 HTML。当路径未在构建时生成时,将在用户请求页面时按需生成。
这在应用有许多可以静态生成的路由,但您不希望仅生成部分页面而增加构建时间时非常有用。
触发页面生成的用户将收到一个回退 HTML,这通常是一个加载状态的页面。这样做的原因是静态 HTML 可以从 CDN 提供,确保页面始终快速,即使尚未生成。
以下示例展示按需静态生成额外页面的情况:
有关 getStaticPaths
的更多信息,请参阅数据获取文档。
getServerSideProps
如果从页面导出一个名为 getServerSideProps
的 async
函数,Next.js 会在每次请求时渲染该页面(服务端渲染 SSR)。
getServerSideProps
始终在服务端运行,其代码会自动从浏览器包中进行 tree-shaken 移除,确保更少的代码发送到浏览器。这样您无需担心数据获取代码在服务端和浏览器环境中的执行不一致问题。由于服务器通常与数据源有更快的连接,这在许多情况下能提高性能。同时通过减少数据获取逻辑的暴露,也增强了安全性。
您可以使用任何异步甚至同步的数据获取技术,包括 fetch
、REST、GraphQL 或直接访问数据库。
当使用 next/link
在页面间导航时(而非在浏览器中执行 getServerSideProps
),Next.js 会向服务器发起获取请求,服务器将返回调用 getServerSideProps
的结果。
context
参数是一个包含以下键的对象:
params
:如果页面使用动态路由,params
包含路由参数。例如页面名为[id].js
,则params
形如{ id: ... }
。了解更多请查看 动态路由文档。req
:HTTP 请求对象。res
:HTTP 响应对象。query
:查询字符串。
以下示例使用 getServerSideProps
在请求时获取数据并渲染:
了解更多关于 getServerSideProps
的信息,请参阅 数据获取文档。
预览模式
如前文所述,当页面从无头 CMS 获取数据时,静态生成 (Static Generation) 非常有用。但当您在无头 CMS 上撰写草稿并希望立即预览时,静态生成就不理想了。由于输出是静态的,预览变更会变得困难,因为您必须重新生成静态页面。
Next.js 引入的 getStaticProps
开启了新的可能性,例如在某些条件下利用 Next.js 的按需渲染能力。
例如,当预览无头 CMS 的草稿时,您可能希望绕过静态渲染,按需渲染包含草稿内容而非发布内容的页面。您会希望 Next.js 仅针对这种情况绕过静态生成。
我们很高兴宣布 Next.js 的新内置功能:预览模式 (Preview Mode)。
预览模式允许用户绕过静态生成的页面,按需渲染(SSR)来自 CMS 的草稿页面。
但不仅限于特定 CMS 系统。预览模式直接与 getStaticProps
和 getServerSideProps
集成,因此可与任何类型的数据获取方案配合使用。
使用 next start
或无缝部署到 Vercel 边缘网络时,预览模式已可用。
亲自体验预览模式:https://next-preview.vercel.app/
与 CMS 提供商合作
getStaticProps
允许您从任何数据源(包括 CMS 系统)获取数据
我们正积极与 CMS 生态系统中的许多关键参与者合作,提供与 Next.js 集成的示例和指南。
当前正在积极开发的示例包括:
如果您的公司在 CMS 生态系统中活跃,我们很乐意合作!欢迎通过邮件或 Twitter 联系我们的团队。
全局样式表的内置 Sass 支持
Next.js 9.2 引入了全局 CSS 样式表的内置支持,以取代 next-css
插件,通过更好的默认设置提供更优化的结果。
发布后,我们越来越多地被要求集成 Sass 支持,因为许多迁移到 Next.js 的企业拥有基于 Sass 的现有设计系统。
通过调查 Next.js 插件使用情况,我们发现约 30% 的 Next.js 应用目前使用 next-sass
,而 44% 使用原生 CSS,6% 使用 Less。
此外,next-sass
存在与 next-css
相同的约束缺失问题。这意味着您可以在项目的每个文件中导入 Sass 文件,但这些导入的 Sass 文件将对整个应用全局生效。
基于这些统计数据和反馈,我们很高兴地宣布 Next.js 现在内置支持导入 Sass 样式表。
要在应用中使用全局 Sass 导入,请先安装 sass
:
然后在 pages/_app.js
中导入 Sass 文件。
例如,假设项目根目录下有以下名为 styles.scss
的样式表:
如果尚未存在,请创建 pages/_app.js
文件。然后导入 styles.scss
文件:
由于样式表本质上是全局的,必须在 自定义 <App>
组件中导入,以避免全局样式的类名和顺序冲突。
在开发环境中,这种样式表表达方式允许您在编辑样式时页面自动更新。
在生产环境中,所有 Sass 和 CSS 文件会自动合并为一个经过压缩的 .css
文件。该 CSS 文件将通过 <link>
标签加载,并自动注入到 Next.js 生成的默认 HTML 标记中。
此新功能完全向后兼容。如果您正在使用 @zeit/next-sass
或其他 CSS 相关插件,该功能会被禁用以避免冲突。
如果您当前使用 @zeit/next-sass
,建议从 next.config.js
和 package.json
中移除该插件,升级后转而使用内置的 Sass 支持。
组件级样式的内置 Sass CSS 模块支持
Next.js 现在支持使用 [name].module.scss
文件命名约定的 Sass 文件的 CSS 模块。
与 Next.js 5+ 中通过 next-sass
提供的支持不同,全局 Sass 和 CSS 模块现在可以共存——next-sass
要求应用中所有 .scss
文件要么全局处理,要么局部处理,不能两者兼有。
CSS 模块通过自动创建唯一的类名来实现 Sass 的局部作用域。这允许您在不同的文件中使用相同的 Sass 类名而不必担心冲突。
这种行为使 CSS 模块成为包含组件级 Sass 的理想方式。CSS 模块文件可以在应用的任何位置导入。
要在应用中使用 Sass CSS 模块,请确保已安装 sass
:
现在,假设 components/
文件夹中有一个可复用的 Button
组件:
首先,创建包含以下内容的 components/Button.module.scss
:
然后,创建 components/Button.js
,导入并使用上述 CSS 文件:
Sass 文件的 CSS 模块是一个_可选_功能,仅对扩展名为 .module.scss
的文件启用。常规的 <link>
样式表和 全局 Sass 样式仍然受支持。
在生产环境中,所有 CSS 模块文件会自动合并为多个经过压缩和代码拆分的 .css
文件。这些 .css
文件代表了应用中的热执行路径,确保为每个页面加载最少数量的 CSS 以实现绘制。
与上述相同,此新功能完全向后兼容。如果您正在使用 @zeit/next-sass
或其他 CSS 相关插件,该功能会被禁用以避免冲突。
如果您当前使用 @zeit/next-sass
,建议从 next.config.js
和 package.json
中移除该插件,转而使用内置的 Sass 支持。
404 页面的自动静态优化
Next.js 9 的发布引入了 自动静态优化 的概念:当页面没有阻塞数据需求时,Next.js 会在构建时自动将页面生成为静态 HTML。然而,有一个页面未被自动渲染为静态 HTML:404 页面。404 页面未自动静态化的主要原因是处理 404 的 /_error
页面不仅处理 404,还处理其他错误。
由于 404 页面针对不存在的路由进行渲染,按需渲染页面可能导致成本增加和服务器负载加重。
我们通过两种方式帮助您获得最佳实践:
- 默认的 Next.js 体验会生成静态 404 页面
- 自定义 404 页面时仍确保最终获得静态页面
此功能完全向后兼容,因此如果您当前有自定义的 pages/_error.js
,在添加 pages/404.js
之前,它将继续用于 404 页面。
默认的静态 404 页面
当应用没有自定义的 pages/_error.js
页面时,Next.js 会自动静态生成 404 页面,并在需要提供 404 时使用该页面。这一过程自动完成,无需任何更改。
使用 pages/404.js 自定义 404 页面
要覆盖默认 404 页面,您现在可以创建 pages/404.js
,该页面仍会在构建时自动静态优化。如果应用有此页面,将使用它而非 pages/_error.js
来渲染 404。
运行时减小 32+ kB(Gzip 减小 15+ kB)
Next.js 支持 与 React 相同的浏览器,无需额外配置。这包括 Internet Explorer 11 (IE11) 和所有主流浏览器(Edge、Firefox、Chrome、Safari、Opera 等)。
作为此兼容性的一部分,我们还会将您的应用编译为兼容 IE11:这允许您安全地使用 ES6+ 语法特性、Async/Await、对象剩余/扩展属性等——所有这些都无需任何配置。
此编译过程还包括透明地注入必要的功能 polyfill(如 Array.from
或 Symbol
)。然而,这些 polyfill 仅对 不到 10% 的网络流量 是必要的,大多数情况下是为了支持 IE11。
从 Next.js 9.3 开始,Next.js 会自动加载支持旧版浏览器所需的 polyfill,并且仅在这些旧版浏览器中加载 polyfill。
实际上,这意味着对于 90%+ 的用户,首次加载 大小将减少 32 kB 或更多。
对于依赖更多浏览器特性的大型应用,这些大小节省甚至更大。
此优化完全自动进行,无需对应用进行任何更改即可受益!
社区
我们非常高兴看到 Next.js 的持续增长:
- 我们有超过 927 位独立贡献者。
- 在 GitHub 上,该项目已获得超过 46,600 次 star。
- 示例目录 包含超过 226 个示例。
Next.js 社区现在拥有超过 15,250 名成员。社区现在可以在 GitHub discussions 上找到,这是一个供社区讨论和提问的新地方!加入我们!
我们感谢我们的社区以及所有帮助塑造此版本的外部反馈和贡献。
特别感谢 Jeff Escalante 对新数据获取方法的重要反馈。
衷心感谢所有为此版本做出贡献的人:@arcanis, @lgordey, @ijjk, @martpie, @jaywink, @fabianishere, @dijs, @TheRusskiy, @quinnturner, @timneutkens, @lfades, @vvo, @adithwip, @rafaelalmeidatk, @bmathews, @Spy-Seth, @EvgeniyKumachev, @chibicode, @piglovesyou, @HaNdTriX, @Timer, @janicklas-ralph, @devknoll, @prateekbh, @ethanryan, @MoOx, @rifaidev, @msweeneydev, @motiko, 和 @balazsorban44 的帮助!