经过 26 个 canary 版本迭代和 340 万次下载后,我们自豪地推出生产就绪的 Next.js 7,主要特性包括:
- 开发者体验优化:启动速度提升 57%,重新编译提速 42%
- 更完善的错误报告,采用 react-error-overlay
- 升级编译工具链:支持 Webpack 4 和 Babel 7
- 标准化动态导入
- 静态 CDN 支持
- 更精简的初始 HTML 负载
- App 与 Pages 间的服务端渲染 (SSR) React Context 支持
值此之际,我们很高兴通过全新改版的 Nextjs.org 与您分享这些更新
开发者体验优化
Next.js 的核心目标之一是:在提供最佳生产性能的同时,打造极致的开发者体验。本次版本对构建和调试流程进行了多项重要改进
编译速度
得益于 webpack 4、Babel 7 以及代码库的多项优化,Next.js 开发环境启动速度最高提升 57%。
通过引入增量编译缓存机制,代码变更后的构建速度可提升 40%。
以下是我们收集的基准测试数据:
6.0 | 7.0 | 差异 | |
---|---|---|---|
基础应用启动时间 | 1947ms | 835ms | 57% 提升 |
基础应用代码变更 | 304ms | 178ms | 42% 提升 |
额外福利:得益于 webpackbar,您现在能在开发和构建过程中获得更直观的实时反馈:
React 错误覆盖层增强错误报告
准确且友好的错误提示对开发和调试体验至关重要。此前我们仅展示错误信息和堆栈跟踪,现在通过集成 react-error-overlay
,堆栈跟踪将包含:
- 服务端与客户端错误的精确定位
- 源码高亮提供上下文
- 完整的增强型堆栈跟踪
下图展示了错误提示的对比改进:
额外福利:通过 react-error-overlay
,点击代码块即可快速在编辑器中打开对应文件。
Webpack 4
自首个版本起,Next.js 就采用 webpack 进行代码打包,并复用其丰富的插件生态。我们很高兴宣布 Next.js 现已升级至最新的 webpack 4,带来诸多改进和错误修复。
主要升级包括:
- 支持
.mjs
源文件 - 代码分割优化
- 更完善的 tree-shaking(无用代码消除)支持
新特性还包括 WebAssembly 支持,Next.js 甚至能服务端渲染 WebAssembly,参见此示例。
注意: 本次升级完全向后兼容。但如果您通过 next.config.js 使用自定义 webpack 加载器或插件,可能需要相应升级。
CSS 导入
webpack 4 引入了新的 CSS 提取方案 mini-extract-css-plugin。
@zeit/next-css
、@zeit/next-less
、@zeit/next-sass
和 @zeit/next-stylus
现已基于 mini-extract-css-plugin
重构。
新版插件解决了 20 个与 CSS 导入相关的问题,例如现在支持在动态 import()
中导入 CSS:
重大改进是您不再需要在 pages/_document.js
中添加以下代码:
Next.js 现在会自动注入 CSS 文件。在生产环境中,还会自动为 CSS URL 添加内容哈希,确保用户永远不会获取过时文件,并支持永久不可变缓存。
简言之,要在 Next.js 项目中支持导入 .css
文件,只需在 next.config.js
中注册 withCSS 插件:
标准化动态导入
自版本 3 起,Next.js 就通过 next/dynamic
支持动态导入。
作为该技术的早期采用者,我们当时不得不自行实现 import()
处理方案。
这导致 Next.js 逐渐与 webpack 后续引入的原生支持产生差异,某些功能缺失。
因此 Next.js 之前无法支持 webpack 后来引入的部分 import()
特性。
例如无法手动指定分块名称和捆绑文件:
另一个例子是无法直接使用 import()
而必须通过 next/dynamic
模块包装。
从 Next.js 7 开始,我们不再修改默认的 import()
行为,这意味着您能开箱即用地获得完整的 import() 支持。
此变更同样完全向后兼容。动态组件的使用方式依然简单:
此示例会为 my-component
创建独立的 JavaScript 文件,仅在渲染 <MyComponent />
时加载。
最重要的是,如果组件未被渲染,其 <script>
标签不会出现在初始 HTML 文档负载中。
为了简化代码库并利用 React 生态优势,Next.js 7 的 next/dynamic
内部重构为基于 react-loadable
(略有修改)。这还引入了两项动态组件新特性:
- 通过
next/dynamic
的timeout
选项设置超时 - 通过
delay
选项设置加载组件延迟时间。例如当导入速度极快时,可延迟显示加载状态
Babel 7
Next.js 6 在 Babel 7 尚处测试阶段时就已支持。如今 Babel 7 稳定版已发布,Next.js 7 也完成了升级。
完整变更请参阅 Babel 发布说明。
主要特性包括:
- TypeScript 支持(可通过
@zeit/next-typescript
实现) - 支持 Fragment 语法
<>
- 支持
babel.config.js
- 新增
overrides
属性,可针对特定文件或目录应用预设/插件
如果您的 Next.js 项目没有自定义 Babel 配置,则不存在破坏性变更。
若有自定义 Babel 配置,则需要将相关插件/预设升级至最新版本。
若从低于 Next.js 6 的版本升级,可运行优秀的 babel-upgrade
工具。
除升级至 Babel 7 外,Next.js Babel 预设 (next/babel
) 现在默认在 NODE_ENV=test
时将 modules
选项设为 commonjs
。
此前这通常是 Next.js 项目中创建自定义 .babelrc
的唯一原因:
在 Next.js 7 中简化为:
此时甚至可以移除 .babelrc
文件,因为 Next.js 会在没有 Babel 配置时自动使用 next/babel
。
更精简的初始 HTML 负载
Next.js 在预渲染 HTML 时,会将页面包裹在包含 <html>
、<head>
、<body>
和必要 JavaScript 文件的默认结构中。
此前初始负载约为 1.62kB。Next.js 7 优化后降至 1.5kB,缩减 7.4%,使页面更轻量。
6.0 | 7.0 | 差异 | |
---|---|---|---|
服务端渲染文档大小 | 1.62kb | 1.50kb | 7.4% 缩减 |
主要优化手段包括:
- 移除
__next-error
div - 压缩内联脚本(未来版本将完全移除)
- 编译时消除未使用的
__NEXT_DATA__
属性(如nextExport
和assetPrefix
)
静态 CDN 支持
Next.js 5 引入了 assetPrefix
支持,使资源能从指定位置(通常是 CDN)自动加载。此功能在 CDN 支持代理时效果最佳,例如请求如下 URL:
通常 CDN 会检查缓存,若无则从源站请求。
边缘网络 正是采用这种代理机制。
但某些解决方案要求直接将目录预上传至 CDN。问题在于 Next.js 的 URL 结构与 .next
文件夹内部结构不匹配。例如:
Next.js 7 调整了 .next
目录结构以匹配 URL 结构:
虽然我们推荐使用代理型 CDN,但新结构也支持用户将 .next
目录上传至其他类型 CDN。
Styled JSX v3
我们很高兴推出 styled-jsx 3,Next.js 默认集成的 CSS-in-JS 方案现已支持 React Suspense。
一个常见问题是:当子组件不属于当前组件作用域时,如何为其添加样式?例如当子组件仅在父组件中需要特定样式时:
上述代码尝试选择 p
标签但无效,因为 styled-jsx 样式仅作用于当前组件,不会泄漏到子组件。传统解决方案是使用 :global
方法移除 p
标签前缀,但这会导致样式泄漏到整个页面。
styled-jsx 3 通过引入新 API css.resolve
解决了此问题,它会为给定的 styled-jsx 字符串生成 className
和 <style>
标签(即 styles
属性):
此 API 支持透明地将自定义样式传递给子组件。
作为 styled-jsx 的主要版本升级,如果您使用 styles-jsx/css
,会有一项破坏性变更以优化包体积。在 styled-jsx 2 中,即使仅使用"scoped"版本,也会同时生成"scoped"和"global"版本的外部样式。
styled-jsx 3 要求全局样式必须通过 css.global
而非 css
标记,以便优化包体积。
完整变更请参阅发布说明。
App 与 Pages 间的服务端渲染 React Context
从 Next.js 7 开始,我们支持在 pages/_app.js
和页面组件间使用新版 React context API。
此前在服务端无法在页面间使用 React context。这是因为 webpack 使用内部模块缓存而非 require.cache,我们为此编写了自定义 webpack 插件来共享页面间的模块实例。
此改动不仅支持了新版 React context,还减少了 Next.js 在页面间共享代码时的内存占用。
6.0 | 7.0 | 差异 | |
---|---|---|---|
内存占用 | 57.5MB | 48.1MB | 16% 降低 |
nextjs.org
伴随 Next.js 7 发布,我们推出了全新设计的 nextjs.org。
博客
您正在阅读的这篇博客文章已收录于 nextjs.org 的新版博客板块。这里将成为 Next.js 相关资讯(如版本发布)的新主场。
全新 nextjs.org
获取灵感
随着使用 Next.js 的应用数量持续增长,我们需要一种方式来集中展示这些精美的应用。欢迎体验全新的 /showcase
页面:
在 nextjs.org/showcase 获取灵感
这个全新的展示平台让我们能够持续添加基于 Next.js 构建的新应用。
我们诚邀您访问 /showcase
获取灵感,或提交您使用 Next.js 开发的应用!
社区
自首次发布以来,Next.js 已被广泛应用于从世界 500 强企业到个人博客的各类场景。我们非常欣喜地见证了 Next.js 的普及增长:
- 目前有超过 12,500 个公开索引的域名正在使用 Next.js
- 已有超过 500 位贡献者提交了至少 1 次代码提交
- 该项目在 GitHub 上获得了超过 29,000 次星标
- 自首次发布以来已收到近 2200 个拉取请求
Next.js 社区拥有近 2000 名成员。立即加入我们!