跳至内容
返回博客

2022年12月22日,星期四

Next.js 13.1

发布者

Next.js 13.1 包括对 pages/(稳定版)和 app/(测试版)目录的改进

通过运行以下命令进行更新

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

改进了 app 目录的可靠性和支持

在 Next.js 13 中,我们宣布了新的 app 目录(测试版)。这个新的路由和数据获取系统可以与您现有的 pages 目录一起逐步采用。

app 目录提供了许多好处,包括增强的布局、组件、测试和样式的共存、组件级数据获取等等。感谢您的反馈和早期测试,我们对 app 目录的可靠性进行了一些改进

  • 无布局 Div:以前,app 目录会添加额外的 <div> 元素以在导航时将滚动布局滚动到视图中。在 13.1 中,不再创建这些额外元素。滚动行为得以保留。
  • TypeScript 插件:我们构建了一个新的 TypeScript 插件,它提供了页面和布局配置选项的建议,将文档直接带到您的 IDE 中,并提供了关于服务器组件和客户端组件的有用使用提示(例如,防止在服务器组件中使用 useState)。了解更多
  • 可靠性改进:我们修复了许多错误,包括改进的 CSS 模块支持、正确地为布局和页面去重 cache()fetch()、内存泄漏等等。
  • 更少的客户端 JavaScript:app 目录现在比 pages 目录减少了 9.3kB 的客户端 JavaScript。无论您向应用程序添加 1 个还是 1000 个服务器组件,此基线都不会增加。React 运行时暂时略大,增加是由 React 服务器组件运行时引起的,该运行时处理 Next.js 之前处理的机制。我们正在努力进一步减少这种情况。
pages/app/增量
总首屏加载 JS基线-9.3kB缩小了12.1%
Next.js 运行时基线-12kB缩小了56.8%
React 运行时基线+2.7kB增大了5.2%

我们很高兴能够继续改进 app 目录的稳定性。app 目录的测试版文档 已经进行了数百次更新,基于您的反馈

内置模块转译(稳定版)

您现在可以标记来自本地包(如单仓库)或来自外部依赖项(node_modules)的依赖项以进行转译和捆绑。此内置支持取代了流行的 next-transpile-modules 包。

/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['@acme/ui', 'lodash-es'],
};
 
module.exports = nextConfig;

我们感谢 Pierre de la Martinière (@martpie) 为该包所做的工作以及他们帮助确保内置支持满足社区需求。

导入解析以获得更小的包

许多流行的 npm 包使用“桶文件”来提供一个重新导出其他模块的单个文件。例如

@acme/ui/index.ts
export { default as Button } from './dist/Button';
export { default as Slider } from './dist/Slider';
export { default as Dropdown } from './dist/Dropdown';

这允许包的使用者在一行中使用命名导出

import { Button, Slider, Dropdown } from '@acme/ui';

虽然打包器理解这些桶文件并且可以移除未使用的重新导出(称为“死代码消除”),但此过程涉及解析/编译所有重新导出的文件。对于发布的库,一些 npm 包提供的桶文件重新导出了数千个模块,这会减慢编译时间。这些库建议使用 babel-plugin-transform-imports 来避免此问题,但对于使用 SWC 的用户,之前没有支持。我们已将一个名为 modularizeImports 的新 SWC 转换内置到 Next.js 中。

此新设置启用 SWC 转换,该转换根据定义的模式更改您的导入语句。例如,上面使用三个组件的代码将自动转换为使用直接导入,而无需开发人员手动编写此代码

// Before (with barrel file)
import { Button, Slider, Dropdown } from '@acme/ui';
 
// After (with modularized imports from plugin)
import Button from '@acme/ui/dist/Button';
import Slider from '@acme/ui/dist/Slider';
import Dropdown from '@acme/ui/dist/Dropdown';

此转换可以通过 next.config.js 中的 modularizeImports 选项实现

