likes
comments
collection
share

Next.js 13.4 发布了

作者站长头像
站长
· 阅读数 15

Next.js 13.4

总结: Next.js 13.4推出了App Router,它与React Suspense集成,提高了感知加载性能。路由器还使用熟悉的async/await语法启用数据提取,并且所有组件默认都是React Server Components。该版本还包括Turbopack(beta),这是一个新的打包程序,可以加速本地迭代,以及Server Actions(alpha),使服务器变异不需要中间API层。其他改进包括草稿模式,用于获取和呈现草稿内容,而Pages Router仍然得到支持。

注: 此文由notion AI 翻译

原文地址 Next.js 13.4是一个基础版本,标志着应用路由器的稳定:

自从六个月前发布了Next.js 13以来,我们一直专注于构建下一个版本的Next.js的基础——应用路由器,以便可以逐步采用,而不需要进行不必要的破坏性更改。

现在,随着13.4的发布,您现在可以开始采用应用路由器用于生产。

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

Next.js App Router

我们在2016年发布了Next.js,为了提供一种轻松的方法来为React应用程序提供服务器渲染,我们的目标是创建一个更动态,个性化和全球化的Web。

在原始公告文章中,我们分享了Next.js的一些设计原则:

  • 零配置。使用文件系统作为API
  • 只有JavaScript。一切都是函数
  • 自动服务器呈现和代码拆分
  • 数据获取由开发人员完成

Next.js现在已经六岁了。我们的原始设计原则仍然存在,随着Next.js被更多的开发人员和公司采用,我们一直在为框架的升级工作。

我们一直在研究Next.js的下一代,并且今天随着13.4的发布,这一代Next.js已经稳定并准备好采用。本文将分享有关应用路由器的设计决策和选择的更多内容。

零配置。使用文件系统作为API

基于文件系统的路由一直是Next.js的核心功能。在我们的原始文章中,我们展示了从单个React组件创建路由的示例:

// Pages Router
// pages/about.js

import React from 'react';
export default () => <h1>About us</h1>;

没有其他配置。将文件放在pages /中,Next.js路由器将处理其余部分。我们仍然喜欢这个简单的路由。但是,随着框架的使用情况增加,开发人员正在寻求改进支持定义布局,将UI片段嵌套为布局,并具有更多灵活性以定义加载和错误状态的支持。将这个东西改进到现有的Next.js路由器中并不容易。

框架的每个部分都必须围绕路由器进行设计。页面转换,数据获取,缓存,数据的突变和重新验证,流媒体,内容样式等。

为了使我们的路由器与流媒体兼容,并解决这些对布局支持的要求,我们着手构建我们的路由器的新版本。

这是我们在发布我们的布局RFC之后落脚的地方。

// 新:应用路由器✨
// app/layout.js
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>);
}

// app/page.js
export default function Page() {
  return <h1>Hello, Next.js!</h1>;
}

比您在此处看到的更重要的是您看不到的内容。这个新路由器(可以通过app /目录逐步采用)具有完全不同的架构,建立在React Server ComponentsSuspense的基础之上。

这个基础使我们能够删除最初开发的用于扩展React原语的Next.js特定API。例如,您不再需要使用自定义_app文件来自定义全局共享布局:

// Pages Router
// pages/_app.js

//此“全局布局”包装所有路由。无法
//组合其他布局组件,并且您无法从此文件获取全局数据。
export default function MyApp({ Component,pageProps }) {
  return <Component {...pageProps} />;
}

对于页面路由器,布局不能组合,并且数据获取不能与组件放置在同一位置。通过新的应用路由器,现在支持此功能。

// 新:应用路由器✨
// app/layout.js
//
//整个应用程序共享根布局
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>);
}

// app/dashboard/layout.js
//
//布局可以嵌套和组合
export default function DashboardLayout({ children }) {
  return (
    <section>
      <h1>Dashboard</h1>
      {children}
    </section>);
}

对于页面路由器,_document用于自定义从服务器的初始负载。

// Pages Router
// pages/_document.js

//此文件允许您自定义<html>和<body>标记
//用于服务器请求,但添加了特定于框架的功能
//而不是编写HTML元素。
import { HtmlHeadMainNextScript } from 'next/document';

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>);
}

使用应用路由器,您不再需要从Next.js中导入<Html><Head><Body>。相反,您只需使用React。

