随着React框架和AI大模型爆火,全栈成为开发趋势。 下面我们来聊聊 React的顶级小迷弟——Next.js
初识Next.js
Next.js 作为 React 服务端渲染应用框架,优势显著。Next.js中文网
支持静态生成(SSG)与服务端渲染(SSR)两种预渲染方式,适配多样场景;基于页面的路由零配置,自动代码拆分优化加载;可静态导出成网站,内置了 CSS-IN-JS 库 styled-jsx
简化样式管理。
方案成熟,被众多公司用于生产,部署轻松,能适配 Vercel 及其他环境,是构建 SEO 友好 SPA 应用的理想之选。
1. 使用自动(CLI工具)创建
1.1 系统要求
- Node.js 18.18 或更高版本。
- 支持 macOS、Windows(包括 WSL)和 Linux。
1.2 创建项目
建议使用 create-next-app
启动一个新的 Next.js 应用,它会自动为你设置所有内容。要创建项目,请运行:
npx create-next-app@latest
接下来会有一系列的操作提示,比如设置项目名称、是否使用 TypeScript、是否开启 ESLint、是否使用 Tailwind CSS 等,根据自己的实际情况进行选择即可。如果刚开始你不知道如何选择,遵循默认选择即可(一路回车)
简单讲解一下对于use:
ESLint 是一个用于识别和报告JavaScript代码中问题的工具。它帮助保持代码风格一致并避免错误。
Tailwind CSS 是一个实用优先的CSS框架,通过在HTML中直接使用类名来快速构建自定义设计。
App Router 是Next.js的一个新功能,它提供了更灵活的路由管理方式,支持布局、嵌套路由等高级特性。
Import Alias 允许你为模块路径设置别名,比如用@/*代替相对或绝对路径,简化了模块导入语句,使项目结构更清晰。
1.3 运行项目
查看项目根目录 package.json
文件的代码:
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
我们可以看到脚本命令有 dev
、build
、start
、lint
,分别对应开发、构建、运行、代码检查。
开发的时候使用 npm run dev
。部署的时候先使用 npm run build
构建生产代码,再执行 npm run start
运行生产项目。运行 npm run lint
则会执行 ESLint 语法检查。
现在我们执行 npm run dev
运行项目吧!
2. Next路由
路由(Router)是next.js 作为单页面 SPA 重要的play的一环。在Next.js中,路由决定了一个页面如何渲染或者一个请求该如何返回。Next.js有两套路由解决方案,之前的方案称之为“PagesRouter”,目前的方案称之为“AppRouter”,两套方案目前是兼容的。
从Pages Router 到APP Router
前面使用create-next-app
创建的项目,打开发现默认并没有 pages
这个目录。查看 packages.json
中的 Next.js 版本,如果版本号大于 13.4
,那就对了!
Next.js 从 v13 起就使用了新的路由模式 —— App Router 为啥升级到APP Router 了?之前我们声明路由,在pages 目录创建页面。现在 升级为新的 App Router 后,现在的目录结构类似于:
src/
└── app
├── page.js
├── layout.js
├── template.js
├── loading.js
├── error.js
└── not-found.js
├── about
│ └── page.js
└── more
└── page.js
使用新的模式后,你会发现 app
下多了很多文件。这些文件的名字并不是我乱起的,而是 Next.js 约定的一些特殊文件。从这些文件的名称中你也可以了解文件实现的功能,比如布局(layout.js)、模板(template.js)、加载状态(loading.js)、错误处理(error.js)、404(not-found.js)等。
3. 使用 Pages Router
当然你也可以继续使用 Pages Router,如果你想使用 Pages Router,只需要在 src
目录下创建一个 pages
文件夹或者在根目录下创建一个 pages
文件夹。其中的 JS 文件会被视为 Pages Router 进行处理。
但是要注意,虽然两者可以共存,但 App Router 的优先级要高于 Pages Router。而且如果两者解析为同一个 URL,会导致构建错误。
4. 使用 App Router
开始起飞 ~~
4.1. 定义路由(Routes)
首先是定义路由,文件夹被用来定义路由。每个文件夹都代表一个对应到 URL 片段的路由片段。创建嵌套的路由,只需要创建嵌套的文件夹。举个例子, app/blog/article
目录对应的路由地址就是 /blog/article
:
4.2. 定义页面(Pages)
那如何保证这个路由可以被访问呢?你需要创建一个特殊的名为 page.js
的文件。至于为什么叫 page.js
呢?除了 page
有“页面”这个含义之外,你可以理解为这是一种约定或者规范。(如果你是 Next.js 的开发者,你也可以约定为 index.js
甚至 louis.js
!)
在上图这个例子中:
app/page.js
对应路由/
app/dashboard/page.js
对应路由/dashboard
app/dashboard/settings/page.js
对应路由/dashboard/settings
analytics
目录下因为没有page.js
文件,所以没有对应的路由。这个文件可以被用于存放组件、样式表、图片或者其他文件。
当然不止 .js
文件,Next.js 默认是支持 React、TypeScript 的,所以 .js
、.jsx
、.tsx
都是可以的。
那 page.js
的代码该如何写呢?最常见的是展示 UI,比如:
// app/page.js
export default function Page() {
return <h1>Hello, Next.js!</h1>
}
访问 http://localhost:3000/
,效果如下:
4.3. 定义布局(Layouts)
布局是指多个页面共享的 UI。在导航的时候,布局会保留状态、保持可交互性并且不会重新渲染,比如用来实现后台管理系统的侧边导航栏。
定义一个布局,你需要新建一个名为 layout.js
的文件,该文件默认导出一个 React 组件,该组件应接收一个 children
prop,chidren
表示子布局(如果有的话)或者子页面。
举个例子,我们新建目录和文件如下图所示:
(api文件夹暂时不使用,article文件夹下的page文件后文还会提及) 相关代码如下:
// app/blog/article
export default function Blog({children}) {
return (
<section>
<h1>My Blog 来到</h1>
{children}
</section>
)
}
// app/blog/page.js
export default function Page({ params }) {
return <div>My Post blog 页面</div>
}
当访问 /blog
的时候,效果如下:
其中,My Blog 来到
来自于 app/blog/layout.js
,My Post blog 页面
来自于 app/blog/page.js
你可以发现:同一文件夹下如果有 layout.js 和 page.js,page 会作为 children 参数传入 layout。换句话说,layout 会包裹同层级的 page。
app/blog/article/page
代码如下:
// app/blog/article/page.js
export default function article({children}) {
return (
<div>
<h1>Article 文章页</h1>
{children}
</div>
)
}
当访问 /blog/article
的时候,效果如下
你可以发现:布局是支持嵌套的,app/blog/article/page.js
会使用 app/layout.js
和 app/blog/layout.js
两个布局中的内容,不过因为我们没有在 app/layout.js
写入可以展示的内容,所以图中没有体现出来。
根布局(Root Layout)
布局支持嵌套,最顶层的布局我们称之为根布局(Root Layout),也就是 app/layout.js
。它会应用于所有的路由。除此之外,这个布局还有点特殊。
使用 create-next-app
默认创建的 layout.js
代码如下:
// app/layout.js
import './globals.css'
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
export const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
)
}
其中:
app
目录必须包含根布局,也就是app/layout.js
这个文件是必需的。- 根布局必须包含
html
和body
标签,其他布局不能包含这些标签。如果你要更改这些标签,不推荐直接修改。 - 你可以使用路由组创建多个根布局。
- 默认根布局是服务端组件且不能设置为客户端组件。
参考文献: