2018年9月19日,星期三
Next.js 7
发布者经过 26 个 Canary 版本和 340 万次下载,我们很荣幸地推出生产就绪的 Next.js 7,其特性包括
- DX 改进:启动速度提升 57%,重新编译速度提升 42%
- 更好的错误报告,使用 react-error-overlay
- 升级的编译管道:Webpack 4 和 Babel 7
- 标准化的动态导入
- 静态 CDN 支持
- 更小的初始 HTML 负载
- 在 App 和 Pages 之间使用 SSR 的 React Context
最后,我们很高兴在新版的 Nextjs.org 上分享这个消息
DX 改进
Next.js 的首要目标之一是提供最佳的生产性能和尽可能最佳的开发者体验。此版本为构建和调试管道带来了许多重大改进
编译速度
得益于 webpack 4、Babel 7 以及我们代码库中的许多改进和优化,Next.js 在开发期间的启动速度现在提升了 57%。
得益于我们新的增量编译缓存,您对代码所做的更改现在将构建速度提升 40%。
以下是我们收集的一些示例数据
6.0 | 7.0 | 变化 | |
---|---|---|---|
启动时间(基本应用) | 1947毫秒 | 835毫秒 | 57% 更快 |
代码更改(基本应用) | 304毫秒 | 178毫秒 | 42% 更快 |
作为一项额外福利,在开发和构建时,由于 webpackbar,您现在将看到更好的实时反馈

