NextJS 13发布,包含大量新特性

NextJS 13发布,NextJS 13 新特性,新app目录,使用Turbopack,编译快至700倍,更智能的图片加载,字体加载,以及更好用的路由链接。

NextJS 13发布,包含大量新特性

Nextjs 13将会为无限制动态功能打下基础:

  • app目录:更容易、更快、更少的前端js
    • Layout布局
    • React服务端组件
    • Streaming流
  • Turbopack:快至700倍的基于Rust的Webpack替换品
  • next/image: 比本地浏览器图片懒加载更快
  • @next/font:自动适配自托管字体
  • next/link:a标签自动简化api

pages目录的Nextjs 13目前处于稳定版本,可以用于生产环境,下面的命令可以用于更新

npm i next@latest react@latest react-dom@latest eslint-config-next@latest
新的app目录(Beta)

我们正在改进Nextjs中的路由和布局体验,并通过引入app目录与React以后的特性保持一致。这是之前为社区反馈发布的关于布局RFC的跟进。

目前app目录还处于beta版本,不推荐用于生产环境。目前使用pages目录的Nextjs 13,与具有稳定特性的组件例如改进版的next/image,next/link一起使用,并且按照自己的节奏选择进入app目录,在可预见的未来,pages目录将会继续得到支持。

app目录包括对以下内容的支持:

  • 布局:在路由之间轻松共享 UI,同时保留状态并避免昂贵的重新渲染。
  • 服务器组件:使服务器优先成为大多数动态应用程序的默认设置。
  • 流式传输:在渲染时以 UI 为单位显示即时加载状态和流式传输。
  • 支持数据获取:异步服务器组件和扩展获取 API 支持组件级获取。

布局

app/ 目录使布局复杂的界面变得容易,跨导航维护状态,避免昂贵的重新渲染,并启用高级路由模式。 此外,您可以嵌套布局,并将应用程序代码与您的路由(如组件、测试和样式)放在一起。

在app/目录下创建路由文件"page.js":

// app/page.js
// This file maps to the index route (/)
export default function Page() {
  return <h1>Hello, Next.js!</h1>;
}

然后,您可以通过文件系统定义布局。 布局在多个页面之间共享 UI。 在导航时,布局会保留状态,保持交互,并且不会重新渲染。

// app/blog/layout.js
export default function BlogLayout({ children }) {
  return <section>{children}</section>;
}

服务器组件

app/ 目录引入了对 React 新的服务器组件架构的支持。 服务器和客户端组件将服务器和客户端分别用于他们最擅长的事情 - 允许您使用单一编程模型构建快速、高度交互的应用程序,从而提供出色的开发人员体验。

借助服务器组件,我们为构建复杂界面奠定了基础,同时减少了发送到客户端的 JavaScript 数量,从而实现更快的初始页面加载。

加载路由时,会加载 Next.js 和 React 运行时,它们是可缓存且大小可预测的。 此运行时的大小不会随着应用程序的增长而增加。 此外,运行时是异步加载的,使来自服务器的 HTML 能够在客户端逐步增强。


流式传输

app/ 目录引入了逐步渲染和增量流式传输 UI 的渲染单元到客户端的能力。

使用 Next.js 中的服务器组件和嵌套布局,您可以立即渲染页面中不需要数据的部分,并显示正在获取数据的页面部分的加载状态。 使用这种方法,用户不必等待整个页面加载完毕就可以开始与之交互。

部署到 Vercel 时,使用 app/ 目录的Nextjs 13 应用程序将默认在 Node.js 和 Edge 运行时中流式传输响应以提高性能。


数据获取

React 最近对 Promises RFC的支持引入了一种强大的新方法来获取数据和处理组件内的 Promise:

// app/page.js
async function getData() {
  const res = await fetch('https://api.example.com/...');
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
  return res.json();
}

// This is an async Server Component
export default async function Page() {
  const data = await getData();

  return <main>{/* ... */}</main>;
}

本地fetch web api 在 React 和 Next.js 中也得到了扩展。 它会自动对获取请求进行重复数据删除,并提供一种在组件级别获取、缓存和重新验证数据的灵活方式。 这意味着静态站点生成 (SSG)、服务器端渲染 (SSR) 和增量静态重新生成 (ISR) 的所有优势现在都可以通过一个 API 获得:

