今天我们很高兴地宣布 Next.js 9.1 版本,新增对 src
和 public
目录的支持。
本版本新特性
src
目录支持:现在可以将pages
目录嵌套在src
文件夹下,支持更多样化的应用结构。public
目录支持:定义需要挂载到应用根 URL 的文件(例如favicon.ico
)。
本版本预览功能
- 内置 CSS 支持:即将支持全局 CSS 导入,并提供开发环境热重载及生产环境的优化、编译和 polyfill 支持。
- 静态错误页面:静态导出预期的错误页面(如 404),提升 CDN 可用性。
- Module/Nomodule:为使用现代浏览器的终端用户提供更小的 JavaScript 包。
- 改进的代码分割:减少向终端用户传输的字节量,提升 TTI 和页面切换速度。大型库的代码块将在多次部署间长期缓存。
与往常一样,我们确保所有这些改进都保持向后兼容。您只需运行以下命令即可更新:
如果您的应用使用的是 9.0 之前的 Next.js 版本,可以参考 升级指南 了解可能需要进行的更改。
自上次大版本发布以来,我们很高兴看到 TikTok、Hilton、Elastic、Realtor 和 JW Player 等公司采用 Next.js 构建产品。查看 案例展示 了解更多!
src
目录支持
Next.js 有一个特殊的 pages
目录,其中每个文件都会成为独立路由。遵循约定优于配置的原则,该目录必须位于 Next.js 应用的根目录下。
在与使用 Next.js 的公司交流并分析一些闭源代码库后,我们发现开发者普遍希望将代码放在 src
目录中,并将 pages
目录也置于其中。
从 Next.js 9.1 开始,您现在可以创建 src/pages
目录,而无需在应用根目录下创建 pages
目录。
使用 src
目录是可选的,这主要适用于那些已有此目录规范的公司。
src 目录中的 pages 文件夹
public
目录支持
除了 pages
目录外,Next.js 还有另一个特殊目录 static
,其中的文件会被映射到 /static
路由。
例如,static/my-image.png
会被映射到 /static/my-image.png
。
这个约定自 Next.js 首次发布以来一直运作良好,没有特别的问题。
然而,随着时间的推移,我们发现 /static
并不能满足 Web 应用的所有需求。例如,robots.txt
必须从域名根目录提供服务。
从 Next.js 9.1 开始,我们引入了一个名为 public
的新目录。
public
目录中的任何文件都将被映射到域名根目录。
例如,public/robots.txt
将被映射到 /robots.txt
。
由于 public
目录也能覆盖 static
目录的功能,我们决定弃用 static
目录,推荐创建具有相同功能的 public/static
文件夹。
我们始终致力于保持向后兼容,因此 static
目录将继续工作,但会显示弃用警告。
即将到来
以下功能目前处于实验阶段,将在最终实现完成后正式发布。
内置 CSS 支持
目前,Next.js 内置了一个名为 styled-jsx 的 CSS-in-JS 解决方案。这个方案非常适合为单个 React 组件添加样式。
然而,在与企业交流中,我们发现普遍存在复用现有 CSS 样式或基于 CSS 的设计系统的需求。
通常这意味着需要添加 next-css
插件来支持 CSS 导入。
我们发现大约 50% 的 Next.js 用户会在他们的应用中添加这个插件。
鉴于如此广泛的使用,我们正在添加对 CSS 导入的内置支持,包括开发环境的自动样式重载,以及生产环境的优化,这些在 next-css
插件中以前是无法实现的。
初始实现目前正在生产环境的 Next.js 应用中进行测试。
首先将引入全局 CSS 导入:
在全局 CSS 导入之后,我们将通过 .module.css
扩展名引入对 CSS 模块的支持:
这将为我们提供使用 CSS 导入时显著更好的开发者体验。
您可以在 GitHub 上的 RFC 中阅读更多关于正在进行的工作。
静态错误页面
Next.js 有一个在发生错误时渲染的特殊页面,内部称为 /_error
。用户可以通过创建导出 React 组件的 pages/_error.js
文件来自定义此页面。
渲染的错误通常分为两种情况:预期错误和意外错误。
预期错误例如 404
页面。
意外错误例如在 getInitialProps
中抛出错误或在渲染 React 树时出错,这会渲染 500
页面。
我们计划为预期错误添加 自动静态优化,因为通常它们不需要动态渲染。
如果用户希望动态渲染这些页面,可以选择退出,但默认情况下 404
将是一个静态页面。这减少了使用 server
目标时的服务器负载,以及使用 serverless
目标时的成本。
使页面静态化的另一个好处是,在使用 CDN 时可以自动缓存。
与 Google Chrome 的合作
如 Next.js 9 发布公告 中所述,Google Chrome 团队正在投入资源改进 Next.js,并致力于多项工作,为所有 Next.js 应用带来大规模性能提升。
要了解更多关于这次合作的信息,您可以阅读 Next.js 9 发布公告 并观看 Nicole Sullivan 在 React Rally 上的演讲。
Module/Nomodule
在 Next.js 中编写代码时,您通常编写的是"现代" JavaScript。您可以使用所有最新的稳定功能,Next.js 会通过使用 Babel 编译代码自动确保这些功能被转换或 polyfill。
目前,这些 JavaScript 功能大多已在主流浏览器中得到支持。然而,通常(包括在 Next.js 中)代码会作为单一的 JavaScript 包发送,在所有您的应用支持的浏览器中运行。
对于 Next.js 而言,这意味着将现代 JavaScript 编译为与 Internet Explorer 11 兼容的格式。
例如,目前 Next.js 必须为 async/await 语法提供 polyfill,因为代码可能在不支持 async/await 的浏览器中执行,这会导致错误。
为了避免破坏旧版浏览器,同时向支持新语法的浏览器发送现代 JavaScript,Next.js 将采用 module/nomodule 模式。module/nomodule 模式提供了一种可靠的机制,可以向现代浏览器提供现代 JavaScript,同时允许旧版浏览器回退到 polyfill 的 ES5 代码。
这个新功能目前正在多个大型 Next.js 生产应用中进行测试,以收集真实世界的数据。这些测试的结果看起来很有希望,关于这一变更的性能改进的更多细节将很快分享。
改进的代码分割
Next.js 目前有多个 JavaScript 包需要加载以使页面具有交互性。最值得注意的是:
- 页面 JavaScript 包
- 包含公共 JavaScript 的文件
- Next.js 客户端运行时包
- 动态导入(通常通过
next/dynamic
添加)
为了确保页面具有交互性,所有这些包都必须加载,因为它们都相互依赖,以便能够在浏览器中启动 React。
由于这些包是启动 React 所必需的,因此尽可能优化它们并且不过度下载应用的其他部分代码非常重要。
为此,有一个 commons
包,其中包含页面之间的公共 JavaScript。当前生成 commons
的代码分割策略计算基于比例启发式,如果一个模块在 50% 的页面中使用,它将被标记为公共模块。
然而,应用可能由许多不同的部分组成。例如,营销页面、博客和仪表盘。如果营销页面的数量远多于仪表盘,公共模块的计算会导致营销页面的优化结果更好。
我们的目标是同时优化这两者在一个应用中。
Alex Castle 定义了一个新的代码块分层(创建单独的 JavaScript 文件),允许多个文件进行更优化的公共代码块分割,特别是在涉及许多页面时。
与 module/nomodule 支持类似,改进的代码分割正在多个大型 Next.js 生产应用中进行测试,以收集真实世界的数据。这些测试的结果以及关于这一变更的性能改进的更多细节将很快在单独的博客文章中分享。
社区
我们对即将到来的变化感到兴奋,这些变化将提升所有 Next.js 应用的性能。
此外,Next.js 社区仍在不断壮大:
- 我们有超过 800 位贡献者提交了至少 1 次提交。
- 在 GitHub 上,该项目已获得超过 41,350 次星标。
- 示例目录 包含超过 210 个示例。
Next.js 社区现在有超过 11,250 名成员。加入我们!
我们感谢我们的社区以及所有帮助塑造这个版本的外部反馈和贡献。