// 新:应用路由器✨
// app/layout.js
//
//整个应用程序共享根布局
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>);
}

构建新的文件系统路由器的机会也是解决我们的路由系统中许多其他相关功能请求的正确时间。例如:

  • 以前,您只能从外部npm包(如组件库)中导入全局样式表(_app.js中),这是一个不太理想的开发人员体验。使用应用路由器,您可以在任何组件中导入(并放置)任何CSS文件。
  • 以前,通过Next.js(通过getServerSideProps)选择进入服务器端呈现意味着与您的应用程序交互被阻止,直到整个页面被水合。通过应用路由器,我们已经重新设计了体系结构,以与React Suspense深度集成,这意味着我们可以有选择地水合页面的部分,而不会阻止UI中的其他组件具有交互性。内容可以从服务器立即流式传输,从而提高页面的感知加载性能。

路由器是使Next.js工作的核心。但这不是关于路由器本身,而是它如何将框架的其他部分整合在一起,如数据获取

Only JavaScript. Everything is a function

Next.js 和 React 开发人员想要编写 JavaScript 和 TypeScript 代码,并将应用程序组件组合在一起。从我们的原始帖子:

import React from 'react';
import Head from 'next/head';

export default () => (
  <div>
    <Head>
      <meta name="viewport" content="width=device-width, initial-scale=1" />
    </Head>
    <h1>Hi. I'm mobile-ready!</h1>
  </div>);

在 Next.js 的未来版本中,我们增加了一项 DX 改进,可以自动为您导入 React。

这个组件封装了可以在应用程序中任何地方重用和组合的逻辑。结合文件系统路由,这意味着可以轻松开始构建感觉像编写 JavaScript 和 HTML 的 React 应用程序。

例如,如果您想要获取一些数据,Next.js 的原始版本如下所示:

import React from 'react';
import 'isomorphic-fetch';

export default class extends React.Component {
  static async getInitialProps() {
    const res = await fetch('<https://api.company.com/user/123>');
    const data = await res.json();
    return { username: data.profile.username };
  }
}

在 Next.js 的未来版本中,我们增加了一项 DX 改进,可以为您填充 fetch,因此您不需要导入 isomorphic-fetchnode-fetch,并且可以在客户端和服务器上使用 Web fetch API

随着采用率的增长和框架的成熟,我们探索了新的数据获取模式。

getInitialProps 在服务器和客户端都运行。该 API 扩展了 React 组件,允许您创建 Promise 并将结果转发到组件的 props。

虽然 getInitialProps 今天仍然有效,但我们接着根据客户反馈在下一代数据获取 API 上进行了迭代:getServerSidePropsgetStaticProps

// 生成路由的静态版本
export async function getStaticProps(context) {
  return { props: {} };
}
// 或者动态服务器呈现路由
export async function getServerSideProps(context) {
  return { props: {} };
}

这些 API 更清晰地指出您的代码在哪里运行,无论是客户端还是服务器,并允许 Next.js 应用程序自动进行静态优化。此外,它还允许进行静态导出,使 Next.js 可以部署到不支持服务器的地方(例如 AWS S3 存储桶)。

但是,这不是“纯 JavaScript”,我们希望更接近原始的设计原则。

自 Next.js 创建以来,我们与 React 核心团队在 Meta 密切合作,构建了基于 React 原语的框架功能。我们的合作伙伴关系与 React 核心团队多年的研究和开发相结合,为 Next.js 实现我们的目标提供了机会,包括 Server Components。

通过 App Router,您可以使用熟悉的 asyncawait 语法来获取数据。无需学习新的 API。默认情况下,所有组件都是 React Server Components,因此数据获取会安全地在服务器上进行。例如:

// app/page.js

export default async function Page() {
  const res = await fetch('<https://api.example.com/>...');
  // 返回值不会被序列化
  // 您可以使用 Date、Map、Set 等。
  const data = res.json();

  return '...';
}

关键是,“数据获取取决于开发人员”原则得到实现。您可以获取数据并组合任何组件。不仅是第一方组件,而且是 Server Components 生态系统中的任何组件,例如与 Server Components 集成并完全在服务器上运行的 Twitter 嵌入 react-tweet

// app/page.js

import { Tweet } from 'react-tweet';

export default async function Page() {
  return <Tweet id="790942692909916160" />;
}

