2020年10月27日,星期二
Next.js 10
发布者我们很高兴推出 Next.js 10,其特性包括
- 内置图像组件和自动图像优化:使用新的
next/image
组件自动优化图像 - 国际化路由:使用内置的基元开始国际化您的 Next.js 应用程序
- Next.js 分析:衡量真实用户性能并据此采取行动
- Next.js 商城:高性能电子商务网站的一体化入门套件
- React 17 支持:最新的 React 版本完全兼容 Next.js
getStaticProps
/getServerSideProps
快速刷新:编辑数据获取方法时自动重新加载属性- MDX 快速刷新:当使用
@next/mdx
时,现在利用快速刷新来应用更改,而无需完全重新加载页面 - 从第三方 React 组件导入 CSS:现在支持从 npm 导入组件所需的 CSS
href
的自动解析:as
属性在next/link
上不再需要@next/codemod
CLI:允许更轻松地访问所有 Next.js 代码修改getStaticPaths
的阻塞回退:在生成新的静态页面时等待预渲染,而不是提供静态回退页面
内置图像组件和自动图像优化
我们使用 Next.js 的目标是改进两件事:开发者体验和用户体验。
今年,我们已经在开发者体验和改进所有 Next.js 应用程序的性能方面投入了大量资金。我们专注于减少浏览器必须加载的 JavaScript 量。
我们推出了超过 20 项新功能,这些功能改进了性能和开发者体验。与此同时,Next.js 核心的 JavaScript 大小**减少了 16%**。
一月份,我们与 Google Chrome 团队合作,推出了一流的 JavaScript 代码分割策略。
例如,Barnebys 的**应用程序大小减少了 23%**,而 Sumup 的**最大 Javascript 包大小减少了 70%**。这些改进的实现**无需更改** Next.js 应用程序中的**任何代码**。
公司只需将 Next.js 升级到最新版本即可自动采用这一新策略。
Web 上的图像
虽然我们专注于减少浏览器必须加载的 JavaScript 量已取得成效,但 Web 不仅仅是 Javascript:它还包括标记和图像。
图像占网页总字节数的 50%。
图像对最大内容ful Paint 有很大影响,因为它们通常是页面加载时最大的可见元素。Largest Contentful Paint 是 Google 将很快在其搜索排名中使用的核心 Web Vital 。
所有图像中有一半以上的大小超过 1 兆字节,这意味着它们未针对在 Web 上显示进行优化。
如今,用户使用手机、平板电脑和笔记本电脑浏览 Web,但图像仍然是“一刀切”的。例如:网站加载 2000 x 2000 像素的图像,但手机仅将其显示为 100 x 100 像素。
此外,网页上 30% 的图像位于初始视口之外,这意味着浏览器加载了用户向下滚动页面后才看到的图像。
图像通常没有 width
和 height
属性,导致页面加载时它们会跳动。这会损害累积布局偏移核心 Web Vital。
网站上 99.7% 的图像未使用 WebP 等现代图像格式。
为了在网页上以高性能方式使用图像,必须考虑许多方面:大小、重量、懒加载和现代图像格式。
开发人员必须设置复杂的构建工具来优化图像,但是这些工具通常不涵盖来自外部数据源的用户提交的图像,从而无法优化所有图像。
这项不可能的开发任务不可避免地导致令人沮丧的最终用户体验。
Next.js 图像组件
我们很高兴宣布我们针对 Web 上高性能图像的解决方案:Next.js 图像组件和自动图像优化。
最基本的是,Next.js 图像组件只是 HTML <img>
元素的直接替代品,专为现代 Web 而发展。
<img
src="/profile-picture.jpg"
width="400"
height="400"
alt="Profile Picture"
/>
import Image from 'next/image';
<Image
src="/profile-picture.jpg"
width="400"
height="400"
alt="Profile Picture"
/>;
Google Chrome 团队帮助创建了这个 React 组件,通过使最佳实践成为默认设置来提高页面性能。
当使用 next/image
组件时,图像会自动懒加载,这意味着它们仅在用户接近看到图像时才呈现。这可以防止加载初始视口之外的 30% 图像。
强制执行图像尺寸,允许浏览器立即呈现图像所需的空间,而不是在加载时跳入,从而防止布局偏移。
虽然 HTML <img>
元素上的 width
和 height
可能会导致响应式布局出现问题,但**使用 next/image
时情况并非如此**。当使用 next/image
时,图像会根据提供的 width
和 height
的宽高比自动变为响应式。
开发人员可以标记初始视口中的图像,从而允许 Next.js 自动预加载这些图像。预加载初始视口中的图像已显示将 Largest Contentful Paint 提高了高达 50%。
自动图像优化
即使与 HTML <img>
元素相比有这些改进,仍然存在一个主要问题。2000 x 2000 像素的图像被发送到渲染较小图像的手机。
借助 Next.js 10,我们还在解决这个问题。next/image
组件将通过内置的图像优化自动生成更小的尺寸。
内置图像优化会自动以 WebP 等现代图像格式提供图像,如果浏览器支持,WebP 比 JPEG 小约 30%。它还允许 Next.js 自动采用**未来**的图像格式,并将它们提供给支持这些格式的浏览器。
图像优化适用于任何图像源。即使图像来自外部数据源(如 CMS),也会对其进行优化。
Next.js 10 不是在构建时优化图像,而是在用户请求时按需优化图像。与静态站点生成器和纯静态解决方案不同,无论您交付 10 个图像还是 1000 万个图像,您的构建时间都不会增加。
结论
新的 next/image
组件和自动图像优化是强大的新基元,将极大地改善用户体验。
next/image
组件处理自动懒加载、关键图像的预加载、跨设备的正确尺寸调整,并自动支持现代格式。这些功能适用于来自任何来源的图像。
我们期待看到您的用户体验通过这些新的基元变得更快。
有关更多详细信息,请查看 Next.js 图像组件和自动图像优化文档。
国际化路由
今年,一些企业和社区成员帮助我们的团队了解了国际化的重要性。
例如,我们了解到,如果您的网站已被翻译,则 72% 的消费者更有可能留在您的网站上,而 55% 的消费者表示他们只从其母语的电子商务网站购买商品。
如果您计划在其他国家/地区上市,则国际化您的项目对于成功至关重要。
国际化项目有两个主要支柱:翻译和路由。
许多 React 库准备应用程序进行翻译,但它们中的大多数都希望您手动处理路由,并且通常仅适用于一种渲染策略。
因此,作为 Next.js 10 的一部分,我们发布了对国际化路由和语言检测的内置支持。
这种对国际化路由的内置支持支持 Next.js 的混合策略,因此您可以根据每个页面在静态生成或服务器端渲染之间进行选择。
Next.js 10 支持两种最常见的路由策略:子路径路由和域路由。
对于这两种策略,您首先需要在 Next.js 配置中配置区域设置。
module.exports = {
i18n: {
locales: ['en', 'nl'],
defaultLocale: 'en',
},
};
区域设置是 UTS 区域设置标识符,这是一种用于定义区域设置的标准化格式。
通常,区域设置标识符由语言、区域和脚本组成,并用破折号分隔:language-region-script
。区域和脚本是可选的。例如
en-US
- 美国英语nl-NL
- 荷兰荷兰语nl
- 荷兰语,无特定地区
配置区域设置后,您可以选择子路径路由或域路由。
子路径路由
子路径路由将区域设置放在 URL 中。这允许所有语言存在于单个域上。
例如,您可以将区域设置插入 URL 中,例如 /nl-nl/blog
和 /en/blog
。
域路由
域路由使您能够将区域设置映射到顶级域。例如 example.nl
可以映射到 nl
区域设置,而 example.com
可以映射到 en
区域设置。
域路由需要一些额外的配置才能知道如何路由域
module.exports = {
i18n: {
locales: ['en', 'nl'],
domains: [
{
domain: 'example.com',
defaultLocale: 'en',
},
{
domain: 'example.nl',
defaultLocale: 'nl',
},
],
},
};
语言检测
Next.js 10 在 /
路由上基于 Accept-Language
标头内置了语言检测,所有现代浏览器都支持该标头。配置的区域设置将与 Accept-Language
标头匹配,然后根据配置的策略进行重定向。
搜索引擎优化
由于 Next.js 知道用户访问页面的语言,它将自动将 lang 属性添加到 <html>
标记。
Next.js 不知道页面的变体,因此由您使用 next/head
添加 hreflang
元标记。您可以在 Google 网站站长文档 中了解有关 hreflang
的更多信息。
Next.js 中国际化的未来
国际化路由是使国际化和本地化您的项目更轻松的一系列功能中的第一个。国际化路由允许与大多数 React 国际化库集成。
要了解有关国际化路由的更多信息,请查看 国际化路由文档。
Next.js 速度洞察
在 Vercel,我们知道您无法修复您无法衡量的东西。
您的访客对网站性能越来越敏感。如果您的网站加载时间超过 3 秒,则超过 50% 的访客会放弃您的网站 。 如果您从事电子商务,许多人发现将加载时间缩短十分之一秒会导致转化率提高 1% 。
由于性能对您的成功至关重要,我们很荣幸发布 Next.js 速度洞察。这是跟踪真实世界性能指标并将这些见解反馈到您的开发工作流程中的解决方案。
使用 Next.js 速度洞察
您现在将持续衡量,而不是衡量一次。
测量将来自您的访客正在使用的实际设备,而不是在您的开发设备上进行测量。
Next.js 速度洞察旨在关注整体情况,深入了解您的受众,以及您的应用程序对用户的性能表现。
我们如此坚定地收集真实数据,是因为性能不佳的原因并不总是最明显的。性能回归可能来自各种地方——第三方脚本和样式表,或第一方字体、图像和视频,它们过大或速度缓慢。
核心 Web Vitals
Google 与 Web Performance Working Group 合作,建立了一组指标来准确衡量用户体验您网站性能的方式:恰如其分地命名为 Web Vitals。Web Vitals 是衡量您网站的感知加载速度、响应速度和视觉稳定性的指标——所有这三者对于网站的整体健康状况至关重要!
感知加载速度可以通过 Largest Contentful Paint 或页面所有内容何时显示来衡量。例如,当我打开一个链接购买一双运动鞋时——在我看到我的运动鞋、它们的价格和添加到购物车按钮之前所经过的时间就是 LCP。
页面响应速度可以通过 First Input Delay 来衡量,它衡量您的用户必须等待多长时间才能看到他们与页面的第一次交互的反应。例如,我点击“添加到购物车”和购物车中商品数量增加之间的时间间隔是 FID。
最后,视觉稳定性可以通过累积布局偏移来衡量,或者元素在显示给用户后移动了多少。例如,我们都经历过尝试点击一个按钮的挫败感,该按钮因为图像加载延迟而移动了——这就是布局偏移。
围绕这些 Web Vitals 对您的真实用户进行持续测量和一致性至关重要。这是真正了解您的网站对用户表现的唯一方法。您网站的性能可能会因用户的设备及其网络条件或他们与页面的交互方式而异。加载个性化内容或广告的网站也可能会遇到用户与用户之间性能差异很大的情况。
模拟测试无法捕获这些重要信号。
Next.js 速度洞察允许您捕获真实世界的见解,而不是综合基准。它支持持续的测量流,而不是依赖偶尔的测试,从而确保它成为您开发工作流程的一部分。
Next.js 速度洞察允许您捕获真实世界的见解,而不是综合基准。它支持持续的测量流,而不是依赖偶尔的测试,从而确保它成为您开发工作流程的一部分。
访问 nextjs.org/analytics 了解如何立即在您的应用程序中启用它。
Next.js 商城
电子商务是 Web 最重要的用途之一。新的 Next.js 10 功能是电子商务的强大新工具。
因此,今天,我们与 BigCommerce 合作发布了 Next.js Commerce,这是电子商务网站的一体化 React 入门套件。只需点击几下,Next.js 开发人员就可以克隆、部署和完全自定义它。立即访问 nextjs.org/commerce 开始使用。
React 17 支持
React 17 对 Next.js 没有重大更改,但仍需要进行一些维护性更改,例如更新 peerDependencies。新的 JSX 转换 在使用 React 17 时会自动启用,无需进行任何配置更改。
要开始使用 React 17,您只需升级 Next.js 和 React 即可
npm install next@latest react@latest react-dom@latest
getStaticProps
/ getServerSideProps
快速刷新
当您编辑 getStaticProps
和 getServerSideProps
函数时,Next.js 现在会自动重新运行该函数并应用新数据。这使您可以更快地迭代,而无需刷新页面。
要了解更多关于 getStaticProps
和 getServerSideProps
的信息,您可以阅读数据获取文档。
MDX 快速刷新
当将 Next.js 与 MDX 结合使用(通过 @next/mdx
)时,更改 MDX 内容现在将利用快速刷新,确保浏览器在编辑时不必重新加载页面。
@next/mdx
文档 指导您如何在 Next.js 中设置 MDX。
从第三方 React 组件导入 CSS
您现在可以在 React 组件内部导入第三方 CSS。这允许对仅用于单个组件的 CSS 进行代码拆分。例如,您现在可以使用 react-datepicker
库,而无需在 _app.js
中导入 CSS
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
function MyComponent() {}
您可以参考内置 CSS 支持文档,以了解更多关于 Next.js 如何处理 CSS 导入的信息。
自动解析 href
如果您以前使用过动态路由,您可能遇到过需要为 next/link
提供 href
和 as
属性的情况。它看起来像这样
<Link href="/categories/[slug]" as="/categories/books" />
这允许 Next.js 为动态参数插值 href,但是,当开发人员忘记添加 as
或在 href
中添加 as
时,会导致页面转换不使用客户端路由,从而引起摩擦。
几个月前,我们着手解决开发人员的这种摩擦,主要目标是改善开发人员体验和最终用户体验。我们逐步努力寻找一种允许自动解析 href
的解决方案。
我们很高兴地宣布,作为 Next.js 10 的一部分,您不再需要在大多数用例中使用 as
属性。消除开发人员的摩擦并改善最终用户体验。
此更改完全向后兼容,如果您当前同时使用 href
和 as
,则现有行为将保留。
为了采用自动 href
解析,您只需更改 next/link
的用法,使其仅使用 href
保存您以前在 as
属性中拥有的值即可。
<Link href="/categories/books" />
要了解更多关于 next/link
和客户端路由的信息,您可以参考 next/link
文档。
@next/codemod
CLI
我们致力于通过广泛的向后兼容性来确保 Next.js 升级尽可能顺利。这种承诺始于非常谨慎地弃用功能,同时引入新的和更好的解决方案来替代它们。除了这项承诺之外,我们还为所有 Next.js 功能进行了广泛的集成测试,包括复制本地开发的测试。
当 Next.js 中的某个功能被弃用并需要进行大型代码库更改时,我们的团队会为其创建一个 codemod。Codemod 是一种自动化代码转换,您可以在项目上运行它来更新源代码。
例如:我们发布了一个 codemod,用于将箭头函数和匿名函数更新为命名函数。此转换是必需的,因为否则 React Fast Refresh 不会将该函数检测为有效的 React 组件。同样,React hooks eslint 规则也不会将该函数识别为 React 组件。
在 Next.js 10 中,我们发布了一个新的 Next.js codemods CLI 工具,使您可以通过运行单个命令来更新您的应用程序:npx @next/codemod <转换> <路径>
。
要了解更多关于 codemods 的信息,您可以查看Next.js Codemods 文档。
getStaticPaths
的阻塞回退
在 Next.js 9.3 中,我们引入了 getStaticProps
和 getStaticPaths
,以及在 getStaticPaths
中返回 fallback
属性的功能。fallback
属性允许生成额外的静态页面,而无需完全重建,最初提供一个静态 HTML 文件,然后在后续请求中被完全渲染的内容替换。在过去的几个月中,我们收到了许多公司的反馈,他们想要一种类似但略有不同的行为:当用户首次请求页面时进行阻塞预渲染。在初始渲染之后,该页面将重用于后续请求。
在 Next.js 10 中,我们正在解决这种情况。
我们很高兴地宣布 getStaticPaths
的新 fallback: 'blocking'
模式,该模式启用阻塞行为,其中不向浏览器发送静态回退。相反,初始请求将被等待以进行预渲染。
export function getStaticPaths() {
return {
// enables blocking mode for the fallback behavior
fallback: 'blocking',
};
}
要了解更多关于增量生成额外静态页面的 fallback
行为的信息,您可以参考 fallback
文档。
getStaticProps
/ getServerSideProps
的重定向和 notFound 支持
自从引入 getStaticProps
和 getServerSideProps
以来,我们注意到用户在某些情况下需要返回重定向和 404 响应。为了帮助简化这些情况,我们现在允许从 getStaticProps
和 getServerSideProps
返回两个新字段:notFound
和 redirect
。
notFound
支持
当返回 notFound
字段为 true
时,将返回默认的 404 页面,状态代码为 404
。这使您可以避免使用 SSG 生成额外的页面,并且不必手动处理渲染 404 页面。
export function getStaticProps() {
return {
// returns the default 404 page with a status code of 404
notFound: true,
};
}
redirect
支持
现在可以返回重定向,其中包含 destination
以及重定向是否应为永久性,例如 permanent: true
。在需要使用特定状态而不是默认状态的情况下,也可以返回可选的 statusCode
来代替 permanent
字段。
export function getStaticProps() {
return {
// returns a redirect to an internal page `/another-page`
redirect: {
destination: '/another-page',
permanent: false,
},
};
}
export function getServerSideProps() {
return {
// returns a redirect to an external domain `example.com`
redirect: {
destination: 'https://example.com',
permanent: false,
},
};
}
结论
我们很高兴看到 Next.js 的采用持续增长
- 我们拥有超过 1,300 位独立贡献者,自 9.5 版本发布以来新增了超过 120 位贡献者
- 在 GitHub 上,该项目已获得超过 54,800 次 star。
加入 Next.js 社区,请访问 GitHub Discussions。 Discussions 是一个社区空间,您可以在这里与其他 Next.js 用户联系,自由提问或分享您的工作。
鸣谢
我们感谢我们的社区,包括所有帮助塑造此版本的外部反馈和贡献。
此版本由以下贡献者共同完成:@ijjk, @adebiyial, @elliottsj, @saintmalik, @HaNdTriX, @prateekbh, @amirsaeed671, @paambaati, @imagentleman, @gregrickaby, @Janpot, @atcastle, @Kirkhammetz, @remorses, @davidsonsns, @kmkzt, @slawekkolodziej, @Timer, @styfle, @timneutkens, @ykzts, @ashconnell, @orYoffe, @lfades, @justinwhall, @fbaiodias, @ludofischer, @felipeguilhermefs, @gr-qft, @TasukuUno, @YichiZ, @weichienhung, @seosmmbusiness, @HsuTing, @gsimone, @peduarte, @ztanner, @neighborhood999, @chibicode, @merceyz, @opudalo, @lunchboxav, @mohsen1, @akd-io, @justman00, @helloworld, @devknoll, @borekb, @ArthurMaverick, @sakito21, @TrySound, @omBratteng, @svenheden, @hallaji, @kettanaito, @vvo, @m-lautenbach, @jensmeindertsma, @Zeko369, @longlho, @stefanprobst, @laugharn, @sdornan, @daneroo, @mohd-akram, @austingmhuang, @sphilee, @devinekadeni, @Bacher, @nghiepit, @tomasdisk, @leader22, @paulogdm, @284km, @belgattitude, @geritol, @stigkj, @sampoder, @samrobbins85, @Pitasi, @digitalPlayer1125, @timfee, @plug-n-play, @philihp, @leerob, @dylanjha, @Kerumen, @rdimaio, @jorisw, @zerbinidamata, @jamesgeorge007, @Jashnm, 和 @futantan!