// This request should be cached until manually invalidated.
// Similar to `getStaticProps`.
// `force-cache` is the default and can be omitted.
fetch(URL, { cache: 'force-cache' });

// This request should be refetched on every request.
// Similar to `getServerSideProps`.
fetch(URL, { cache: 'no-store' });

// This request should be cached with a lifetime of 10 seconds.
// Similar to `getStaticProps` with the `revalidate` option.
fetch(URL, { next: { revalidate: 10 } });

在 app 目录中,您可以在布局、页面和组件中获取数据——包括支持来自服务器的流式响应。

我们正在启用符合人体工程学的方法来处理加载和错误状态,并在渲染时在 UI 中流式传输。 在未来的版本中,我们还将改进和简化数据突变。

我们很高兴与开源社区、包维护者和其他为 React 生态系统做出贡献的公司合作,为 React 和 Next.js 的新时代构建。 将数据获取并置在组件内部并减少向客户端发送 JavaScript 的能力是社区反馈的两个重要部分,我们很高兴将其包含在 app/ 目录中。

引入Turbopack(Alpha)

Next.js 13 包含 Turbopack,它是 Webpack 基于 Rust 的新继任者。

Webpack 已被下载超过 30 亿次。 虽然它是构建 Web 不可或缺的一部分,但我们已经使用基于 JavaScript 的工具达到了最大性能的极限。

在 Next.js 12 中,我们开始过渡到原生 Rust 驱动的工具。 我们首先从 Babel 迁移,这导致转译速度提高了 17 倍。 然后,我们替换了 Terser,这使得缩小速度提高了 6 倍。 是时候全力以赴进行捆绑了。

将 Turbopack alpha 与 Next.js 13 一起使用结果如下:

  • 更新速度比 Webpack 快 700 倍
  • 更新速度比 Vite 快 10 倍
  • 冷启动速度比 Webpack 快 4 倍

Turbopack 仅捆绑开发时所需的最少资产,因此启动时间非常快。 在具有 3,000 个模块的应用程序上,Turbopack 需要 1.8 秒才能启动。 Vite 耗时 11.4 秒,Webpack 耗时 16.5 秒。

Turbopack 对服务器组件、TypeScript、JSX、CSS 等提供了开箱即用的支持。 在 Alpha 版期间,许多功能尚不受支持。 我们很想听听您对使用 Turbopack 加速本地迭代的反馈。

立即在 Next.js 13 中使用 next dev --turbo 试用 Turbopack alpha。

next/image

Next.js 13 引入了一个强大的新 Image 组件,使您可以轻松地显示图像而无需布局转换并按需优化文件以提高性能。

在 Next.js 社区调查期间,70% 的受访者告诉我们他们在生产中使用了 Next.js Image 组件,反过来,他们看到了改进的 Core Web Vitals。 在 Next.js 13 中,我们进一步改进了 next/image。

新图片组件包含:

  • 交付更少的客户端 JavaScript
  • 更容易设计和配置
  • 默认情况下需要alt标签更易于访问
  • 对标Web平台
  • 更快,因为本机延迟加载不需要混合作用
import Image from 'next/image';
import avatar from './lee.png';

function Home() {
  // "alt" is now required for improved accessibility
  // optional: image files can be colocated inside the app/ directory
  return <Image alt="leeerob" src={avatar} placeholder="blur" />;
}

在Next.js 13中升级 next/image

旧的 Image 组件被重命名为 next/legacy/image。 我们提供了一个 codemod,它会自动将您现有的 next/image 使用更新为 next/legacy/image。 例如,当从根目录运行时,此命令将在您的 ./pages 目录上运行 codemod:

npx @next/codemod next-image-to-legacy-image ./pages
@next/font

Next.js 13 引入了一个全新的字体系统:

  • 自动优化您的字体,包括自定义字体
  • 删除外部网络请求以提高隐私和性能
  • 内置自动自托管任何字体文件
  • 使用 CSS size-adjust 属性自动进行零布局移位

这个新的字体系统让您可以方便地使用所有 Google 字体,同时兼顾性能和隐私。 CSS 和字体文件在构建时下载,并与您的其余静态资产一起自托管。 浏览器不会向 Google 发送任何请求。

import { Inter } from '@next/font/google';

const inter = Inter();

<html className={inter.className}>

