经过足足70个canary版本之后,Next.js 9终于正式发布了!

经过足足70个canary版本之后,Next.js 9正式版终于发布了。新版的主要特性包括:

  • 内置零配置TypeScript支持:开发者可以借助自动化TypeScript支持和集成的类型检查更方便地构建应用。

  • 基于文件系统的动态路由:无需自定义服务器即可通过文件系统表达复杂的应用路由需求。

  • 自动静态优化:利用默认的服务端渲染和静态预渲染提升网站速度,同时不牺牲功能。

  • API路由:利用热重载和统一的构建管道快速构建后端应用程序端点。

  • 更多生产优化:通过视口内预取等优化提升应用的响应能力。

  • 提升开发体验:一系列细微、易用的改进,改善开发工作体验。

这些优势都会尽可能向后兼容。大多数Next.js应用只需运行下列代码即可升级到新版:

npm i next@latest react@latest react-dom@latest

应用代码库需要改动的情况很少。详细信息可参阅升级指南

基于Next.js的网站案例很多,包括IGN、Bang&Olufsen、Intercom、Buffer和Ferrari等等。更多案例可参见:https://nextjs.org/showcase

内置零配置TypeScript支持

一年前的Next.js 6通过名为@zeit/next-typescript的插件引入了TypeScript的基础支持。用户还必须自定义他们的.babelrc并在next.config.js中启用它。

这个插件配置好后允许Next.js构建.ts和.tsx文件。但它没有集成类型检查,也没有Next.js核心提供的类型。于是开发者必须在DefinitelyTyped中单独维护社区包,可能没法及时更新内容。

据调研,大多数新老用户都对使用TypeScript非常感兴趣。他们需要一种更可靠、更标准化的解决方案,从而将TypeScript轻松集成到现有或新的代码库中。

所以Next.js核心开始集成TypeScript支持,改善了开发人员的体验,并加快了相关流程。

自动安装

在Next.js中使用TypeScript非常简单:将任何文件、页面或组件从.js重命名为.tsx,然后运行next dev即可。

随后Next.js就会知道项目中正在使用TypeScript了。Next.js CLI将指导开发者为React和Node.js安装必要的类型。

Next.js还将创建一个默认的tsconfig.json,其中包含一些默认值(如果尚未存在)。此文件可以用来在Visual Studio Code等编辑器中进行集成类型检查。

Next.js 9自动TypeScript设置

集成类型检查

Next.js会在开发者开发和生产构建时处理类型检查。

在开发过程中,Next.js会在保存文件后显示类型错误。类型检查在后台执行,应用更新会立即反映在浏览器中。类型错误一旦可用就会传到浏览器中。

Next.js 9开发时类型检查

如果存在类型错误,Next.js会自动让生产构建失败(例如下图中的“next build”)。这样错误的代码就不会进入生产版本。

Next.js 9生产类型检查

用TypeScript编写的Next.js核心

现在Next.js的大部分代码库已经迁移到TypeScript上,不仅增强了Next.js的代码质量,而且现在所有核心模块都提供了类型。

例如,当导入next/link时,支持TypeScript的编辑器将显示允许的属性以及它们接受的值。

Next.js核心类型

动态路由

动态路由(也称为URL Slugs或Pretty/Clean URL)是两年半前Next.js发布后,GitHub上的第一批功能请求之一。

Next.js 2.0引入了自定义服务器API,开发者能以编程方式使用Next.js,“解决”了这个需求。Next.js可以作为呈现引擎,启用传入URL的抽象和映射以呈现某些页面。

据官方调研,许多应用都使用了自定义服务器。自定义服务器最常见的用途是动态路由。

但是自定义服务器也有自己的缺陷:路由在服务器级而不是代理级处理,它作为整体部署和扩展,并且容易出现性能问题。

由于自定义服务器要求整个应用程序跑在一个实例上,通常很难把它部署到无服务器环境来解决上述问题。无服务器请求是在代理层路由的,并独立扩展/执行以消除性能瓶颈。

开发者创建一个名为pages/blog.js的文件后就能在/blog下面有一个可访问页面了,然后就进入了Next.js的魔法世界。那么为什么用户需要创建自己的服务器,还要学习Next.js的可编程API才能支持像/blog/my-first-post (/blog/:id)这样的路由呢?官方开始探索新的路由映射方案,新的解决方案从pages/目录入手。

