阿里云飞天发布时刻,领先大模型限免,超7000万 tokens免费体验 了解详情
写点什么

Next.js 7.0 正式发布:重新编译速度提高 42%,支持 WebAssembly

  • 2018-10-13
  • 本文字数:7366 字

    阅读完需:约 24 分钟

在经过 26 次金丝雀发布和 340 万次下载之后,现在,我们正式推出生产就绪的 Next.js 7。

  • DX 改进:启动速度提高 57%,重新编译速度提高 42%;
  • 使用 react-error-overlay 更好地报告错误;
  • 编译管道升级:Webpack 4 和 Babel 7;
  • 标准化的动态导入;
  • 静态 CDN 支持;
  • 较小的初始 HTML 载荷;
  • App 和 Page 之间的 React Context(服务器端渲染)。

DX 改进

Next.js 的主要目标之一是提供最佳的性能和开发者体验。最新版本为构建和调试管道带来了很多重大改进。

得益于 Webpack 4 和 Babel 7,以及我们对代码库做出的很多改进和优化,Next.js 现在在开发过程中的启动速度提高了 57%。

我们新增了增量编译缓存,让变更代码的构建速度快了 40%。

以下是我们收集的一些示例数据:

因为使用了 webpackbar,在开发和构建的同时可以看到更好的实时反馈:

使用 react-error-overlay 更好地报告错误

准确地渲染错误对于良好的开发和调试体验来说是至关重要的。到目前为止,我们可以渲染错误消息和堆栈跟踪信息。我们在此基础上更进一步,我们使用 react-error-overlay 来丰富堆栈跟踪信息:

  • 准确的服务器端和客户端错误位置;
  • 高亮显示错误来源;
  • 完整的堆栈跟踪信息。

这是之前和之后的错误显示比较:

另外,借助 react-error-overlay,你只需单击特定代码块就可以轻松打开文本编辑器。

Webpack 4

从发布第一个版本以来,Next.js 一直使用 Webpack 来打包代码和重用丰富的插件。Next.js 现在使用了最新的 Webpack 4,其中包含很多改进和 bug 修复。

  • 支持.mjs 源文件;
  • 代码拆分改进;
  • 更好的摇树优化(删除未使用的代码)支持。

另一个新功能是支持 WebAssembly,Next.js 甚至可以进行 WebAssembly 服务器渲染,这里有一个例子

CSS 导入

因为使用了 Webpack 4,我们引入了一种从捆绑包中提取 CSS 的新方法,这个插件叫作 mini-extract-css-plugin

mini-extract-css-plugin 提供了 @zeit/next-css、@zeit/next-less、@zeit/next-sass 和 @zeit/next-stylus。

这些 Next.js 插件的新版本解决了与 CSS 导入相关的 20 个问题,例如,现在支持 import() 动态导入 CSS:

复制代码
// components/my-dynamic-component.js
import './my-dynamic-component.css'
export default () => <h1>My dynamic component</h1>
复制代码
// pages/index.js
import dynamic from 'next/dynamic'
const MyDynamicComponent = dynamic(import('../components/my-dynamic-component'))
export default () => <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 后来引入的一些功能,包括 import()。

例如,无法手动命名和捆绑某些文件:

import(/* webpackChunkName: 'my-chunk' */ '../lib/my-library')

另一个例子是在 next/dyanmic 模块之外使用 import()。

从 Next.js 7 开始,我们不再直接使用默认的 import(),Next.js 为我们提供了开箱即用的 import() 支持。

这个变更也是完全向后兼容的。使用动态组件非常简单:

import dynamic from 'next/dynamic'
const MyComponent = dynamic(import('../components/my-component'))
export default () => {
  return <div>
    <MyComponent />
  </div>
}

这段代码的作用是为 my-component 创建一个新的 JavaScript 文件,并只在渲染 <MyComponent/> 时加载它。

最重要的是,如果没有进行渲染,<script> 标记就不会出现在初始 HTML 文档中。

