Next.js 15 RC新特性速览

May 30, 2024

Next.js 15 RC版本已经发布,它带来了一系列令人兴奋的新特性和改进,为前端开发带来了新的风向。以下是Next.js 15 RC的一些亮点特性,让我们一起探索它们将如何影响我们的开发流程。

💡
RC版本,即Release Candidate版本,是一个软件或产品在正式发布前的一个测试阶段。在这个阶段,软件已经完成了主要的开发工作,并且已经通过了内部测试,但是还没有对公众发布。RC版本的主要目的是让更广泛的用户群体在实际环境中测试软件,以发现并修复可能存在的问题,确保软件的稳定性和可靠性。这意味着Next.js团队已经完成了主要的开发工作,并希望通过社区的测试来确保新特性和改进在正式发布前是稳定和可靠的。用户可以安装RC版本来尝试新特性,并提供反馈,帮助改进最终的稳定版本。

 

特性介绍

React 19 RC支持

Next.js 15 RC现在支持React 19 RC,这是React团队的重大更新。它包括了客户端和服务器端的新特性,例如Actions。这将允许开发者在React v19正式发布之前就使用并提供反馈。

React Compiler(实验性)

React Compiler是由Meta的React团队创建的一个新实验性编译器。它通过理解纯JavaScript语义和React规则,深入理解你的代码,从而自动优化代码。这减少了开发者需要手动进行的记忆化操作,简化了代码,使其更易于维护,减少了错误。介绍React Comppiler的文章挺多了,核心优化点就是后续可以不再大量使用memo等类似的hook了,react性能也会有很大的提升。

错误提醒优化

这个错误相信很多开发者都遇到过,通常反应是一脸懵,定位也很耗时。

Next.js 15 RC 改进后的效果:

缓存策略更新

Next.js 15对缓存策略进行了更新。fetch请求、GET路由处理器和客户端路由缓存现在默认不再缓存。如果需要保留之前的行为,可以继续选择使用缓存。

在之前的版本中, fetch请求、GET路由处理会被自动缓存,以提高性能。但在Next.js 15中,默认情况下不再进行这种自动缓存。这一变化使得开发者能够更加灵活地控制缓存行为,根据应用的具体需求来决定是否进行缓存以及如何进行缓存。

Next.js的缓存能力参考我之前的文章:《Next.js缓存能力

对于仍然希望缓存fetch()请求的开发者,Next.js 15提供了一些其他手段,包括:

  • 将单个 fetch 调用中的缓存选项设置为强制缓存(force-cache)
[javascript]
fetch(`https://...`, { cache: 'force-cache' | 'no-store' })
  • 将单个路由的动态路由配置选项设置为“强制静态”(force-static)
[javascript] layout.tsx | page.tsx | route.ts
export const dynamic = 'auto'
// 'auto' | 'force-dynamic' | 'error' | 'force-static'
  • 将 fetchCache 路由配置选项设置为“默认缓存”(default-cache),以覆盖 Layout 或 Page 中的所有 fetch 请求,使其使用强制缓存,除非它们明确指定了自己的缓存选项
[javascript] layout.tsx | page.tsx | route.ts
export const fetchCache = 'auto'
// 'auto' | 'default-cache' | 'only-cache'
// 'force-cache' | 'force-no-store' | 'default-no-store' | 'only-no-store'

另外在 Next 14 中,使用 GET HTTP 方法的路由处理程序默认会被缓存,除非它们使用了动态函数或动态配置选项。在 Next.js 15 中,GET 函数默认不会被缓存。

你仍然可以通过使用静态路由配置选项(如导出 dynamic = 'force-static')来选择启用缓存。

像 sitemap.ts、opengraph-image.tsx、icon.tsx 等特殊路由处理程序以及其他元数据文件,除非它们使用动态函数或动态配置选项,否则它们默认仍然是静态的。

增量采用的部分预渲染(实验性)

Next.js 14引入了部分预渲染(PPR),这是一种在同一页面上结合静态和动态渲染的优化。Next.js 15通过添加experimental_ppr路由配置选项,允许特定布局和页面采用PPR。

Partial Prerendering(部分预渲染)是一种优化页面加载性能的方法,它是Client Side Rendering(客户端渲染)和Server Side Rendering(服务器端渲染)两种方法的结合体。在这种渲染方式下,页面的一部分(通常是对SEO和首次加载速度关键的部分)在服务器端进行渲染,而其他部分(通常是交互性强的部分)则在客户端进行渲染。

Partial Prerendering旨在将静态渲染的速度优势与动态个性化响应的灵活性相结合。它依靠React Suspense等技术来提供快速的初始静态响应,同时可以根据用户交互或其他触发器动态地替换组件。这种优化方式有助于加快页面加载速度,提高用户体验,并允许开发者在需要时保持页面的交互性。

在Next.js 14中,Partial Prerendering作为预览版功能被引入。开发者现在可以在Next.js 15中使用这个功能来优化他们的Web应用程序,并期望在将来得到更快、更可靠的性能。