使用 React Error Overlay 改进错误报告
渲染准确且有帮助的错误对于良好的开发和调试体验至关重要。到目前为止,我们只会渲染错误消息及其堆栈跟踪。展望未来,我们将使用 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
提供支持。
这些 Next.js 插件的新版本解决了 20 个与 CSS 导入相关的现有问题;例如,现在支持在动态 import()
中导入 CSS
import './my-dynamic-component.css';
export default function MyDynamicComponent() {
return <h1>My dynamic component</h1>;
}
import dynamic from 'next/dynamic'
const MyDynamicComponent = dynamic(import('../components/my-dynamic-component'))
export default function Index() {
return () {
<div>
<MyDynamicComponent/>
</div>
}
}
一个主要的改进是您不再需要在 pages/_document.js
中添加以下内容
<link rel="stylesheet" href="/_next/static/style.css" />
相反,Next.js 会自动注入 CSS 文件。在生产环境中,Next.js 还会自动向 CSS URL 添加内容哈希,以便在发生更改时,确保您的最终用户永远不会获得文件的过时版本,并有能力引入不可变的永久缓存。
简而言之,为了在您的 Next.js 项目中支持导入 .css
文件,您只需在您的 next.config.js
中注册 withCSS 插件
const withCSS = require('@zeit/next-css');
module.exports = withCSS({
/* my next config */
});
标准化的动态导入
自版本 3 以来,Next.js 就通过 next/dynamic
支持动态导入。
作为这项技术的早期采用者,我们不得不编写自己的解决方案来处理 import()
。
因此,Next.js 开始偏离 webpack 后来为其引入的支持,并且缺少某些功能。
因此,Next.js 不支持 webpack 自那时以来引入的一些 import()
功能。
例如,手动命名和捆绑某些文件是不可能的
import(/* webpackChunkName: 'my-chunk' */ '../lib/my-library');
另一个例子是使用 import()
而不将其包装在 next/dynamic
模块中。
从 Next.js 7 开始,我们不再触及默认的 import()
行为。这意味着您可以开箱即用地获得完整的 import() 支持。
此更改也完全向后兼容。使用动态组件仍然像以下一样简单
import dynamic from 'next/dynamic';
const MyComponent = dynamic(import('../components/my-component'));
export default function Index() {
return (
<div>
<MyComponent />
</div>
);
}
此示例的作用是为 my-component
创建一个新的 JavaScript 文件,并且仅在渲染 <MyComponent />
时加载它。
最重要的是,如果未渲染,则 <script>
标签不包含在初始 HTML 文档负载中。
为了进一步简化我们的代码库并利用出色的 React 生态系统,在 Next.js 7 中,next/dynamic
被重写以使用幕后的 react-loadable
(进行了一些小的修改)。这也为动态组件引入了两个很棒的新功能
- 使用
next/dynamic
上的timeout
选项设置超时 - 加载组件延迟,使用
next/dynamic
上的delay
选项。此延迟允许您的loading
组件在渲染加载状态之前等待 x 时间,例如,如果导入速度非常快。
Babel 7
Next.js 6 在 Babel 7 仍处于 beta 版时引入了它。从那时起,Babel 7 的稳定版本已经发布,而 Next.js 7 现在正在使用此版本。
有关更改的完整列表,您可以参考 Babel 的 发行说明。
一些主要功能包括
- Typescript 支持,对于 Next.js,您可以使用
@zeit/next-typescript
- Fragment 语法
<>
支持 babel.config.js
支持overrides
属性,用于仅将预设/插件应用于文件或目录的子集
如果您的 Next.js 项目中没有自定义 Babel 配置,则不会有重大更改。
但是,如果您确实有自定义 Babel 配置,则必须将相应的自定义插件/预设升级到最新版本。
如果您是从低于 Next.js 6 的版本升级,则可以运行出色的 babel-upgrade
工具。
除了升级到 Babel 7 之外,Next.js Babel 预设(next/babel
)现在默认将 modules
选项设置为 commonjs
,当 NODE_ENV
设置为 test
时。
此配置选项通常是在 Next.js 项目中创建自定义 .babelrc
的唯一原因
{
"env": {
"development": {
"presets": ["next/babel"]
},
"production": {
"presets": ["next/babel"]
},
"test": {
"presets": [["next/babel", { "preset-env": { "modules": "commonjs" } }]]
}
}
}
在 Next.js 7 中,这变成了
{
"presets": ["next/babel"]
}
此时,可以删除 .babelrc
,因为当没有 Babel 配置时,Next.js 将自动使用 next/babel
。
更小的初始 HTML 负载
由于 Next.js 预渲染 HTML,它会将页面包装到具有 <html>
、<head>
、<body>
和渲染页面所需的 JavaScript 文件的默认结构中。
此初始负载以前约为 1.62kB。在 Next.js 7 中,我们优化了初始 HTML 负载,现在为 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
支持,这是一种使 Next.js 能够自动从特定位置(通常是 CDN)加载资源的方法。如果您的 CDN 支持代理,则此选项效果很好,您可以请求类似以下的 URL
https://cdn.example.com/_next/static/<buildid>/pages/index.js
通常,CDN 会检查其缓存中是否包含该文件,否则直接从源服务器请求该文件。
代理资源正是 Edge Network 的工作方式。
但是,某些解决方案需要将目录直接预先上传到 CDN 中。这样做的问题是 Next.js 的 URL 结构与 .next
文件夹内的文件夹结构不匹配。例如我们之前的示例
https://cdn.example.com/_next/static/<buildid>/pages/index.js
// mapped to:
.next/page/index.js
在 Next.js 7 中,我们更改了 .next
的目录结构以匹配 URL 结构
https://cdn.example.com/_next/static/<buildid>/pages/index.js
// mapped to:
.next/static/<buildid>/pages/index.js
虽然我们确实建议使用代理类型的 CDN,但这种新结构允许不同类型的 CDN 用户将 .next
目录上传到他们的 CDN。
Styled JSX v3
我们很高兴推出 styled-jsx 3,Next.js 中默认包含的 CSS-in-JS 解决方案现在已为 React Suspense 做好准备。
经常不清楚的一件事是如何样式化子组件,如果该组件不属于当前组件范围,例如,如果您包含了一个子组件,该子组件仅在父组件内部使用时才需要特定样式
const ChildComponent = () => (
<div>
<p>some text</p>
</div>
);
export default function Index() {
return (
<div>
<ChildComponent />
<style jsx>{`
p {
color: black;
}
`}</style>
</div>
);
}
上面的代码尝试选择 p
标签不起作用,因为 styled-jsx 样式的作用域限定于当前组件,它们不会泄漏到子组件中。一种解决方法是使用 :global
方法,从 p
标签中删除前缀。但是,这引入了一个新问题,即样式会泄漏到整个页面。
在 styled-jsx 3 中,通过引入新的 API css.resolve
解决了此问题,该 API 将为给定的 styled-jsx 字符串生成 className
和 <style>
标签(styles
属性)
import css from 'styled-jsx/css';
const ChildComponent = ({ className }) => (
<div>
<p className={className}>some text</p>
</div>
);
const { className, styles } = css.resolve`
p {
color: black;
}
`;
export default function Index() {
return (
<div>
<ChildComponent className={className} />
{styles}
</div>
);
}
这个新的 API 允许将自定义样式透明地传递给子组件。
由于这是 styled-jsx 的主要版本,因此如果使用 styles-jsx/css
,则会有一个重大更改,可以改善捆绑包大小。在 styled-jsx 2 中,我们将生成外部样式的“scoped”和“global”版本,即使仅使用“scoped”版本,我们仍然会包含这些外部样式的“global”版本。
在 styled-jsx 3 中,全局样式必须使用 css.global
而不是 css
进行标记,以便 styled-jsx 可以优化捆绑包大小。
有关所有更改,请参阅 发行说明。
在 App 和 Pages 之间使用 SSR 的 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 相关的沟通新家,例如,新版本公告。

获取灵感
随着使用 Next.js 的应用程序数量持续增长,我们需要一种在一个概览中展示所有这些精美应用程序的方式。欢迎访问新的 /showcase
页面

这个新的案例展示使我们能够不断添加使用 Next.js 构建的新应用程序。
我们邀请您访问 /showcase
以获取灵感,或提交您使用 Next.js 构建的应用程序!
社区
自首次发布以来,Next.js 已被应用于从财富 500 强公司到个人博客的各种领域。我们非常高兴看到 Next.js 的采用率不断增长。
- 目前,有超过 12,500 个公开索引的域名正在使用 Next.js。
- 我们有超过 500 位贡献者提交了至少 1 次 commit。
- 在 GitHub 上,该项目已被 star 超过 29,000 次。
- 自首次发布以来,已提交了近 2200 个 pull request。
Next.js 社区拥有近 2000 名成员。 加入我们!