Back返回博客

Next.js 12.2 版本发布

Next.js 12.2 带来了稳定版的中间件 (Middleware) 和按需增量静态再生 (On-Demand ISR),实验性的边缘服务端渲染 (Edge SSR) 和 API 路由 (API Routes) 等新特性!

我们通过 12.2 版本为 Next.js 的未来奠定基础:

立即通过运行 npm i next@latest 进行更新。

中间件(稳定版)

我们很高兴地宣布中间件在 12.2 版本中已稳定,并根据用户反馈改进了 API。

中间件允许您在请求完成前运行代码。根据传入的请求,您可以通过重写、重定向、添加标头或设置 cookie 来修改响应。

middleware.ts
import { NextRequest, NextResponse } from 'next/server';
 
// 如果传入请求包含 "beta" cookie
// 则将请求重写至 /beta
export function middleware(req: NextRequest) {
  const isInBeta = JSON.parse(req.cookies.get('beta') || 'false');
  req.nextUrl.pathname = isInBeta ? '/beta' : '/';
  return NextResponse.rewrite(req.nextUrl);
}
 
// 支持单个匹配值或匹配数组
export const config = {
  matcher: '/',
};

要升级至中间件的最新 API 变更,请参阅 迁移指南

您可以在 Vercel 上免费试用 中间件,或使用 next start 自托管时 体验该功能。

按需增量静态再生(稳定版)

按需增量静态再生 (ISR) 允许您无需重新部署即可更新站点内容。当无头 CMS 或电商平台中的数据变更时,您可以立即轻松更新站点。这是社区最期待的功能之一,我们很高兴它现已稳定。

pages/api/revalidate.js
export default async function handler(req, res) {
  // 检查密钥以确认这是有效请求
  if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
    return res.status(401).json({ message: '无效令牌' });
  }
 
  try {
    await res.revalidate('/path-to-revalidate');
    return res.json({ revalidated: true });
  } catch (err) {
    // 如果出现错误,Next.js 将继续
    // 显示最后成功生成的页面
    return res.status(500).send('重新验证时出错');
  }
}

增量静态再生适用于所有支持 Next.js 构建 API (next build) 的提供商。部署至 Vercel 时,按需重新验证在将页面推送至边缘节点后约 300 毫秒内即可全局生效。

了解更多信息,请 查看文档观看演示 了解按需重新验证的实际效果。

边缘 API 路由(实验性)

Next.js 现在也支持在 API 路由中使用 边缘运行时。边缘运行时比 Node.js 更轻量,可实现快速启动以降低延迟。此外,边缘 API 路由支持从服务器流式传输响应。

您可以在 config 中为 API 路由设置运行时,指定 nodejs(默认)或 experimental-edge

pages/api/hello.js
import type { NextRequest } from 'next/server';
 
export default (req: NextRequest) => {
  return new Response(`Hello, from ${req.url} I'm now an Edge API Route!`);
};
 
export const config = {
  runtime: 'experimental-edge',
};

由于边缘运行时较为轻量,为适应快速启动存在一些限制——例如不支持 fs 等 Node.js 特定 API。因此,API 路由的默认运行时仍为 nodejs

了解更多信息,请 查看文档

边缘服务端渲染(实验性)

Next.js 现在支持使用 边缘运行时 进行服务端渲染。

如上所述,边缘运行时比 Node.js 更轻量,可实现快速启动以降低延迟。与 React 18 结合使用时,它支持页面的流式服务端渲染。

Next.js 默认使用 Node.js 作为服务端渲染页面的运行时。从 12.2 开始,如果您使用 React 18,可以选择使用边缘运行时。

您可以在 next.config.js 中全局设置运行时,指定 nodejsexperimental-edge

next.config.js
module.exports = {
  experimental: {
    runtime: 'experimental-edge',
  },
};

更改默认页面运行时会影响所有页面,包括 SSR 流式传输服务器组件 功能。您也可以通过导出 runtime 配置在每个页面基础上覆盖此默认值:

pages/index.js
export const config = {
  runtime: 'nodejs',
};
 
export default function Home() {}