[javascript]
import { Suspense } from "react"
import { StaticComponent, DynamicComponent } from "@/app/ui"
 
export const experimental_ppr = true
 
export default function Page() {
  return {
     <>
	     <StaticComponent />
	     <Suspense fallback={...}>
		     <DynamicComponent />
	     </Suspense>
     </>
  };
}

next/after(实验性)

after()是一个新实验性API,它允许你在响应完成流式传输后安排工作,使得次要任务可以在不阻塞主响应的情况下运行。这对于日志记录、分析和其他外部系统同步等任务非常有用。

异步任务的执行,之前我在实现缓存的时候也吐槽过,next.js自己内部是有这个能力的,但是一直未开放给外部,或者与vercel平台深度绑定。现在终于放开了一部分。

[javascript]
import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // Secondary task
  after(() => {
    log();
  });
 
  // Primary task
  return <>{children}</>;
}

create-next-app更新

Next.js 15对create-next-app进行了更新,提供了新的设计和一个新的标志来在本地开发中启用Turbopack

外部包捆绑优化(稳定)

在App Router中,外部包默认被捆绑,并且可以使用新的serverExternalPackages配置选项来选择性地排除特定包。在Pages Router中,外部包默认不被捆绑,但可以使用现有的transpilePackages选项来指定要捆绑的包。

之前serverExternalPackages 为实验特性,新版本中进入stable。

如何升级

要从Next.js 14升级到Next.js 15,你可以按照以下步骤操作:

1. 更新依赖项

使用你偏好的包管理器运行以下命令来安装Next.js 15 RC版本以及相关的React和React DOM的RC版本:

[shell]
npm i next@rc react@rc react-dom@rc eslint-config-next@rc

或者如果你使用Yarn:

[shell]
yarn add next@rc react@rc react-dom@rc eslint-config-next@rc

或者如果你使用pnpm:

[shell]
pnpm up next@rc react@rc react-dom@rc eslint-config-next@rc

或者如果你使用Bun:

[shell]
bun add next@rc react@rc react-dom@rc eslint-config-next@rc

2. 升级TypeScript类型定义(如果使用TypeScript)

确保你也将@types/react@types/react-dom升级到最新版本。

3. 更新fetch请求的缓存行为

在Next.js 15中,默认情况下不再缓存fetch请求。要将特定的fetch请求加入缓存,可以通过传递cache: 'force-cache'选项来实现:

[javascript]
export default async function RootLayout() {
  const a = await fetch('https://...') // 不缓存
  const b = await fetch('https://...', { cache: 'force-cache' }) // 缓存

  // ...
}

4. 更新路由处理器的缓存行为

GET路由处理器函数默认不再缓存。要启用缓存,可以在路由处理器文件中使用export dynamic = 'force-static'配置选项:

[javascript]
export dynamic = 'force-static'

export async function GET() {}

5. 客户端路由缓存

通过<Link>useRouter导航时,默认不再重用客户端路由缓存中的页面片段。要启用页面片段的缓存,可以使用staleTimes配置选项:

[javascript]
const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30,
      static: 180,
    },
  },
}

module.exports = nextConfig

6. 更新next/font

@next/font包已被移除,取而代之的是内置的next/font。你可以使用提供的codemod自动重命名你的导入:

[javascript]
// 之前
import { Inter } from '@next/font/google'

// 之后
import { Inter } from 'next/font/google'

7. 更新bundlePagesRouterDependencies配置

experimental.bundlePagesExternals现在已稳定,并更名为bundlePagesRouterDependencies

[javascript]
const nextConfig = {
  // 之前
  experimental: {
    bundlePagesExternals: true,
  },

  // 之后
  bundlePagesRouterDependencies: true,
}

module.exports = nextConfig

8. 更新serverExternalPackages配置

experimental.serverComponentsExternalPackages现在已稳定,并更名为serverExternalPackages

[javascript]
const nextConfig = {
  // 之前
  experimental: {
    serverComponentsExternalPackages: ['package-name'],
  },

  // 之后
  serverExternalPackages: ['package-name'],
}

module.exports = nextConfig

9. 更新Speed Insights

Next.js 15中移除了Speed Insights的自动集成。要继续使用Speed Insights,请按照Vercel Speed Insights快速入门指南操作。

按照这些步骤,你应该能够从Next.js 14平滑升级到Next.js 15。记得在升级过程中检查你的项目是否有任何不兼容的更改,并根据需要进行调整。

总结

从RC的特性上看,Next.js还是挺重视社区反馈的。之前我所见到的两类比较多的吐槽点:

  • 大量的默认行为导致难以理解。比如fetch的默认缓存,如果对next.js的缓存逻辑不理解,很容易弄出bug。这对新人很不友好。
  • 与vercel的深度绑定。虽然会带动vercel的发展,但是对next.js的长期发展不利。

新版本在这些方面做了一些改进,希望后续next.js能有更好的发展。

See all postsSee all posts