创建动态路由页面

Next.js支持使用基本命名参数创建路由,这是一种由path-to-regexp(Express的库)推广的模式。

现在开发者可以在pages目录中创建名为:pages/post/[pid] .js的文件来创建与/post/:pid路由匹配的页面了。

Next.js将自动匹配/post/1、/post/hello-nextjs等请求,并呈现pages/post/[pid] .js中定义的页面。匹配的URL段将作为查询参数传递到你的页面,其名称在[方括号]之间指定。

例如:给定以下页面和/post/hello-nextjs请求,查询对象将是{pid:‘hello-nextjs’}:

static async getInitialProps({ query }) {
//pid = 'hello-nextjs'
  const { pid } = query

  const postContent = await fetch(
    `https://api.example.com/post/${encodeURIComponent(pid)}`
  ).then(r => r.text())

  return { postContent }
}

新版还支持多个动态URL段。

目录名称和文件名支持[param]语法,示例如下:

./pages/blog/[blogId]/comments/[commentId].js
./pages/posts/[pid]/index.js

更多信息可参考Next.js文档Next.js学习部分

自动静态优化

Next.js在大约两年前发布的v3版本中增加了对静态网站生成的支持。

理由很简单:静态网站速度很快,它们不需要服务器端计算,数据可以立即从CDN服务器传输到最终用户。

但是,之前的版本中服务端呈现或静态生成的应用程序不可兼得,要么选择服务端呈现要么是静态生成,没有中间答案。

实际上应用可以有不同的需求。这些需求需要不同的呈现策略和取舍。

例如,主页和营销页面通常包含静态内容,是静态优化的理想场景。

另一方面,产品介绍页可能更适合数据频繁更新的服务端呈现。

于是官方开始探索更好的方案,试图为每个场景自动选择最快的途径,比如为宣传页面静态输出,为介绍页面做动态服务端呈现。

从Next.js 9开始,用户无需在完全服务器呈现或静态导出其应用之间做二选一了。新版可以在不同页面上使用不同的策略。

自动部分静态导出

新版引入了一种启发式方法来自动确定页面是否可以预呈现为静态HTML。

程序使用getInitialProps判断页面是否有阻止数据的需求来作出选择。

这样一来,Next.js就可以创建同时包含服务器呈现和静态生成页面的混合应用

内置的Next.js服务器(next start)和编程API(app.getRequestHandler())都透明地支持这种构建输出。无需配置或特殊处理。

静态生成的页面仍然是反应式的:Next.js将为应用客户端进行hydrate操作,使其具有完整的交互性。

此外,如果页面依赖于URL中的查询参数,Next.js将在hydrate操作后更新你的应用程序。

在开发期间静态生成页面时Next.js会弹出通知告知开发者。单击通知即可隐藏。

Next.js静态优化指标

静态生成的页面也将显示在Next.js的构建输出中:

Next.js构建输出类型指示

API路由

许多情况下,开发者在构建React应用程序时需要某种后端,用来从数据库检索数据或处理用户提供的数据(例如联系表单)。

官方调研发现许多需要后端的用户使用自定义服务器构建了他们的API,结果遇到了很多问题。例如,Next.js不编译自定义服务器代码,这意味着开发者无法使用导入/导出或TypeScript。

因此许多用户最后在自定义服务器之上实现了他们自己的自定义编译管道。虽然这解决了他们的需求,但也容易出现许多陷阱:例如,树抖动(tree shaking)配置不正确时会在整个应用程序中禁用。

现在Next.js 9引入了API路由,为开发者构建后端带来了最佳体验。

要开始使用API​​路由,请在pages/目录中创建名为api/的目录。

此目录中的任何文件都将自动映射到/api/<你的路径>,就像其他页面文件映射到路由一样。

例如,pages/api/contact.js将映射到/api/contact。

注意:API路由也支持动态路由。

pages/api/目录中的所有文件都导出一个请求处理函数,而不是React组件:

export default function handle(req, res) {
  res.end('Hello World')
}
  • req指的是扩展http.IncomingMessage的NextApiRequest。

  • res指的是扩展http.ServerResponse的NextApiResponse。

通常来说,API端点接收一些传入数据,例如查询字符串、请求正文或cookie,并使用其他数据响应。

官方调研发现,许多情况下用户没有直接使用Node.js请求和响应对象。相反,他们使用了像Express这样的服务器库提供的​​抽象。

