跳到内容
返回博客

2020年10月27日 星期二

Next.js 10

发布者

我们很高兴推出Next.js 10,其主要功能包括:

内置图像组件和自动图像优化

我们使用 Next.js 的目标是改进两件事:开发者体验和用户体验。

今年我们已经投入大量精力在开发者体验和提升所有 Next.js 应用程序的性能上。我们专注于减少浏览器需要加载的 JavaScript 代码量。

我们引入了超过 20 项新功能,提升了性能和开发者体验。同时,Next.js 核心的 JavaScript 文件大小已减少了 16%

1 月份,我们与 Google Chrome 团队合作推出了一种新的、业内最佳的 JavaScript 代码拆分策略。

例如,Barnebys 的应用程序大小减少了 23%,Sumup 的最大 JavaScript 包大小减少了 70%。这些改进是在他们的 Next.js 应用程序中未更改任何代码的情况下实现的。

公司通过简单地将 Next.js 升级到最新版本,自动采用了这种新策略。

网络上的图像

虽然我们专注于减少浏览器需要加载的 JavaScript 量已经取得了成效,但网络不仅仅是 JavaScript:它还包括标记和图像。

图像占据网页总字节的 50%。

图片对“最大内容绘制 (Largest Contentful Paint)”有很大影响,因为它们通常是页面加载时最大的可见元素。最大内容绘制是 Google 将很快在其搜索排名中使用的核心网页指标之一

一半的图片大小超过一兆字节,这意味着它们未针对在网络上显示进行优化。

如今,用户通过手机、平板电脑和笔记本电脑浏览网页,但图片仍然是“一刀切”的尺寸。例如:网站加载一张 2000x2000 像素的图片,但手机只将其显示为 100x100 像素。

此外,网页上 30% 的图像位于初始视口之外,这意味着浏览器加载的图像在用户向下滚动页面之前是看不到的。

图片通常没有 widthheight 属性,这导致它们在页面加载时跳动。这会损害累积布局偏移(Cumulative Layout Shift)核心网络指标。

99.7% 的网站图片未使用 WebP 等现代图片格式。

为了在网页上高效使用图片,需要考虑许多方面:大小、重量、延迟加载和现代图片格式。

开发人员必须设置复杂的构建工具来优化图像,然而这些工具通常不涵盖来自外部数据源的用户提交图像,从而无法优化所有图像。

这项不可能的开发任务不可避免地导致了令人沮丧的最终用户体验。

Next.js 图像组件

我们很高兴宣布我们解决网络上高性能图像的方案:Next.js 图像组件和自动图像优化。

最基本地说,Next.js 图像组件只是 HTML <img> 元素的直接替代品,并为现代网络进行了演进。

<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> 元素上的 widthheight 可能会导致响应式布局问题,但使用 next/image 时并非如此。使用 next/image 时,图像会根据提供的 widthheight 的宽高比自动实现响应式。

开发人员可以标记初始视口中的图像,使 Next.js 能够自动预加载这些图像。预加载初始视口中的图像已将“最大内容绘制”(Largest Contentful Paint)性能提高了高达 50%。

自动图像优化

即使与 HTML <img> 元素相比有了这些改进,仍然存在一个主要问题。2000 x 2000 像素的图像被发送到渲染较小图像的手机。

通过 Next.js 10,我们也解决了这个问题。next/image 组件将通过内置的图像优化自动生成更小的尺寸。

内置图像优化会自动以 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 配置中配置区域设置。

next.config.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 区域设置。

域名路由需要一些额外的配置才能知道如何路由域名

next.config.js
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 知道用户访问页面的语言,它会自动将语言属性添加到 <html> 标签中。

Next.js 不了解页面的变体,因此由您使用 next/head 添加 hreflang 元标签。您可以在 Google 网站管理员文档中了解更多关于 hreflang 的信息。

Next.js 国际化的未来

国际化路由是使您的项目国际化和本地化更轻松的一系列功能中的第一个。国际化路由允许与大多数 React 国际化库集成。

要了解有关国际化路由的更多信息,请查看国际化路由文档

Next.js 速度洞察

