下一代前端构建利器——Turbopack

JavaScript/前端
57
0
0
2024-09-22

Next 已经发布13.4稳定版本

详细官方文档:Building Your Application: Routing | Next.js 13.4 (nextjs.org)

新特性

一、App Router

Next.js 基于文件系统的路由设计模式,是其核心特性之一。该设计模式使得在 Next.js 项目中创建和管理路由变得非常简单和直观。

1. Nextjs路由设计原则

  • 零配置,使用文件系统作为API
  • 只有JavaScript,一切皆是函数
  • 自动服务器渲染和代码拆分
  • 数据获取由开发人员决定

2. 旧版本路由模式

  1. 页面级路由:在 pages 目录下创建文件来定义页面级路由。每个文件对应一个页面,并且文件名确定了该页面的路由路径。例如, pages/index.js 对应根路径 /pages/about.js 对应 /about
  2. 动态路由:处理具有动态参数的路由。通过在文件名中使用方括号包裹参数名称,可以在路由路径中指定动态片段。例如, pages/post/[id].js 可以匹配类似 /post/1/post/2 这样的路由。
  3. 嵌套路由:创建具有父子关系的页面结构。通过在 pages 目录中的文件夹内创建文件,可以实现嵌套路由。例如, pages/blog/index.js 对应 /blog ,而 pages/blog/post.js 对应 /blog/post
  4. 客户端路由:Next.js 使用内置的客户端路由器来处理客户端导航。您可以使用 next/link 组件或 router 对象来实现客户端路由导航。此模式允许您在不重新加载整个页面的情况下进行导航和页面切换。
  5. API 路由:Next.js 还提供了内置的 API 路由模式,使您可以在项目中快速创建 API 端点。通过在 pages/api 目录下创建文件,您可以定义 API 路由并进行服务器端处理。

3. 新版本路由模式

路由路径 ,从 pages 改为 app。在新模式下中,使用小括号包起来的文件夹不会进入到实际路由,且每层路由必须使用文件夹包裹page.js \ page.ts\ page.jsx \ page.tsx

Parallel Routes平行路由

平行路由允许在同一布局中同时或有条件地呈现一个或多个页面。对于应用的高度动态部分(例如社交网站上的仪表板和源信息),平行路由可用于实现复杂的路由模式。

4. Root Layout

  • Root Layout文件必须创建,且Root layout必须定义HTMLbody标签,因为 Next.js 不会自动创建它们。
  • 不再需要从 Next.js 导入 <Html><Head><Body> 。可使用 React 直接编写 html 内容。
  • 可以使用内置的 SEO 支持来管理 HTML 元素,例如元素。
  • 默认情况下,根Layout是 Server 组件不是Client组件。
  • 可以添加 metadata 设置元信息。