next.config.js
module.exports = {
  modularizeImports: {
    '@acme/ui': {
      transform: '@acme/ui/dist/{{member}}',
    },
  },
};

利用此转换与 @mui/icons-materiallodash 一起使用,可以跳过对未使用的文件的编译。了解更多

查看演示以查看其运行情况。

用于边缘的轻量级 Node.js 运行时,现在稳定支持 API 路由

Next.js 中的边缘运行时使用 Node.js API 的严格子集(如 RequestResponse 等),这些 API 与 Vercel 等边缘计算平台兼容,或在自行托管时兼容。这些 API 在任何地方运行,包括在浏览器中,允许开发人员学习一次,随处编写。

pages/api/hello.ts

// "experimental-" prefix is no longer needed
export const config = {
  runtime: 'edge',
};
 
export default function handler(req: Request) {
  return new Response('Hello World');
}

Next.js 中间件默认已使用这种轻量级边缘运行时,以获得更好的性能。由于中间件可以在应用程序中的每个请求之前运行,因此拥有轻量级运行时对于确保低延迟至关重要。在 Next.js 12.2 中,我们添加了可以选择性地将此运行时用于API 路由 的功能。

在 13.1 中,Next.js 中的边缘运行时现已稳定,可用于 API 路由。当自托管时,使用边缘运行时的中间件和 API 路由默认将作为单区域工作负载运行,作为 next start 的一部分。在 Vercel 上,Next.js 中间件和 API 路由使用 Vercel Edge Functions 在全球部署,以实现尽可能低的延迟。Vercel Edge Functions 也现已普遍可用

Turbopack 改进

在发布了与 Next.js 13 结合使用的Turbopack alpha 版本后,我们一直专注于提高可靠性,添加对最受请求的功能的支持,以及制定插件计划和在其他框架中的使用计划。

