上一次写 Next 相关的东西都是 3 年前的事情了,这 3 年里 Next 也经历了 2-3 次的大版本变化。当时写的时候 Next 是 12 还是 13 的,现在已经是 15 了,从 build 到实现都有一些重大变化,因而就想着重新过一下关键点这部分内容没啥专门好的归纳,基本上学/写到哪里记到哪里,**里面讲了 Next 推荐的文件夹管理方式,以及路由、metadata、S

Next.js 实战笔记 1.0:架构重构与 App Router 核心机制详解

上一次写 Next 相关的东西都是 3 年前的事情了,这 3 年里 Next 也经历了 2-3 次的大版本变化。当时写的时候 Next 是 12 还是 13 的,现在已经是 15 了,从 build 到实现都有一些重大变化,所以就想着重新过一下关键点

这部分内容没啥特别好的归纳,基本上学/写到哪里记到哪里

更多内容可以在官方文档里面看到,我觉得一个比较有用的部分是这个:**Project structure and organization,**里面讲了 Next 推荐的文件夹管理方式,以及路由、metadata、SEO 之类的关键信息

构造

早起的版本中 Next 还是使用 webpack 做 bundle 的,从 Next 12 之后慢慢引入了 Rust 编写的 SWC(Speedy Web Compiler),到现在的 15 版本,已经开始引入 turbopack 去渐渐代替 webpack

找到的资料说,dev 模式自动开启 turbo,不过我看了下,好像还是要手动开启:

yarn dev --turbo
yarn run v1.22.22
$ next dev --turbo
▲ Next.js 14.0.3 (turbo)
- Local: http://localhost:3000
✓ Ready in 2.4s
❯ yarn dev
yarn run v1.22.22
$ next dev
▲ Next.js 14.0.3
- Local: http://localhost:3000
✓ Ready in 2.7s

可以看到有 --turbo flag 的才会开启 turbopack……

目前体感来说,使用 turbopack 会快不少,大概提速 30%-50%,不过我的练手项目都比较小,差别就在这几秒或者是几百毫秒的差别,不足以大到让我有明显的体感上的差别

❗ 看了一下,大概是 next 的 config 文件里面没有配置,所以默认 dev 没有开启 turbo

app router vs page router

新版的项目结构也有了一些的变化,比如说之前的 directory 叫 page,现在改成了 app 。Next 还有一个选项是把所有的代码包在 src 下面,我没选那个,这里提一句

这种转变,实际上是 Next 内部中实现的转变,即从 page router 转成了 app router,现在推荐使用的是 app router,因为 Next 基于 app router 实现了很多新的功能,同样也是未来的转变方向

二者核心对比:

功能Page Router (pages/)App Router (app/)
路由机制文件系统自动生成路由文件系统自动生成嵌套路由
支持 Layout❌ 仅支持 _app.js 全局包装✅ 支持嵌套 layout.tsx
支持 Server Components❌ 仅客户端组件(可用 SSR)✅ 默认是 Server Component
支持 Streaming❌ 不支持✅ 支持分块传输 / loading UI
Data fetchinggetServerSideProps, getStaticProps, getInitialPropsfetch() in Server Component
Middleware 支持
动态路由[id].js[id]/page.tsx
API Routespages/api/*✅ 仍使用 pages/api/*
文件结构限制只有一个页面文件允许多个文件组合构成页面(如 loading.tsx, error.tsx
状态成熟度✅ 成熟稳定? 仍在改进(尤其是缓存行为)

server component

这应该是 page router 和 app router 最大的区别了,旧版的 page router 中,默认的还是 client side rendering,在 build 的阶段将数据写入 HTML 中。新版的 app router 则是 app 文件夹下默认所有的组件都在服务端生成,其中的一些状态和日志不会在 client 端显示,只会在服务端显示,如下面这个 log:

page.js should render as page, and is server component, which will be rendered at server

前面的 server 标记了是 server 端的内容,在正式打包后就会被去除

另一个需要注意的是,server component 不能用 hooks,这是 client component 专用的。如果要使用 hooks 的话,需要在文件头标注 use client;,这样这个组件下所有的内容都会在 client 端生成,否则就会报错:

如果想要利用好 Next 的 server side rendering,那么就尽可能的抽象组件,尽可能的在末端使用 use client

路由

基础的路由比较简单,新加一个文件夹,并且创建对应的 page.js 文件即可:

动态路由

根据官方文档显示,显示的 directory 的名称应该如下:

[folder]Dynamic route segment
[...folder]Catch-all route segment
[[...folder]]Optional catch-all route segment

并且在对应的文件夹下创建 page.js 文件即可

路由组与私有路由

根据官方文档,实现如下:

(folder)Group routes without affecting routing
_folderOpt folder and all child segments out of routing

layout

这个也是 Next 提升了很多的地方,这是目前 template 中的 layout:

import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly) {
return (
{children}
);
}

其中, metadata 就是当前页面绑定的关键词,这也是个保留词。使用当前 layout 的所有页面,都会共享这里面的布局和 metadata

除此之外,Next 做的改进就是,每个文件夹下面都可以有它独立的 layout,这是不影响外层布局的。如果有这个需求的话,这个用途/设定挺好的

Image

Next15 也对其做了不少的改进,之前主要用的是 lazy loading 的特性,这次发现了一个 priority,即与 lazy loading 相反的特性,很适合加在 logo/banner 等地方

加载数据

现在 Next 所有的组件默认都是 server component 了,因此也不太需要使用 useEffect 去渲染数据,而是可以直接创建新的 async 组件,如:

const Meals = async () => {
const meals = await getMeals();
return ;
};

加载状态

这里我主要新创建了一个 loading.js 文件,然后搭配了 Suspense 使用:

import React from "react";
import classes from "./loading.module.css";
const MealsLoadingPage = () => {
return Fetching meals...;
};
export default MealsLoadingPage;
const MealsPage = () => {
return (
<>
Delicious meals, created{" "}
by you
Lorem ipsum dolor sit amet consectetur adipisicing elit. Magnam
voluptatibus fuga voluptas temporibus porro consequatur totam nihil
quae omnis eos blanditiis asperiores, repudiandae itaque officia
optio? Repudiandae recusandae sit sequi?
Share Your Favorite Recipe
}>
);
};

效果如下:

如果不使用 Suspense 的话,那么整个页面都会被 loading.js 所接管

posted @ 2025-07-28 21:46  yfceshi  阅读(7)  评论(0)    收藏  举报