您可以通过在运行时查看 process.env.NEXT_RUNTIME 环境变量,以及在 webpack 编译期间检查 options.nextRuntime 变量来检测正在使用的运行时。

了解更多信息,请 查看文档

next/image 改进

next/future/image 组件(实验性)

我们听取了您对当前 Image 组件的反馈,很高兴分享新版 next/image 的早期预览。这个经过改进的新图像组件需要更少的客户端 JavaScript,并简化了图像样式设置:

  • 渲染单个 <img> 而不需要 <div><span> 包装器
  • 添加了对标准 style 属性的支持
  • 移除了 layoutobjectFitobjectPosition 属性,改用 styleclassName
  • 移除了 IntersectionObserver 实现,改用 原生懒加载
  • 移除了 loader 配置,改用 loader 属性
  • 注意:暂不支持 fill 模式,因此需要提供 widthheight 属性

这提高了性能,因为原生 loading="lazy" 不需要等待 React 水合和客户端 JavaScript 执行。

了解更多信息,请 查看文档

远程模式(实验性)

next/image 现在支持实验性配置选项 remotePatterns,允许您在使用内置图像优化 API 时为远程图像指定通配符。这提供了比现有 images.domains 配置更强大的匹配能力,后者仅对域名进行精确匹配。

next.config.js
module.exports = {
  experimental: {
    images: {
      remotePatterns: [
        {
          // `src` 属性的主机名必须以 `.example.com` 结尾,
          // 否则将返回 400 Bad Request
          protocol: 'https',
          hostname: '**.example.com',
        },
      ],
    },
  },
};

了解更多信息,请 查看文档

禁用图片优化

零配置的图片优化 API 会阻止使用 next export,因为它需要服务器根据请求实时优化图片。在此之前,目标使用 next export 的用户需要配置 loader 以使用第三方图片优化服务,但如果没有可用的服务提供商,则没有明确的解决方案。从今天开始,next export 用户可以通过一个新的配置属性为所有 next/image 实例禁用图片优化:

next.config.js
module.exports = {
  experimental: {
    images: {
      unoptimized: true,
    },
  },
};

SWC 插件(实验性)

Next.js 编译器 使用 SWC 来转换和压缩生产环境的 JavaScript 代码。SWC 在 Next.js 12.0 中引入,旨在提升本地开发和构建性能。

现在,你可以添加插件(使用 WebAssembly 编写)来自定义编译期间的 SWC 转换行为:

next.config.js
module.exports = {
  experimental: {
    swcPlugins: [
      ['css-variable/swc', { displayName: true, basePath: __dirname }],
    ],
  },
};

更多信息请查看文档

React 18 支持改进

  • 改进了对 CSS-in-JS 库(如 styled-componentsemotion)的支持,升级体验更流畅且无破坏性变更。
  • 现在完全支持 AMP 和 HTML 后优化(CSS、字体优化)。
  • next/head 现在支持 React 18。
  • Next.js 的路由播报器(用于向屏幕阅读器和其他辅助技术正确播报页面切换)现在支持 React 18。

其他改进

  • 在 Next.js 编译器中支持 Emotion 转换。现在支持 @emotion/babel-plugin 的大部分功能,除非你使用 importMap,否则可以移除该插件。更多信息请查看文档
  • 通过允许自定义默认选项(包括 cssProp 选项),改进了 Next.js 编译器对 styled-components 转换的支持。更多信息请查看文档
  • 更好地支持 JavaScript ES 模块,因此像 next/imagenext/link 这样的组件可以正确通过 import 导入。
  • next/link 不再需要手动添加 <a> 作为子元素。现在你可以以向后兼容的方式启用此行为
  • 我们添加了实验性支持,通过修改 browsersList 仅分发现代 JavaScript。你可以在 next.config.jsexperimental 选项中设置 browsersListForSwc: truelegacyBrowsers: false 来启用此行为。
  • 新的 @swc/helpers 优化避免了跨包的重复代码,在最小配置下减少了约 2KB 的包大小,在大型应用中效果更显著。
  • 我们显著减少了 Next.js 的安装体积。通过将我们的 monorepo 迁移到 pnpm,我们得以在创建预编译版本时移除重复的包。这使得安装体积减少了 14MB。
  • 在我们持续改进 Next.js 自托管能力的努力中,我们将实验性的 outputStandalone: true 配置稳定为 output: 'standalone'。此配置通过仅包含必要的文件/资源(包括移除在构建部署包中安装所有 node_modules 的需求)大幅减少了部署体积。你可以在我们的 with-docker 示例中查看此配置的实际效果。