在 Vercel,我们知道无法衡量就无法改进。

您的访问者对网站性能越来越敏感。如果您的网站加载时间超过 3 秒,超过 50% 的访问者会放弃。如果您从事电子商务,许多人发现将加载时间缩短 1/10 秒,可以带来1% 的转化率提升

由于性能对您的成功至关重要,我们很荣幸推出 Next.js Speed Insights。该解决方案用于跟踪真实世界的性能指标,并将这些洞察反馈到您的开发工作流程中。

借助 Next.js Speed Insights

与其一次测量,不如现在持续测量。

与其在您的开发设备上测量,不如从您的访客实际使用的设备中获取测量数据。

Next.js Speed Insights 旨在关注整体情况,深入了解您的受众,以及您的应用程序为用户带来的性能。

我们之所以如此坚持收集真实数据,是因为性能不佳的原因并非总是最明显的。性能退化可能由多种因素引起——第三方脚本和样式表,或者过大或缓慢的第一方字体、图像和视频。

核心 Web 指标

Google 联合 Web 性能工作组,建立了一套准确衡量用户如何体验您网站性能的指标:恰如其名,Web Vitals。Web Vitals 跟踪您网站的感知加载速度、响应能力和视觉稳定性——所有这三项对于网站的整体健康状况都至关重要!

感知加载速度可以通过最大内容绘制(Largest Contentful Paint)来衡量,即页面所有内容显示完毕的时间。例如,当我打开一个链接购买一双运动鞋时,我看到运动鞋、它们的价格以及“添加到购物车”按钮所经过的时间就是 LCP。

页面响应能力可以通过首次输入延迟(First Input Delay)来衡量,它衡量用户等待看到他们与页面首次交互的反应所需的时间。例如,我点击“添加到购物车”和购物车中商品数量增加之间的时间就是 FID。

最后,视觉稳定性可以通过累积布局偏移(Cumulative Layout Shift)来衡量,即元素显示给用户后移动的程度。例如,我们都曾有过试图点击一个按钮却发现它因为图片加载延迟而移动的挫败感——这就是布局偏移。

对您的真实用户进行这些 Web Vitals 的持续测量和符合性至关重要。这是真正了解您的网站对用户表现如何的唯一方法。您网站的性能可能会因用户的设备和网络状况,或他们与页面交互的方式而大相径庭。加载个性化内容或广告的网站也可能因用户而异,性能差异巨大。

模拟测试无法捕捉这些重要的信号。

Next.js Speed Insights 允许您捕捉真实世界的洞察,而不是合成基准。它实现了连续的测量流,而不是依赖于偶尔的测试,确保它成为您开发者工作流程的一部分。

Next.js Speed Insights 允许您捕获真实世界的洞察,而不是合成基准。它实现了持续的测量流,而不是依赖于偶尔的测试,确保它成为您开发者工作流程的一部分

访问 nextjs.org/analytics 了解如何立即在您的应用程序中启用它。

Next.js 电子商务

电子商务是网络最重要的用途之一。新的 Next.js 10 功能是用于电子商务的强大新工具。

这就是为什么今天,我们与 BigCommerce 合作发布了 Next.js Commerce,一个用于电子商务网站的一体化 React 入门工具包。通过几次点击,Next.js 开发者可以克隆、部署和完全定制它。立即在 nextjs.org/commerce 开始吧。

React 17 支持

React 17 对 Next.js 没有重大更改,但需要一些维护更改,例如更新对等依赖项。新的 JSX 转换 在使用 React 17 时会自动启用,无需任何配置更改。

您只需升级 Next.js 和 React 即可开始使用 React 17

终端
npm install next@latest react@latest react-dom@latest

getStaticProps / getServerSideProps 快速刷新

当您编辑 getStaticPropsgetServerSideProps 函数时,Next.js 现在将自动重新运行该函数并应用新数据。这使您无需刷新页面即可更快地迭代。

要了解有关 getStaticPropsgetServerSideProps 的更多信息,您可以阅读数据获取文档

MDX 的快速刷新

当使用 Next.js 与 @next/mdx 结合使用时,更改 MDX 内容现在将利用快速刷新,确保浏览器在编辑时无需重新加载页面。