由于路由已与 React Suspense 集成,因此您可以更流畅地显示回退内容,同时逐渐显示所需的内容。

// app/page.js

import { Suspense } from 'react';
import { PostFeed, Weather } from './components';

export default function Page() {
  return (
    <section>
      <Suspense fallback={<p>Loading feed...</p>}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={<p>Loading weather...</p>}>
        <Weather />
      </Suspense>
    </section>);
}

此外,路由将页面导航标记为转换,使路由转换可中断。

自动服务器渲染和代码分割

创建 Next.js 时,开发者手动配置 webpack、babel 和其他工具以运行 React 应用程序仍然很普遍。添加更进一步的优化,例如服务器渲染或代码分割,通常未在自定义解决方案中实现。Next.js 以及其他 React 框架创建了一个抽象层,以实现并强制执行这些最佳实践。

基于路由的代码分割意味着您的 pages/ 目录中的每个文件都会被分割成自己的 JavaScript 包,帮助减少文件系统并提高初始页面加载性能。

这对于服务器渲染应用程序以及使用 Next.js 的单页应用程序都是有益的,因为后者通常在应用程序启动时加载单个大型的 JavaScript 包。然而,要实现组件级别的代码分割,开发者需要使用 next/dynamic 来动态导入组件。

// app/page.tsx

import dynamic from 'next/dynamic';

const DynamicHeader = dynamic(() => import('../components/header'), {
  loading: () => <p>Loading...</p>,
});

export default function Home() {
  return <DynamicHeader />;
}

使用 App Router,服务器组件不包括在浏览器的 JavaScript 包中。默认情况下,客户端组件会自动进行代码拆分(使用 webpack 或 Next.js 中的 Turbopack)。此外,由于整个路由器架构都是流式的并启用了 Suspense,您可以逐步将 UI 的部分从服务器发送到客户端。

例如,您可以使用条件逻辑拆分整个代码路径。在此示例中,您不需要为注销用户加载仪表板的客户端 JavaScript。

// app/layout.tsx

import { getUser } from './auth';
import { Dashboard, Landing } from './components';

export default async function Layout() {
  const isLoggedIn = await getUser();
  return isLoggedIn ? <Dashboard /> : <Landing />;
}

Turbopack (Beta)

Turbopack 是我们正在通过 Next.js 测试和稳定的新打包工具,它有助于加速在 Next.js 应用程序上工作时的本地迭代(通过 next dev --turbo)和很快就能进行的生产构建(next build --turbo)。

自 Next.js 13 的 alpha 版本发布以来,我们已经看到了稳定增长的采用率,因为我们一直在修补错误并添加对缺失功能的支持。我们一直在 Vercel.com 上使用 Turbopack 和许多 Vercel 客户操作大型 Next.js 网站,以收集反馈并提高稳定性。我们感谢社区对我们团队的测试和报告错误的支持。

现在六个月后,我们准备进入 beta 阶段。

Turbopack 暂时还没有 webpack 和 Next.js 的完整的功能平价。我们正在跟踪这些功能的支持 此问题。但是,大多数用例现在应该得到支持。我们的目标是继续解决由于采用率的增加而导致的剩余错误,并为未来版本做好稳定性的准备。

我们投资于改进 Turbopack 的增量引擎和缓存层,这不仅可以加速本地开发,还可以很快进行生产构建。敬请期待未来版本的 Next.js,您将能够运行 next build --turbo 进行即时构建。

在 Next.js 13.4 中尝试使用 Turbopack beta,通过 next dev --turbo

服务器操作(Alpha)

React 生态系统在表单、管理表单状态、缓存和重新验证数据等方面看到了很多创新和思想的探索。随着时间的推移,React 对于其中一些模式变得更有意见。例如,对于表单状态,推荐使用“不受控制的组件”

当前解决方案的生态系统要么是可重用的客户端解决方案,要么是内置于框架中的原始解决方案。直到现在,还没有一种方法来组合服务器突变和数据原语。React 团队一直在开发一种官方解决方案,用于突变。

我们很高兴宣布,Next.js 支持实验性的服务器操作,使您能够在服务器上突变数据,直接调用函数而无需创建中间 API 层。

// app/post/[id]/page.tsx (Server Component)

import kv from './kv';

export default function Page({ params }) {
  async function increment() {
    'use server';
    await kv.incr(`post:id:${params.id}`);
  }

  return (
    <form action={increment}>
      <button type="submit">Like</button>
    </form>);
}