这样做的原因是,在许多情况下传入数据是某种形式的文本,必须首先解析才有用。因此用这些服务器库后就不用手动解析数据了,最常见的方式是通过中间件。最常用的中间件提供了查询字符串、正文和cookie解析的功能,但是它们仍然需要做一些设置才能用。

Next.js中的API路由将默认提供这些中间件,以便开发者快速高效地创建API端点:

export default function handle(req, res) {
  console.log(req.body)//The request body
  console.log(req.query)//The url querystring
  console.log(req.cookies)//The passed cookies
  res.end('Hello World')
}

除了使用传入数据,API端点通常也会返回数据,通常返回的是JSON。默认情况下,Next.js提供res.json()以简化发送操作:

export default function handle(req, res) {
  res.json({ title: 'Hello World' })
}

在开发中更改API端点时,代码会自动重新加载,因此无需重新启动服务器。

生产优化

预取视口内的<Link>

Next.js 9将自动预取出现在视口内(in viewport)的<Link>组件。

此功能可以加快跳转到新页面的速度,从而提高应用程序的响应速度。

Next.js使用Intersection Observer预取后台必需的资源(https://www.w3.org/TR/resource-hints/#prefetch)。

这些请求优先级较低,并且产生fetch()或XHR请求。如果用户启用了数据保护,Next.js将避免自动预取。

在用户很少访问的页面上将prefetch属性设置为false即可关闭此功能:

<Link href="/terms" prefetch={false}>
  <a>Terms of Service</a>
</Link>

默认的AMP优化

Next.js 9现在默认为AMP(移动页面加速)优先和混合AMP页面呈现优化的AMP。

虽然AMP页面是可选的,但Next.js会自动优化其输出。这些优化可以使呈现速度提高50%。

这里要感谢Sebastian Benz为AMP Optimizer带来的改进。

typeof window分支的无效代码清理

Next.js 9在服务器和客户端构建期间用适当的值(undefined或object)替换typeof window。此更改使Next.js可以自动从生产构建的应用程序中删除无效代码。

如果用户在getInitialProps或应用程序的其他部分中写了纯服务端代码,那么就能注意到客户端包变小了。

改善开发体验

编译指示器

在之前的版本中,开发者只能查看开发者控制台才能知道热代码替换即将执行(并且Next.js编译工具链正在工作)。

然而很多时候,人们正在查看生成的呈现,很难知道Next.js是否仍在编译。例如,开发者可能正在对页面上的样式做些小改动,结果没法第一时间知道它们是否已更新过。

官方为此创建了一个RFC/“第一个好问题”的页面,以探讨这个问题的可行解决方案。

官方收到了许多设计师和工程师在RFC上的反馈。其中Rafael Almeida借此机会与官方团队合作,实现了一个全新的指标,并引入了Next.js 9。

现在每当Next.js执行编译工作时,开发者会看到页面右下角出现一个小三角形。

Next.js编译指标

控制台输出

传统上,开发者在开发中进行更改时,Next.js会显示一个编译指示器状态,并在开发者作出更改时清屏。

这种行为会导致一些问题。最值得注意的是,它会从应用程序代码中清除控制台输出,例如,当你将console.log添加到组件时就会这样。使用外部工具将日志输出拼接在一起时也会清除控制台输出,如Now CLI或docker-compose。

从Next.js 9开始日志输出跳跃变少,也不再清屏。这样可以提供更好的体验,因为终端窗口将显示更多相关信息,闪烁也更少了,同时Next.js能更好地与你正在使用的工具集成。

Next.js开发控制台输出

这里特别感谢Justin Chase的贡献。

构建输出统计

使用next build构建生产应用时,它将为你提供所有已构建页面的详细视图。

每个页面都会自动收到一些统计信息

最显眼的是包大小。随着应用程序的增长,你的JavaScript包也会变大,这个构建时指示可以告诉开发者生产包变大了多少。将来的版本中开发者还可以为生产构建失败的页面设置性能预算

Next.js构建出的页面大小

除了包大小,新版还展示了每个页面中使用了多少个项目组件和node_modules组件,以帮助开发者了解页面的复杂度。

Next.js页面包计数

每个页面还有一个指示,告诉开发者它是静态优化还是服务端呈现,因为每个页面的行为都可能不一样。

Next.js构建页面类型

每页配置对象

现在每个页面都可以导出配置对象。一开始这个配置允许你选择启用AMP,但将来你能配置更多页面特定选项。

//pages/about.js
export const config = { amp: true }

export default function AboutPage(props) {
  return <h3>My AMP About Page!</h3>
}

要选择混合AMP呈现,可以使用’hybrid’值:

//pages/about.js
import { useAmp } from 'next/amp'

export const config = { amp: 'hybrid' }

export default function AboutPage(props) {
  const isAmp = useAmp()
  return <h3>My About Page!{isAmp ? <> Powered by AMP!</> : ''}</h3>
}

新版删除了withAmp高阶组件,为新配置让路。

官方提供了一个codemod,可以自动将withAmp的用法转换为新的配置对象。更多信息可以参阅升级指南

代码库改进

新版对一些工具做了一些更改以提供更好的体验。

如前所述,Next.js核心现在是用TypeScript编写的,并且会自动为Next.js应用程序生成类型。这对使用Next.js构建的应用程序很有用,此外它在处理核心代码库时也很有帮助。现在开发者可以自动获得类型错误和自动完成时。

Next.js已经拥有了一个规模相当大的集成测试套件,包含50多个Next.js应用程序,每个应用程序都有针对自己运行的​​测试。通过这些测试,官方可以确保新版本发布时用户可以顺利升级,因为之前可用的功能是使用同一测试套件测试的。

大多数测试都是集成测试,可以复现“真正的”开发人员使用Next.js开发的过程。例如,一些测试可以复现对Next.js应用程序的更改,以查看热模块替换是否正常工作。

这些集成测试主要基于Selenium webdriver,它与chromedriver结合在一起测试无头Chrome。但随着时间的推移,其他浏览器,尤其是Internet Explorer 11等旧版浏览器会出现一些问题。

因为官方使用了Selenium,所以能够在多个浏览器上自动运行测试。

截至目前,官方正在Chrome、Firefox、Safari和Internet Explorer 11上运行这个测试套件。

谷歌Chrome协作

谷歌Chrome团队一直在通过提交RFC和pull request来改进Next.js。

双方合作的目标是大规模性能提升,重点是包大小、启动和hydrate时间。

例如,这些更改将改善小型网站的体验,也可以改善Hulu、Twitch和Deliveroo等大型应用程序的体验。

模块/Nomodule

合作的第一项重点任务是将新版JavaScript代码发布到支持新版JavaScript的浏览器上。

例如,当前Next.js必须为async/await语法提供polyfill,因为代码可能在不支持async/await的浏览器中执行。

Next.js Module/Nomodule合作RFC

为了在保持旧浏览器中正常运行应用的前提下向支持JS的浏览器发送新版JavaScript代码,Next.js将使用module/nomodule模式。这个模式提供了一种可靠的机制,可以将新版JavaScript代码提供给现代浏览器,同时仍允许旧版浏览器回退到polyfilled ES5。

此处有Next.js中的module/nomodule的RFC。

改进包拆分

Next.js中当前的包拆分策略使用基于比率的启发式算法,用于在单个“公共”块中包含模块。由于只有一个包的时候粒度非常小,因此会下载不必要的代码(因为公共块可能包含特定路由实际上不需要的代码),或者代码复制到了多个页面包中。

Next.js Chunking Collaboration RFC

此处有改进包拆分的RFC。

其他改进

Chrome团队还在对Next.js进行许多其他优化和更改。这些RFC将很快分享给开发者。

这些RFC和pull request标记为“协作”,以便在Next.js问题跟踪器中轻松找到它们。

社区

Next.js社区在继续成长。此版本有超过65位pull request作者提供核心改进或示例。

现在官方提供了200多个关于如何将Next.js与不同库和技术集成的示例,包括大多数css-in-js和数据获取库。

  • 已经有超过720名贡献者提交了至少1次贡献。

  • 在GitHub上,该项目已经得到了38,600星。

  • 自第一个版本发布以来已提交了超过3,400个pull request,自上次主要版本发布以来有超过800个。

  • 自上次主要版本发布以来,Spectrum.chat/next-js上的Next.js社区注册成员多了一倍,现在超过8,600人。

感谢社区以及帮助开发此版本的所有外部反馈和贡献。

英文原文:https://nextjs.org/blog/next-9#built-in-zero-config-typescript-support

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章