import { Metadata } from 'next' 
export const metadata: Metadata = {  
title: '...', 
description: '...',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

5. Client Components 和 Server Components

在 App Router 中,NextJS 将会区分 Client ComponentsServer Components

Server Components

服务端组件,一种特殊的 React 组件,它不是在浏览器端运行,而是只能在服务器端运行。又因为它们没有状态,所以不能使用只存在于客户端的特性,例如useStateuseEffect 都是无法使用的,所以一般我们可以用于获取数据,或者对组件进行渲染(比如你要渲染 markdown 那对应的 JavaScript 依赖就只存在于客户端),从而达到减少客户端体积的作用!! .

注意! App Router 中的文件默认都是服务端组件.

Client Components

客户端组件,如果要使用客户端组件那就必须加上 use client ,并且这个命令会影响到子组件,如果父组件加上了 use client ,那么这个组件下所有的子组件都是客户端组件了(无需再添加use client).

只有在客户端才可以使用useStateuseEffect等 Rooks。

'use client';

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

6. Data fetching

在next13.4版本中,组件默认为服务端组件,大大减少了请求数据时的代码篇幅:

async function getData() {
	const res = await fetch('https://api.example.com/...')
	return res.json()
}
 
export default async function Page() {
  const data = await getData()
 
  return <main></main>
}

当我们把data fetching放入 Root Layout时,所有子页面都可以获取到fetch的数据.

7. 禁用缓存

  • 每次打包构建后,我们获取到的数据都是静态的,意味着无法获取到最新的数据async function getData() { const res = await fetch('https://api.example.com/...') return res.json(),{ cache:'no-store' } }

export default async function Page() {

const data = await getData()

return <main></main>

}当我们设置为no-store时,将不会对获取到的数据进行缓存。二、Turbopack1.介绍Turbopack 是一个由 Vercel(前身为 ZEIT)开发的工具和技术组合,旨在加快 Web 应用程序的构建和交付过程。它主要基于现有的 Next.js 框架,并结合了很多优化手段,提供了更快的启动时间、更小的包大小和更好的缓存策略,从而实现了更高效的前端开发和更好的用户体验。

2.启用 Turbopack

Turbopack 可以在 Next.js 和 目录中使用,以加快本地开发速度。要启用 Turbopack,请在运行 Next.js 开发服务器时使用该标志。

{
  "scripts": {
    "dev": "next dev --turbo",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  }
}

3. 为什么我们需要从webpack5升级到Turbopack?

  1. 构建速度: Turbopack 的设计目标之一是提供快速的构建和交付体验。它利用了 Vercel 的全球 CDN 和增量静态生成等优化功能,在部署时只构建和传输必要的内容,从而加快应用程序的启动时间和加载速度。相比之下,Webpack5 需要更多的配置和插件来实现类似的性能优化。
  2. Automatic Image Optimization(自动图像优化): Turbopack 自动处理和优化您应用中的图像,以提供最佳的加载性能。它会根据设备的屏幕大小和分辨率,动态调整图像的大小和质量,并使用现代的图像格式(如 WebP),以减少图像的文件大小和加载时间。Webpack5 需要使用额外的插件或加载器才能实现类似的功能。
  3. Incremental Static Generation(增量静态生成): Turbopack 使用 Next.js 的增量静态生成功能,根据用户的请求动态生成静态页面,并将其缓存起来。这意味着只有在需要时才会重新生成页面,其他情况下将直接使用缓存的版本,提供更快的页面加载速度和更高的性能。
  4. Edge Caching(边缘缓存): Turbopack 利用 Vercel 的 CDN 实现了边缘缓存,将您的应用程序静态资源缓存到全球各地的服务器上。这样一来,用户在访问应用时可以从离其最近的服务器获取内容,减少网络延迟并提高响应速度。Webpack5 不提供这样的一体化全球 CDN 和扩展功能。

4. 为什么不选择vite

Vite 依赖于浏览器的原生 ES Modules 系统,不需要打包代码,响应更新很快,但是如果文件过多,这种方式会导致浏览器大量进行网络请求,会导致启动时间相对较慢。所以nextjs作者选择同 webpack 一样方式,打包,但是使用了 Turbo 构建引擎,一个增量记忆化框架,永远不会重复相同的工作。

Turbopack 懒加载,当你访问3000端口,仅需要打包app路径下的index.js,且支持记忆化。

详细文档:Why Turbopack? – Turbopack

5.Turbopack的性能提升

Turbopack 性能的秘诀有两个:高度优化的机器代码和低层级增量计算引擎,可以缓存到单个函数的级别。它的架构吸取了 Turborepo 和 Google 的 Bazel 等工具的经验教训,它们都专注于使用缓存来避免重复执行相同的工作。

如图:

  • Turbopack 使用 Rust 编写,打包性能非常好。在生产环境 (production mode) 下,它跳过了打包过程,只打包开发环境下的代码。

  • Turbopack 与Webpack5进行对比

  • Turbopack 与Vite SWC在 dev server方面对比

Turbopack在多React Components 情况下,性能与vite SWC逐渐拉开

关于团队项目从webpack5向Turbopack进行迁移

  1. turbopack作为webpack的继任者,团队提供支持wepack应用的所有工具, 目前还无法从webpack迁移到turbo,但是不提供1:1的API兼容性.
  2. turbopack仍处于beta版本,未来可能提供对babel的支持.
  3. turbopack后续通过插件支持vuesevlte.

结语

关于这篇文章,已尽力涵盖各个方面,可能仍存在一些疏漏之处,还请大家能够不吝赐教,多加指点。