为了进一步简化我们的代码库并利用优秀的 React 生态系统,在 Next.js 7 中,我们使用 react-loadable 重写了 next/dynamic 模块。这为动态组件引入了两个很棒的新特性:

  • 使用 next/dynamic 的 timeout 选项设置超时;
  • 使用 next/dynamic 的 delay 选项设置组件加载延迟。例如,如果导入非常快,可以通过这个选项让加载组件在渲染加载状态之前等待一小段时间。

Babel 7

Next.js 6 中就已经引入了 Babel 7 测试版。后来 Babel 7 稳定版本发布,现在,Next.js 7 正在使用这个新发布的稳定版 Babel 7。

一些主要特性:

  • Typescript 支持,在 Next.js 中可以使用 @zeit/next-typescript;
  • 片段语法 <> 支持;
  • babel.config.js 支持;
  • 通过 overrides 属性将预设 / 插件应用于文件或目录的子集。

如果你的 Next.js 项目中没有自定义 Babel 配置,那么就不存在重大变更。

但如果你具有自定义 Babel 配置,则必须将相应的自定义插件 / 预设升级到最新版本。

如果你从 Next.js 6 以下的版本升级,可以使用 babel-upgrade 工具。

除了升级到 Babel 7 之外,当 NODE_ENV 被设置为 test 时,Next.js Babel 预设(next/babel)现在默认将 modules 选项设置为 commonjs。

这个配置选项通常是在 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%,让页面变得更加精简。

我们主要通过以下几种方式来缩小文件:

  • 移除 __next-error div;
  • 内联脚本被最小化,在未来的版本中,它们将被完全移除;
  • 去掉未使用的 __NEXT_DATA__ 属性,例如 nextExport 和 assetPrefix 属性。

静态 CDN 支持

在 Next.js 5 中,我们引入了 assetPrefix 支持,让 Next.js 可以自动从某个位置(通常是 CDN)加载资源。如果你的 CDN 支持代理,可以使用这种办法。你可以像这样请求资源:

https://cdn.example.com/_next/static/<buildid>/pages/index.js

通常,CDN 先检查缓存中是否包含这个文件,否则直接从源中请求文件。

不过,某些解决方案需要将目录直接预先上传到 CDN 中。这样做的问题在于 Next.js 的 URL 结构与.next 文件夹中的文件夹结构不匹配。例如我们之前的例子:

https://cdn.example.com/_next/static/<buildid>/pages/index.js
// 映射到:
.next/page/index.js

在 Next.js 7 中,我们改变了.next 的目录结构,让它与 URL 结构相匹配:

https://cdn.example.com/_next/static/<buildid>/pages/index.js
// 映射到:
.next/static/<buildid>/pages/index.js

尽管我们建议使用代理类型的 CDN,但新结构也允许不同类型 CDN 的用户将.next 目录上传到 CDN。

styled-jsx 3

我们也引入了 styled-jsx 3,Next.js 的默认 CSS-in-JS 解决方案,现在已经为 React Suspense 做好了准备。

如果一个组件不属于当前组件作用域的一部分,那么该如何设置这个子组件的样式呢?例如,如果你将一个组件包含在父组件中,并只有当它被用在父组件中时才需要特定的样式:

const ChildComponent = () => <div>
  <p>some text</p>
</div>

export default () => <div>
  <ChildComponent />
  <style jsx>{`
    p { color: black }
  `}</style>
</div>

上面的代码试图选择 p 标签,但其实不起作用,因为 styled-jsx 样式被限定在当前组件,并没有泄漏到子组件中。解决这个问题的一种方法是使用:global 方法,将 p 标记的前缀移除。但这样又引入了一个新问题,即样式泄露到了整个页面中。

在 styled-jsx 3 中,通过引入一个新的 API css.resolve 解决了这个问题,它将为给定的 syled-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 () => <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 和 Page 之间的 React Context(服务器端渲染)

从 Next.js 7 开始,我们支持 pages/_app.js 和页面组件之间的 React Context API。

以前,我们无法在服务器端的页面之间使用 React 上下文。原因是 Webpack 保留了内部缓存模块而不是使用 require.cache,我们开发了一个自定义 Webpack 插件来改变这种行为,以便在页面之间共享模块实例。

这样我们不仅可以使用新的 React 上下文,在页面之间共享代码时还能减少 Next.js 的内存占用。

社区