@next/mdx 文档 将指导您如何使用 Next.js 设置 MDX。

从第三方 React 组件导入 CSS

您现在可以在 React 组件内部导入第三方 CSS。这允许对仅用于单个组件的 CSS 进行代码分割。例如,您现在可以使用 react-datepicker 库,而无需在 _app.js 中导入 CSS

components/MyComponent.js
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
 
function MyComponent() {}

您可以参考内置 CSS 支持文档,了解 Next.js 如何处理 CSS 导入的更多信息。

href 的自动解析

如果您之前使用过动态路由,您可能遇到过需要同时为 next/link 提供 hrefas 属性的情况。它看起来像这样:

<Link href="/categories/[slug]" as="/categories/books" />

这允许 Next.js 为动态参数插值 href,但是,当开发人员忘记添加 as 或在 href 中添加 as 导致页面转换不使用客户端路由时,这会造成摩擦。

几个月前,我们着手解决开发人员的这一痛点,主要目标是改善开发人员体验和最终用户体验。我们逐步致力于一个允许 href 自动解析的解决方案。

我们很高兴地宣布,作为 Next.js 10 的一部分,您在大多数用例中不再需要使用 as 属性。这消除了开发人员的痛点,并改善了最终用户体验。

此更改完全向后兼容,如果您目前同时使用 hrefas,则现有行为将保留。

为了采用自动 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 快速刷新将无法检测到该函数是有效的 React 组件。同样,React Hooks eslint 规则也不会将该函数识别为 React 组件。

随着 Next.js 10 的发布,我们正在发布一个新的 Next.js codemods CLI 工具,它允许您运行单个命令来更新您的应用程序:npx @next/codemod <transform> <path>

要了解有关 codemod 的更多信息,您可以查看Next.js Codemods 文档

getStaticPaths 的阻塞回退

在 Next.js 9.3 中,我们引入了 getStaticPropsgetStaticPaths,以及在 getStaticPaths 中返回 fallback 属性的能力。fallback 属性允许生成额外的静态页面而无需完全重新构建,最初提供一个静态 HTML 文件,然后在后续请求中被完全渲染的内容替换。在过去几个月里,我们收到了许多公司的反馈,他们希望获得类似但略有不同的行为:当用户首次请求页面时进行阻塞预渲染。在首次渲染之后,该页面将重复用于后续请求。

Next.js 10 解决了这种情况。

我们很高兴地宣布 getStaticPaths 的新 fallback: 'blocking' 模式,它启用了阻塞行为,即不向浏览器发送静态回退。相反,它会等待初始请求进行预渲染。

pages/posts/[id].js
export function getStaticPaths() {
  return {
    // enables blocking mode for the fallback behavior
    fallback: 'blocking',
  };
}

要了解有关增量生成额外静态页面的 fallback 行为的更多信息,您可以参考fallback 文档

getStaticProps / getServerSideProps 的重定向和未找到支持

getStaticPropsgetServerSideProps 推出以来,我们注意到用户需要返回重定向和 404 响应的情况。为了简化这些情况,我们现在允许从 getStaticPropsgetServerSideProps 返回两个新字段:notFoundredirect

notFound 支持

当返回 notFound 字段为 true 时,将返回默认的 404 页面,状态码为 404。这使您可以避免使用 SSG 生成额外的页面,并且无需手动处理 404 页面的渲染。

pages/posts/[id].js
export function getStaticProps() {
  return {
    // returns the default 404 page with a status code of 404
    notFound: true,
  };
}

redirect 支持

现在可以返回重定向,其中包含 destination 以及重定向是否应为永久重定向(例如 permanent: true)。对于需要使用特定状态而不是默认状态的情况,也可以返回可选的 statusCode

pages/posts/[id].js
export function getStaticProps() {
  return {
    // returns a redirect to an internal page `/another-page`
    redirect: {
      destination: '/another-page',
      permanent: false,
    },
  };
}
pages/posts/[id].js
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 次。

加入 Next.js 社区,参与 GitHub 讨论。讨论区是一个社区空间,允许您与其他 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!