自 Next.js 13.0.0 以来,Turbopack

  • 支持 PostCSS,包括 Tailwind CSS
  • 支持 next/image
  • 支持 @next/font(Google 字体)
  • 支持从动态 import() 语句加载 CSS
  • 支持 CSS 源映射(感谢 @ahabhgk贡献
  • 改进了 next dev 错误覆盖层中的错误处理
  • 改进了内存使用
  • 改进了 CSS 模块支持
  • 改进了 HMR 更新的分块算法
  • 改进了 HMR 源映射的可靠性

我们感谢 Evan You 和 Vite 社区提供的反馈和贡献,以确保 Turbopack 基准测试尽可能准确。我们与 Vite 团队合作,验证了最新的 Turbopack 基准测试,并对我们的测试方法进行了大量改进。

由于这种合作,我们现在使用了一个更准确的指标,其中包括 React 更新机制中花费的时间。我们能够将 Turbopack 以及 Webpack 上的 Next.js 13.1 中的 React 快速刷新时间提高 30 毫秒。我们还添加了一个使用 SWC 的 Vite 的新基准测试,该测试显示与使用默认的 Babel 的 Vite 相比,性能有所提高。查看更新的基准测试或阅读有关测试方法的信息。

立即在 Next.js 13 中尝试 Turbopack alpha 版本,使用 next dev --turbo。如果您有任何反馈,请在GitHub 讨论中告知我们。

Next.js 高级中间件

感谢您的反馈,我们正在使 Next.js 中间件比以往任何时候都更加强大。在 13.1 中,您现在可以从中间件返回响应,以及在请求上设置标头。

这些 API 改进为您提供了强大的新灵活性,可以自定义 Next.js 路由生命周期的每个部分。next.config.js 内部的 experimental.allowMiddlewareResponseBody 配置选项不再需要。

您现在可以更轻松地在请求上设置标头,以及直接响应,而无需 rewriteredirect

middleware.ts
import { NextResponse } from 'next/server';
 
export function middleware(request: Request) {
  // Check if a user has access...
  if (!isAuthorized(request)) {
    return NextResponse.json({ message: 'Unauthorized' });
  }
 
  // Add a new header, this will change the incoming request headers
  // that you can read in getServerSideProps and API routes
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-version', '13.1');
 
  return NextResponse.next({
    request: {
      // Apply new request headers
      headers: requestHeaders,
    },
  });
}

详细了解Next.js 高级中间件

其他改进

  • @next/font 现在支持在同一个字体声明中添加多个字体粗细和样式。了解更多
  • next/dynamic 现在使用 React 原语 lazy()<Suspense>。之前的 suspense 选项不再需要。通过这些更改,next/dynamic 现在与 app 目录兼容。
  • create-next-app 已更新了新设计,现在默认包含@next/font,用于自动自托管字体,且布局偏移量为零。可以使用 npx create-next-app@latest 尝试一下,或部署模板
  • 我们对App Directory Playground进行了大量改进,其中展示了 Next.js 13 中 app 目录(测试版)的一些最新功能和约定。部署您自己的
  • 我们创建了一个高性能图片库模板,其中包括图片占位符、延迟加载、自动优化、键盘支持等。部署您自己的
  • 我们创建了一个资源,用于了解如何将大型开源 React 和 Express.js 应用程序迁移到 Next.js,包括详细的演练和指向特定提交的链接。

社区

Next.js 是 2400 多位独立开发者、谷歌和 Meta 等行业合作伙伴以及我们在 Vercel 的核心团队共同努力的结果。Next.js 每周有超过 360 万次 npm 下载量和 97900 多颗 GitHub 星标,是构建 Web 最受欢迎的方式之一。

加入社区,请访问 GitHub DiscussionsRedditDiscord

此版本由以下人员贡献:

以及以下贡献者:@aarnadlr、@aaronbrown-vercel、@aaronjy、@abayomi185、@ademilter、@adictonator、@adilansari、@adtc、@alantoa、@aleksa-codes、@alfred-mountfield、@alpha-xek、@andarist、@andykenward、@anujssstw、@artdevgame、@artechventure、@arturbien、@aziyatali、@bennettdams、@bertho-zero、@blue-devil1134、@bot08、@brkalow、@brvnonascimento、@chanceaclark、@chibicode、@chrisipanaque、@chunsch、@colinking、@craigwheeler、@ctjlewis、@cvolant、@danmindru、@davidnx、@delbaoliveira、@devvspaces、@dtinth、@ducanhgh、@duncanogle、@ethomson、@fantaasm、@feugy、@fomichroman、@gruz0、@haschikeks、@hughlilly、@idoob、@iiegor、@imranbarbhuiya、@ingovals、@inokawa、@ishaqibrahimbot、@ismaelrumzan、@jakemstar、@janicklas-ralph、@jaredpalmer、@jaykch、@jimcresswell、@joliss、@josephcsoti、@joshuaslate、@joulev、@jueungrace、@juliusmarminge、@karlhorky、@kikobeats、@kleintorres、@koenpunt、@koltong、@kosai106、@labyrinthitis、@lachlanjc、@laityned、@leerob、@leoortizz、@lorenzobloedow、@lucasassisrosa、@m7yue、@manovotny、@marcus-rise、@matthew-heath、@mattpr、@maxleiter、@maxproske、@meenie、@mmaaaaz、@mnajdova、@moetazaneta、@mrkldshv、@nathanhammond、@nekochantaiwan、@nfinished、@niedziolkamichal、@nocell、@notrab、@nuta、@nutlope、@obusk、@orionmiz、@peraltafederico、@reshmi-sriram、@reyrodrigez、@rightones、@rishabhpoddar、@saseungmin、@serkanbektas、@sferadev、@silvioprog、@sivtu、@soonoo、@sqve、@steven-tey、@sukkaw、@superbahbi、@teobler、@theevilhead、@thomasballinger、@timeyoutakeit、@valentinh、@ws-jm、@wxh06、@yasath、@yutsuten 和 @zekicaneksi。