从 Next.js 首次发布以来,就已获得相当多的用户,从财富 500 强公司到个人博客。我们非常高兴看到 Next.js 的采用量一直在增长。

  • 目前,超过 12,500 个被公开索引的域名在使用 Next.js。
  • 我们有超过 500 名贡献者,他们至少提交过一次代码。
  • 在 GitHub 上,这个项目已经有 29,000 个 star。
  • 自首次发布以来,已提交了大约 2200 个拉取请求。

Next.js 社区在 spectrum.chat/next-js 上拥有近 2000 名成员。

英文原文: https://nextjs.org/blog/next-7

2018-10-13 07:223491
用户头像

发布了 731 篇内容, 共 467.8 次阅读, 收获喜欢 2006 次。

关注

评论 1 条评论

发布
暂无评论
发现更多内容

数据可视化大屏酷炫秘籍之前端开发者自己动手

葡萄城技术团队

前端 BI 可视化数据

中台“不火”了,企业“底座”却火了

BeeWorks

软件测试面试真题 | 请介绍一下Python中的深拷贝和浅拷贝

测试人

Python 软件测试 面试题 测试开发

“程”风破浪的开发者|架构师的思维转变

CTO技术共享

学习方法 架构师 “程”风破浪的开发者

“程”风破浪的开发者|Web 3.0 是泡沫还是金矿?

架构精进之路

1024 Web3.0 “程”风破浪的开发者

【网易云信】Sanitizers 系列之 address sanitizer 用法篇

网易智企

算法 开发语言

Flink 读写多套 Kerberos 认证的 Kafka 方案

移动云大数据

“程”风破浪的开发者|CTO浅谈数字化转型

CTO技术共享

学习方法 CTO 数字化转型 “程”风破浪的开发者

消失与存续——应用交付行业的跌宕演进

通明湖

负载均衡 高可用 云原生 信创

阿里最新产,SpringCloud微服务核心技术全解手册Github星标50k

程序员小毕

Java 微服务 后端 SpringCloud springcloudAlibaba

牛掰!阿里十年架构师总结的分布式原理、设计与实战笔记

小小怪下士

Java 程序员 面试 分布式

信息技术国产化浪潮中,云科通明湖如何助力企业转型蝶变?

通明湖

双活 高可用架构 自主可控

沉浸其境,共赴云栖数智硬核美学

阿里云CloudImagine

VR/AR 云栖大会 数智融合 超高清视频 云游戏

数据库浅析

Andy

MySql浅析

Andy

即时通讯IM WorkPlus支持国产化信创环境

BeeWorks

“程”风破浪的开发者|CTO浅谈数字化转型失败原因

CTO技术共享

学习方法 数字化转型 “程”风破浪的开发者

Sanitizers 系列之 address sanitizer 用法篇

网易云信

算法 语言 & 开发

如何引发一场信创负载均衡领域的大变革?

通明湖

负载均衡 信创

5000字解读《低代码发展白皮书(2022年)》

信通院IOMM数字化转型团队

低代码 无代码 低代码报告 IOMM

千企千面,WorkPlus面向政企提供个性化的数智办公平台解决方案

BeeWorks

API 动态更新 Upstream

通明湖

API upstream 动态更新

低代码又又又“出圈”了

优秀

低代码

云科通明湖:金融业务可持续性能力建设,少不了这块“拼图”!

通明湖

负载均衡

颠覆性突破重构企业价值

通明湖

负载均衡 云原生

浅谈长连接负载均衡

捉虫大师

负载均衡 长连接 10月月更

数字政府行业趋势洞察报告(2022年)解读

信通院IOMM数字化转型团队

数字政府 IOMM 政府数字化转型

NFT质押挖矿分红dapp系统开发功能介绍

开发微hkkf5566

云原生颠覆实践,可持续性应用创新引擎

通明湖

负载均衡 云原生

【10.21-10.28】写作社区优质技术博文回顾

InfoQ写作社区官方

优质创作周报

SAP | 如何全局处理消息文本

暮春零贰

SAP 10月月更 动态消息

Next.js 7.0正式发布:重新编译速度提高42%,支持WebAssembly_JavaScript_Next.js博客_InfoQ精选文章