使用服务器操作,您可以进行强大的服务器端数据突变,减少客户端 JavaScript,并逐步增强表单。

// app/dashboard/posts/page.tsx (Server Component)

import db from './db';
import { redirect } from 'next/navigation';

async function create(formData: FormData) {
  'use server';
  const post = await db.post.insert({
    title: formData.get('title'),
    content: formData.get('content'),
  });
  redirect(`/blog/${post.slug}`);
}

export default function Page() {
  return (
    <form action={create}>
      <input type="text" name="title" />
      <textarea name="content" />
      <button type="submit">Submit</button>
    </form>);
}

Next.js 中的服务器操作已经为与其余数据生命周期的深度集成而设计,包括 Next.js 缓存、增量静态再生成 (ISR) 和客户端路由器。

通过新的 API revalidatePathrevalidateTag 重新验证数据意味着,在一次网络回传中进行突变、重新呈现页面或重定向,确保在客户端显示正确的数据,即使上游提供者速度较慢。

// app/dashboard/posts/page.tsx (Server Component)

import db from './db';
import { revalidateTag } from 'next/cache';

async function update(formData: FormData) {
  'use server';
  await db.post.update({
    title: formData.get('title'),
  });
  revalidateTag('posts');
}

export default async function Page() {
  const res = await fetch('https://...', { next: { tags: ['posts'] } });
  const data = await res.json();
  // ...
}

服务器操作被设计为可组合的。React 社区中的任何人都可以构建和发布服务器操作,并在生态系统中分发它们。就像服务器组件一样,我们对客户端和服务器端的可组合原语的新时代感到兴奋。

服务器操作已经在 Next.js 13.4 中以 alpha 版本提供。通过选择使用服务器操作,Next.js 将使用 React 的实验版本发布通道。

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverActions: true,
  },
};

module.exports = nextConfig;

其他改进

  • 草稿模式:从您的无头 CMS 获取和呈现草稿内容。草稿模式适用于pagesapp。我们已经增强和简化了现有的预览模式 API,该 API 在pages中继续工作。预览模式在app中不起作用,您应该使用草稿模式。

常见问题

什么是App Router稳定性?

今天标记App Router稳定并不意味着我们的工作已经完成。稳定性意味着App Router的核心已经准备好投入生产,并已经通过我们自己的内部测试以及许多Next.js早期采用者的验证。

我们仍然希望在未来进行其他优化,包括Server Actions达到完全稳定。对于我们来说,推向核心稳定性对于帮助社区明确应从何处开始学习和构建应用程序非常重要。

App Router建立在React canary channel 之上,现在可以进行框架采用Server Components等功能的特性。了解更多

这对于Next.js beta文档意味着什么?

从今天开始,我们建议使用App Router构建新应用程序。 App Router的beta文档已经被用来解释App Router并从头开始重新编写,现已合并回Next.js稳定文档。现在,您可以轻松切换App或Pages Router。

我们建议阅读App Router增量采用指南以了解如何采用App Router。

Pages Router会消失吗?

不会。我们致力于支持pages/开发,包括Bug修复,改进和安全补丁,多个主要版本将来都将得到支持。我们希望确保开发人员有足够的时间逐步采用App Router。

在生产环境中同时使用 pages/ 和 app/ 是被支持和鼓励的。应用路由器可以按照每个路由的方式进行采用。

这是否意味着Server Components已经“完成”?

Next.js是一个选择基于React体系结构构建的框架,其中包括Server Components。我们希望通过App Router提供的体验鼓励其他框架(或新框架)考虑使用这个体系结构。

这个生态系统中仍有尚未定义的模式,例如处理无限滚动。目前,我们建议在这些模式中使用客户端解决方案,同时该生态系统正在增长,并创建或更新库。

社区

Next.js是超过2600个单独开发人员、谷歌和Meta等行业伙伴以及我们在Vercel的核心团队的共同工作结果。加入GitHub讨论、Reddit和Discord社区。

这个版本是由以下人员提供的:

  • Next.js团队:Andrew、Balazs、Jan、Jiachi、Jimmy、JJ、Josh、Sebastian、Shu、Steven、Tim和Wyatt。
  • Turbopack团队:Alex、Donny、Justin、Leah、Maia、OJ、Tobias和Will。

原文地址