Next.js开发笔记

Next.js开发笔记

Next.js是基于react的一个全栈框架,提供的功能和Nuxt.js基本一样。

Next.js主要是为了解决react的如下问题:

  • js环境
  • 首屏加载慢
  • 安全问题
  • SEO

Next.js通过将渲染这个过程移动到服务端(将生成DOM放在服务端完成)来解决以上问题,也就是SSR。

初始化项目

bash
1
2
3
4
npx create-next-app@latest project-name

# 使用ts
npx create-next-app@latest --typescript project-name

目录结构

nextjs目录结构

路由

静态路由

静态路由是指在编译时就确定了路由和其对应的页面文件。

pages下创建文件即可生成对应的路由配置。

动态路由

可以在pages目录下创建文件名,文件名是变量的形式[param].ts

比如,如果想获取一个article页面的参数id,可以在article下定义名为[id].ts的文件,然后在这个文件内可以使用useRouter来获取id。

API静态路由

API路由允许我们再next.js项目章自定义服务端逻辑,可以处理客户端发起的http请求。

创建方法:

  1. pages/api下创建一个文件,文件名即为路由,这里创建了user.ts文件。

  2. user.ts中编写处理请求的代码。

user.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import type { NextApiRequest, NextApiResponse } from 'next'

type Data = {
code: number
users: string[]
}

export default function handler(req: NextApiRequest, res: NextApiResponse<Data>) {
const users: string[] = ['Alice', 'Bob', 'Charlie']
res.status(200).json({
code: 0,
users,
})
}
  1. 最后访问地址为/api/user的API即可获取到数据。

API动态路由

除了上面的静态路由,next.js还可以实现动态路由(也就是在路由中允许参数)。

创建方法:

  1. pages/api下创建一个文件,文件名形如[id].ts,文件名即为路由。

  2. [id].ts中编写处理请求的代码,在代码中可以获取到id

[id].ts
1
2
3
4
5
6
7
8
9
10
import type { NextApiRequest, NextApiResponse } from 'next'

type Data = {
message: string
}

export default function handler(req: NextApiRequest, res: NextApiResponse<Data>) {
const { id } = req.query
res.status(200).json({ message: Received request for ID: ${id} })
}
  1. 最后访问地址为/api/:id的API即可获取到对应id的数据。

SSR & SSG

这里有3个重要的方法。

  • getServerSideProps:服务端渲染,在请求时运行

  • getStaticProps:服务端生成,生成静态页面时运行

  • getStaticPaths:服务端生成,生成静态页面时运行

声明SSR页面

在页面组件内添加一个getServerSideProps函数。

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 正常的页面组件
const Post = ({data}) => {
return <div>{ data }</div>
}

export default Post

// 将该页面声明为SSR页面,下方函数是在服务端执行的
export async function getServerSideProps(context) {
// 取出id
const { id } = context.query

// 根据id查询接口
const res = await fetch(`/article/${id}`).then(data => data.json())

return {
// 这里的props会被传入到上方组件中
props: {
data: res,
},
}
}

声明SSG页面

如果将以上代码的getServerSideProps改为getStaticProps,那么代码会在build的时候运行,此时文件会变为在build时渲染出来。

但是我们不知道用户会访问哪个id,所以需要搭配getStaticPaths来使用,getStaticPaths就是用来枚举用户可能访问的id。

下面生成一些用户可能访问的id:

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 正常的页面组件
const Post = ({data}) => {
return <div>{ data }</div>
}

export default Post

// 将该页面声明为SSR页面,下方函数是在服务端执行的
export async function getStaticProps(context) {
// 取出id
const { id } = context.query

// 根据id查询接口
const res = await fetch(`/article/${id}`).then(data => data.json())

return {
// 这里的props会被传入到上方组件中
props: {
data: res,
},
}
}

// 下面会在build阶段生成id从1到100的页面
export async function getStaticPaths() {
return {
paths: _.range(1, 100).map((id) => {
return {
params: {
id: id + '',
},
}
})
// id未命中时退化为SSR
fallback: 'blocking',
}
}

fallback的取值还有:false(404),true(退化到CSR)。

增量静态生成(ISR)

自动重新生成

添加revalidate参数,表示这个静态页面最多可存活的秒数,如果当用户请求页面时这个页面已经生成了超过10s则会重新生成该页面。可以用来保证静态页面是最新的。

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 正常的页面组件
const Post = ({data}) => {
return <div>{ data }</div>
}

export default Post

// 将该页面声明为SSR页面,下方函数是在服务端执行的
export async function getStaticProps(context) {
// 取出id
const { id } = context.query

// 根据id查询接口
const res = await fetch(`/article/${id}`).then(data => data.json())

return {
// 这里的props会被传入到上方组件中
props: {
data: res,
},
// 最多存活10s
revalidate: 10,
}
}

// 下面会在build阶段生成id从1到100的页面
export async function getStaticPaths() {
return {
paths: _.range(1, 100).map((id) => {
return {
params: {
id: id + '',
},
}
})
// id未命中时退化为SSR
fallback: 'blocking',
}
}

手动重新生成

pages/api目录下创建一个文件,文件名即路由,在文件中手动调用revalidate方法即可。

参考

  1. https://nextjs.frontendx.cn/
  2. https://www.nextjs.cn/

评论