还支持自定义字体,包括支持自动自托管、缓存和预加载字体文件。

import localFont from '@next/font/local';

const myFont = localFont({ src: './my-font.woff2' });

<html className={myFont.className}>

您可以自定义字体加载体验的每个部分,同时仍确保出色的性能和无布局变化,包括字体显示、预加载、回退等。

next/link

next/link 不再需要手动添加a标签作为子项。

这是在 12.2 中作为实验选项添加的,现在是默认选项。 在 Next.js 13 中, 始终呈现一个 a标签并允许您将 props 转发到底层标签。 例如:

import Link from 'next/link'

// Next.js 12: `<a>` has to be nested otherwise it's excluded
<Link href="/about">
  <a>About</a>
</Link>

// Next.js 13: `<Link>` always renders `<a>`
<Link href="/about">
  About
</Link>

在Nextjs 13中升级next/link

为了将您的next/link升级到 Next.js 13,我们提供了一个 codemod,它将自动更新您的代码库。 例如,当从根目录运行时,此命令将在您的 ./pages 目录上运行 codemod:

npx @next/codemod new-link ./pages
OG 图片生成

社交卡,也称为开放图形图像,可以大幅提高内容点击的参与率,一些实验显示转化率提高了 40%。

静态社交卡耗时、容易出错且难以维护。 正因为如此,社交卡经常缺乏甚至被跳过。 直到今天,需要个性化和动态计算的动态社交卡既困难又昂贵。

我们创建了一个新库@vercel/og,它可以与 Next.js 无缝协作以生成动态社交卡片。

// pages/api/og.jsx

import { ImageResponse } from '@vercel/og';

export const config = {
  runtime: 'experimental-edge',
};

export default function () {
  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          fontSize: 128,
          background: 'white',
          width: '100%',
          height: '100%',
        }}
      >
        Hello, World!
      </div>
    ),
  );
}

通过使用 Vercel Edge Functions、WebAssembly 和用于将 HTML 和 CSS 转换为图像并利用 React 组件抽象的全新核心库,这种方法比现有解决方案快 5 倍。

中间件 API 更新

在 Next.js 12 中,我们引入了中间件以实现 Next.js 路由器的完全灵活性。 我们听取了您对初始 API 设计的反馈,并添加了一些附加功能以改善开发人员体验并添加强大的新功能。

您现在可以更轻松地在请求上设置headers:

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  // Clone the request headers and set a new header `x-version`
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-version', '13');

  // You can also set request headers in NextResponse.rewrite
  const response = NextResponse.next({
    request: {
      // New request headers
      headers: requestHeaders,
    },
  });

  // Set a new response header `x-version`
  response.headers.set('x-version', '13');
  return response;
}

您现在还可以直接从中间件提供响应,而无需重写或重定向。

// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { isAuthenticated } from '@lib/auth';

// Limit the middleware to paths starting with `/api/`
export const config = {
  matcher: '/api/:function*',
};

export function middleware(request: NextRequest) {
  // Call our authentication function to check the request
  if (!isAuthenticated(request)) {
    // Respond with JSON indicating an error message
    return NextResponse.json(
      {
        success: false,
        message: 'Auth failed',
      },
      {
        status: 401,
      },
    );
  }
}

从中间件发送响应当前需要 next.config.js 中的 experimental.allowMiddlewareResponseBody 配置选项。

重大变化
  • 最低 React 版本已从 17.0.2 提升到 18.2.0。
  • 最低 Node.js 版本已从 12.22.0 提升到 14.6.0,因为 12.x 已达到生命周期结束。
  • swcMinify 配置属性已从 false 更改为 true。
  • next/image 已重命名为next/legacy/image,next/future/image已重命名为next/image,可以使用 codemod 安全地自动重命名您的导入。
  • next/link子元素不能再是a标签。添加 legacyBehavior 属性以使用旧行为或删除a标签进行升级。
  • 可以使用 codemod 自动升级您的代码。
  • 当User-Agent是机器人时,不再预取路由。
  • next.config.js 的不推荐使用的target选项已被删除。
  • 支持的浏览器已更改为删除 Internet Explorer 并针对现代浏览器。 您仍然可以使用 Browserslist 来更改目标浏览器。
    • Chrome 64+
    • Edge 79+
    • Firefox 67+
    • Opera 51+
    • Safari 12+