布局 RFC 与高级路由支持

如果你错过了,上个月我们发布了布局 RFC——这是自 2016 年 Next.js 推出以来最大的更新,包括:

  • 嵌套布局:通过嵌套路由构建复杂应用。
  • 为服务端组件设计:针对子树导航优化。
  • 改进的数据获取:在布局中获取数据,避免瀑布流问题。
  • 使用 React 18 特性:流式传输、过渡和 Suspense。
  • 客户端和服务端路由:以服务端为中心的路由,同时具备类似 SPA 的行为。
  • 100% 渐进式采用:无破坏性变更,可逐步采用。
  • 高级路由约定:离屏缓存、即时过渡等。

更多信息请查看 RFC提供反馈

感谢贡献者

Next.js 是 超过 2,000 名独立开发者、行业合作伙伴(如 Google Chrome 和 Meta)以及 Vercel 核心团队共同努力的成果。

本次发布的贡献者包括:@huozhi, @ijjk, @kwonoj, @ViolanteCodes, @akrabdev, @timneutkens, @jpveilleux, @stigkj, @jgoping, @oof2win2, @Brooooooklyn, @CGamesPlay, @lfades, @molebox, @steven-tey, @SukkaW, @Kikobeats, @balazsorban44, @erikbrinkman, @therealmarzouq, @remcohaszing, @perkinsjr, @shuding, @hanneslund, @housseindjirdeh, @RobertKeyser, @styfle, @htunnicliff, @lukeshumard, @sagnik3, @pixelass, @JoshuaKGoldberg, @rishabhpoddar, @nguyenyou, @kdy1, @sidwebworks, @gnoff, @gaspar09, @feugy, @mfix-stripe, @javivelasco, @Chastrlove, @goncharov-vlad, @NaveenDA, @Firfi, @idkwhojamesis, @FLCN-16, @icyJoseph, @ElijahPepe, @elskwid, @irvile, @Munawwar, @ykolbin, @hulufei, @baruchadi, @imadatyatalah, @await-ovo, @menosprezzi, @gazs, @Exortions, @rubens-lopes, @woochul2, @stefee, @stmtk1, @jlarmstrongiv, @MaedahBatool, @jameshfisher, @fabienheureux, @TxHawks, @mattbrandlysonos, @iggyzap, @src200, @AkifumiSato, @hermanskurichin, @kamilogorek, @ben-xD, @dawsonbooth, @Josehower, @crutchcorn, @ericmatthys, @CharlesStover, @charlypoly, @apmatthews, @naingaungphyo, @alexandrutasica, @stefanprobst, @dc7290, @DilwoarH, @tommarshall, @stanhong, @leerob, @appsbytom, @sshyam-gupta, @saulloalmeida, @indicozy, @ArianHamdi, @Clariity, @sebastianbenz, @7iomka, @gr-qft, @Schniz, @dgagn, @sokra, @okbel, @tbvjaos510, @dmvjs, @PepijnSenders, @JohnPhamous, @kyliau, @eric-burel, @alabhyajindal, @jsjoeio, @vorcigernix, @clearlyTHUYDOAN, @splatterxl, @manovotny, @maxproske, @nvh95, @frankievalentine, @nuta, @bagpyp, @dfelsie, @qqpann, @atcastle, @jsimonrichard, @mass2527, @ekamkohli, @Yuddomack, @tonyspiro, @saurabhmehta1601, @banner4422, @falsepopsky, @jantimon, @henriqueholtz, @ilfa, @matteobruni, @ryscheng, @hoonoh, @ForsakenHarmony, @william-keller, @AleksaC, @Miikis, @zakiego, @radunemerenco, @AliYusuf95, 和 @dominiksipowicz。