Skip to content

Next13

[TOC]

什么是Next

Next.js 是一个React框架,支持CSR、SSR、SSG、ISR (Incremental Static Regeneration)等渲染模式。

Next.js 提供了创建 Web 应用程序的构建块,比如:

  • 用户界面、路由、数据获取、渲染模式、后端服务等等

Next.js 不但处理 React 所需的工具和配置,还提供额外的功能和优化,比如:

  • UI构建, CSR、SSR、SSG、ISR 渲染模式,Routing、Data Fetching等等。

中文官网:https://www.nextjs.cn/docs/getting-started

英文官网:https://nextjs.org/docs/getting-started

image-20240911160746941

Next.js 发展史

Next.js 于2016 年 10 月 25 日首次作为开源项目发布在GitHub上,最初是基于六个原则开发的:

  • 开箱即用、无处不在的JS、所有函数用JS编写、自动代码拆分和服务器渲染、可配置数据获取、预期请求和简化部署。

Next.js 2.0 于 2017 年 3 月发布,改进后的版本让小型网站的工作变得更加容易,还提高了构建和热模块替换效率。

7.0 版于 2018 年 9 月发布,改进了错误处理并支持 React 的上下文 API。升级到了webpack4

8.0 版于 2019 年 2 月发布,第一个提供 Serverless 部署的版本。

2020 年 3 月发布的 9.3 版包括各种优化和全局Sass和 CSS 模块支持。

2020 年 7 月 27 日,Next.js 9.5 版发布,增加了增量静态再生成、重写和重定向支持等新功能。

2021 年 6 月 15 日,Next.js 版本 11 发布,其中包括:Webpack 5 支持

2021 年 10 月 26 日,Next.js 12 发布,添加了 Rust 编译器,使编译速度更快

2022 年 10 月 26 日,Vercel 发布了 Next.js 13。

  • 带来了一种新的路由模式,增加了app目录 、布局布局、服务器组件和一组新的数据获取方法等(目前是 beta 版本)
  • 编译和压缩等由 Babel + Terser 换为 SWC( Speedy Web Compiler ),构建工具增加了 Turbopack。

Next.js 特点

开箱即用,快速创建:

  • Next.js 已经帮我集成好了各种技术栈,比如:React、webpack、路由、数据获取、SCSS、TypeScript等等
  • 也提供了专门的脚手架:create-next-app

约定式路由(目录结构即路由)

  • Next.js和Nuxt3一样,所有的路由都是根据 pages目录结构自动生成。但在 Next.js 13 beta 版本增加了app目录。

内置CSS模块和Sass支持:

  • 自从Next.js 9.3 以后就内置了CSS模块和Sass支持,也是开箱即用

全栈开发能力:

  • Next.js不但支持前端开发,还支持编写后端代码,比如:可开发登录验证、存储数据、获取数据等接口

多种渲染模式:支持CSR、SSR、SSG、ISR等渲染模式,当然也支持混合搭配使用

利于搜索引擎优化:

  • Next.js支持使用服务器端渲染,同时它也是一个很棒的静态站点生成器,非常利于SEO和首屏渲染

Next.js VS Nuxt3

Next.js 和 Nuxt3的相同点

  • 利于搜索引擎优化,都能提高首屏渲染速度
  • 零配置,开箱即用
  • 都支持目录结构即路由、支持数据获取、支持TypeScript
  • 服务器端渲染、静态网站生成、客户端渲染等
  • 都需要 Node.js 服务器,支持全栈开发

Next.js 和 Nuxt3区别:

  • Next.js 使用的是React技术栈:React 、webpack 、express 、node.....
  • Nuxt3 使用的是Vue技术栈:Vue、webpack、vite、h3、nitro、node.....
  • Nuxt3 支持组件、组合 API、Vue API等自动导入,Next.js则不支持
  • Next.js 社区生态、资源和文档都会比Nuxt3友好(star数: Nuxt3 -> 41.6k 和 Next.js -> 96.8k )

Next.js 和 Nuxt3如何选择? 个人建议如下:

  • 首先根据自己擅长的技术栈来选择,擅长Vue选择Nuxt3,擅长React选择Next.js
  • 需要更灵活的,选择Next.js
  • 需要简单易用、快速上手的,选择Nuxt3

Next.js 13 环境搭建

在开始之前,请确保您已安装推荐的设置:

  • Node.js (要求 Node.js 14.6.0 或 更高版本。 )
  • Git(window下可以用其随附的 Git Bash 终端命令)
  • Visual Studio Code

创建一个项目,项目名不支持大写

  • 方式一: npx create-next-app@latest --typescript
  • 方式二: yarn create next-app --typescript
  • 方式三: pnpm create next-app –typescript
  • 方式四:npm i create-next-app@latest –g && create-next-app

运行项目

  • npm run dev
  • yarn dev
  • pnpm dev

image-20240911160805560

Next.js 目录结构

image-20240911160815710

入口App组件(_app.tsx)

_app.tsx是项目的入口组件,主要作用:

  • 可以扩展自定义的布局(Layout)
  • 引入全局的样式文件
  • 引入Redux状态管理
  • 引入主题组件等等
  • 全局监听客户端路由的切换

image-20240911160827051

image-20240911160835528

ts.config.json 的配置

Next.js默认是没有配置路径别名的,我们可以在ts.config.json中配置模块导入的别名:

  • baseUrl :配置允许直接从项目的根目录导入,比如: import Button from 'components/button'
  • paths:允许配置模块别,比如: import Button from '@/components/button'

image-20240911160850278

注意:如生效可以重启编辑器

环境变量(.env*)

定义环境变量的4种方式:

  • .env:所有环境下生效的默认设置
  • .env.development:执行 next dev 时加载并生效
  • .env.production : 执行 next start 时加载并生效
  • .env.local :始终覆盖上面文件定义的默认值。所有环境生效,通常只需一个.env.local 文件就够了(常用存储敏感信息)

环境变量定义语法(支持变量,例如 $PORT):

  • 大写单词,多个单词使用下划线,比如:DB_HOST=localhost
  • 添加 NEXT_PUBLIC_ 前缀会额外暴露给浏览器,比如:NEXT_PUBLIC_ANALYTICS_ID=aaabbbccc

环境变量的获取:

  • .env 文件中定义环境变量会加载到 process.env 中。两端都可直接通过 process.env.xxx 访问使用(不支持解构)

注意事项:

  • 由于 .env、.env.development 和 .env.production 文件定义了默认设置,需提交到源码仓库中。
  • 而 .env.*.local 应当添加到 .gitignore 中,因为这类文件是需要被忽略的。

image-20240911160908411

Next.js配置(next.config)

next.config.ts 配置文件位于项目根目录,可对Next.js进行自定义配置,比如,可以进行如下配置:

  • reactStrictMode: 是否启用严格模式,辅助开发,避免常见错误,例如:可以检查过期API来逐步升级
  • env:配置环境变量,配置完需要重启
    • 会添加到 process.env.xx 中
    • 配置的优先级: next.config.js中的env > .env.local > .env
  • basePath:要在域名的子路径下部署 Next.js 应用程序,您可以使用basePath配置选项。
    • basePath:允许为应用程序设置URl路径前缀。
    • 例如 basePath=/music, 即用 /music 访问首页,而不是默认 /
  • images:可以配置图片URL的白名单等信息
  • swcMinify: 用 Speedy Web Compiler 编译和压缩技术,而不是 Babel + Terser 技术

更多的配置: https://nextjs.org/docs/api-reference/next.config.js/introduction

内置组件

Next.js框架也提供了几个内置组件,常用的有:

  • Head:用于将新增的标签添加到页面的 head 标签中,需要从 next/head 中导入
    • 如果想要给所有页面统一添加的,那需在pages目录下新建 _document.js 文件来定制HTML页面
  • Script:将一个script标签到页面的 body 中(不支持在_document.js 中用),需要从 next/script 中导入
  • Link:可以启用客户端的路由切换,需从 next/link 导入
  • Image:内置的图片组件(对 img 的增强)。需从 next/image 导入

image-20240911160925866

image-20240911160938031

Image组件

Image:内置的图片组件,是对 img 的增强,需从 next/image 导入。

Image组件常用属性

  • src 属性:
    • 引入本地图片资源,会自动确认图片的宽高,
    • 引入外部资源需,需手动给宽高,还需配置白名单。
  • width/height:是 number 类型,不支持100%等字符串
  • priority:将图片标记为 LCP ( Largest Contentful Paint )元素,允许预加载图像。
    • 建议大图,并在首屏可见时才应使用该属性。默认为 false
  • placeholder:图片占位,默认值为empty,当值为blur需和blurDataURL一起用
  • fill :让图片填充父容器大小,父容器需设为相对定位

image-20240911160952653

image-20240911160959010

全局和局部样式

Next.js 允许在 JavaScript 文件中直接通过 import 关键字来导入CSS 文件(不是:@import )

全局样式:

  • 在 assets 目录或 styles 目录下编写,然后在 pages/_app.js 入口组件中导入
  • 也支持导入node_modules中样式,导入文件后缀名不能省略

局部样式:

  • Next.js 默认是支持 CSS Module的,如:[name].module.css
  • CSS Module 中的选择器会自动创建一个唯一的类名。
  • 唯一类名保证在不同的文件中使用相同CSS类名,也不用担心冲突

内置Scss支持

  • 用 scss 之前,需安装Sass: npm i sass –D
  • xx.module.scss文件:export中定义的变量,可导出供JavaScript中用

image-20240911161010822

image-20240911161018798

静态资源引用

public目录

  • 常用于存放静态文件,例如:robots.txt、favicon.ico、img等,并直接对外提供访问。
  • 访问需以 / 作为开始路径,例如:添加了一张图片到 public/me.png中
    • 可通过静态URL: /me.png 访问,如右图
    • 静态URL也支持在背景中使用
  • 注意: 确保静态文件中没有与 pages/ 下的文件重名,否则导致错误。

assets目录

  • 常用存放样式、字体 、图片或 SVG 等文件
  • 可用 import 导入 位于assets目录的文件,支持相对路径和绝对路径
    • import Avatar from “../assets/images/avatar.png”
    • import Avatar from “@/assets/images/avatar.png”
  • 背景图片和字体: url("~/assets/images/bym.png")

image-20240911161028668

字体图标

字体图标使用步骤

  • 1.将字体图标存放在 assets 目录下
  • 2.字体文件可以使用相对路径和绝对路径引用。
  • 3.在_app.tsx文件中导入全局样式
  • 4.在页面中就可以使用字体图标了

image-20240911161040397

新建页面

Next.js项目页面需在pages目录下新建( .js, .jsx, .ts, or .tsx )文件,该文件需导出的React组件。

Next.js 会根据 pages 目录结构和文件名,来自动生成路由,比如:

  • pages/index.jsx/ (首页, 一级路由)
  • pages/about.jsx/about (一级路由)
  • pages/blog/index.jsx/blog (一级路由)
  • pages/blog/post.jsx/blog/post (嵌套路由,一级路由)
  • pages/blog/[slug].jsx /blog/:slug (动态路由, 一级路由)

新建页面步骤:

  • 1.新建一个命名为 pages/about.jsx 组件文件,并导出(export)React 组件。
  • 2.接着通过 /about 路径,就可访问新创建的页面了。

注意:Nuxt3 需要添加<NuxtPage>内置组件占位, Next.js则不需要

image-20240911161049936

页面之间的跳转需要用到<Link>组件,需从 next/link 包导入。

Link组件底层实现是一个 <a> 标签,所以使用 a + href 也支持页面切换(不推荐, 会默认刷新浏览器)

<Link>组件属性:

  • href 值类型(不支持 to)
    • 字符类型: / /home/about
    • 对象类型:{ pathname:’’ , query : { } }
    • URL:外部网址
  • as:在浏览器的 URL 栏中显示的路径的别名。
  • replace:替换当前url页面,而不是将新的 url 添加到堆栈中。默认为 false
  • target:和a标签的target一样,指定何种方式显示新页面

image-20240911161103218

image-20240911161110869

编程导航 (useRouter)

Next13除了可以通过<Link>组件来实现导航,同时也支持使用编程导航。

编程导航可以轻松的实现动态导航了,缺点就是不利于SEO。

我们可以从 next/router 中导入 useRouter 函数(或 class 中用 withRouer),调用该函数可以拿到 router对象进行编程导航。

router 对象的方法:

  • push( url [, as , opts] ) :页面跳转
  • replace( url [, as , opts] ) :页面跳转(会替换当前页面)
  • back():页面返回
  • events.on(name, func):客户端路由的监听(建议在_app.tsx监听)
    • routeChangeStart
    • routeChangeComplete
  • beforePopState :路由的返回和前进的监听。 (建议在_app.tsx监听)
  • ....

image-20240911161120018

动态路由

Next.js也是支持动态路由,并且也是根据目录结构和文件的名称自动生成。

动态路由语法:

  • 页面组件目录 或 页面组件文件都 支持 [ ] 方括号语法(方括号前后不能有字符串)。
  • 方括号里编写的字符串就是:动态路由的参数。

例如,动态路由 支持如下写法:

  • pages/detail/[id].tsx -> /detail/:id
  • pages/detail/[role]/[id].tsx -> /detail/:role/:id
  • pages/detail-[role]/[id].tsx -> /detail-:role/:id

路由参数(useRouter)

动态路由参数

  • 1.通过 [] 方括号 语法定义动态路由,比如:/post/[id].tsx
  • 2.页面跳转时,在URL路径中传递动态路由参数,比如:/post/10010
  • 3.动态路由参数将作为查询参数发送到目标页面,并与其他查询参数合并
  • 4.目标页面通过 router.query 获取动态路由参数(注意:Next.js 是 router, Nuxt3 是 route)

查询字符串参数

  • 1.页面跳转时,通过查询字符串方式传递参数,比如:/post/10010?name=liujun
  • 2.目标页面通过 router.query 获取查询字符串参数
  • 3.如果路由参数和查询参数相同,那么 路由参数 将覆盖同名的 查询参数。

image-20240911161133888

404 Page

方式一:捕获所有不匹配的路由(即 404 not found 页面)

  • 通过在方括号内添加三个点 ,如:[...slug].tsx 语法,如在其它目录下的话,仅作用于该目录以及子目录
    • 比如:访问 pages/post/[...slug].js 路径,将匹配/post/a 、/post/a/b、/post/a/b/c等,但不匹配 /post
    • 注意:是可以使用除了slug以外的名称,例如:[...param].tsx
  • [...slug] 匹配的参数将作为查询参数发送到页面,并且它始终是一个数组
    • 如: 访问 /post/a 路径,对应的参数为: { "slug": ["a"] }
    • 如:访问 /post/a/b 路径,对应的参数为: { "slug": ["a", "b"] }

方式二(推荐):在 pages 根目录新建 404.tsx 页面(注意:只支持根目录)

  • 当然还支持 500.tsx 文件,即客户端或者服务器端报错

路由匹配规则

路由匹配优先级, 即预定义路由优先于动态路由,动态路由优先于捕获所有路由。请看以下示例:

  • 1.预定义路由:pages/post/create.js
    • 将匹配 /post/create
  • 2.动态路由 :pages/post/[pid].js
    • 将匹配/post/1, /post/abc 等。
    • 但不匹配 /post/create 、 /post/1/1 等
  • 3.捕获所有路由:pages/post/[...slug].js
    • 将匹配 /post/1/2, /post/a/b/c 等。
    • 但不匹配/post/create, /post/abc、/post/1、、/post/ 等

中间件(middleware)

Next.js的中间件允许我们去拦截客户端发起的请求,例如:API请求、router切换、资源加载、站点图片等。

拦截客服端发起的请求等等之后,便可对这些进行:重写、重定向、修改请求响应标头、或响应等操作。

使用中间件需按照以下步骤操作:

  • 1.在根目录中创建 middleware.ts 文件
  • 2.从 middleware.ts 文件中导出一个中间件middleware函数(支持 async,并只允许在服务端),会接收两个参数:
    • req:类型为 NextRequest
    • event:类型为 NextFetchEvent
  • 3.通过返回NextResponse对象来实现重定向等功能
    • next()- 将继续中间件链
    • redirect()- 将重定向,如:重定向到某个页面
    • rewrite()- 将重写URL,如:配置反向代理
  • 4.没返回值:页面将按预期加载 和 返回 next() 一样

image-20240911161155912

匹配器(Matcher)

匹配器允许我们过滤中间件以在特定路径上运行,比如:

  • matcher: ‘/about/:path*, 意思是匹配以 /about/* 开头的路径。其中路径开头的:是修饰符, 而 * 代表0个 或 n个
  • matcher: [‘/about/:path*’, ‘/dashboard/:path*’] , 意思是匹配以 /about/*/dashboard/* 开头的路径 - matcher: [‘/((?!api|_next/static|favicon.ico).*)‘] ,意思是不匹配以 api、_next、static、favicon.ico 开头的路径

image-20240911161213109

注意:上面的 path 是占位符, 不是固定的。

路由拦截

下面我们通过 中间件 + 匹配器 来实现路由的拦截:

  • matcher: ['/((?!api|_next/static|favicon.ico).*)']

image-20240911161224190

布局组件(Layout)

Layout布局是页面的包装器,可以将多个页面的共性东西写到Layout布局中,使用 props.children 属性来显示页面内容

  • 例如:每个页面的页眉和页脚组件,这些具有共性的组件我们是可以写到一个Layout布局中。

Layout布局的使用步骤:

  • 1.在components目录下新建 layout.tsx 布局组件
  • 2.接着在_app.tsx中通过<Layout>组件包裹<Component>组件

image-20240911161248071

image-20240911161239189

嵌套布局(NestLayout)

Layout布局可以作为所有页面的容器,也可以给每个页面一个单独的布局也是可以的,并且也可以在布局中嵌套布局。

因此,我们可以利用布局再嵌套一个布局来实现二级路由。

image-20240911161258395

嵌套路由

Next.js 和 Nuxt3一样,也支持嵌套路由(但是只在app目录下),也是根据目录结构和文件的名称自动生成。

二级路由实现有两种方案:

  • 方案一:使用Layout布局嵌套来实现
  • 方案二:使用Next.js 13版本,新增的app目录(目前 beta 版本)

image-20240911161309315

App目录和布局

Next.js 13版本,新增的app目录(目前 beta 版本,还是处于实验性阶段,需要在配置开始)

第一步:创建app目录

第二步:创建根HTML布局:layout.tsx

第三步:创建首页: page.tsx

第四步:创建head.tsx,定制head

第五步:创建其它页面和布局

  • page.tsx
  • layout.tsx

image-20240911161319469

组件生命周期

客户端渲染

image-20240911161334336

服务器端渲染

  • constructor
  • UNSAFE_componentWillMount
  • render -> functon component 本身

axios封装

安装依赖库

  • npm i axios –save

封装axios步骤

  • 1.定义HYRequest类,并导出
  • 2.在类中定义request、get、post方法
  • 3.在request中使用axios发起网络请求
  • 4.添加TypeScript类型声明

image-20240911161354558

API Routes

Next.js 提供了编写后端接口的功能(即 API Routes),编写接口可以在 pages/api 目录下编写

在 pages/api 目录下的任何 API Routes 文件都会自动映射到以 /api/* 前缀开头接口地址

比如:编写一个 /api/user 接口

  • 1.在 pages/api 目录下新建 user.ts
  • 2.接在在该文件中使用 handler 函数来定义接口
  • 3.然后就可以用 fetch 函数 或 axios 轻松调用: /api/user 接口了

image-20240911161406579

认识预渲染

认识预渲染

  • 默认情况下,Next.js 会 预渲染 每个页面,即预先为每个页面生成 HTML 文件,而不是由客户端 JavaScript 来完成。
  • 预渲染可以带来更好的性能和 SEO 效果。
  • 当浏览器加载一个页面时,页面依赖JS代码将会执行,执行JS代码后会激活页面,使页面具有交互性。(此过程称Hydration)

Next.js 具有两种形式的预渲染:

  • 静态生成 (推荐):HTML 在 构建时 生成,并在每次页面请求(request)时重用。
  • 服务器端渲染:在 每次页面请求(request)时 重新生成 HTML页面。

提示:出于性能考虑,相对服务器端渲染,更 推荐 使用 静态生成 。

SSG-静态生成(一)

静态生成(也称SSG 或 静态站点生成)

  • 如果一个页面使用了 静态生成,在 构建时 将生成此页面对应的 HTML 文件 。这意味着在生产环境中,运行 next build 时将生成该 页面对应的 HTML 文件。然后,此 HTML 文件将在每个页面请求时被重用,还可以被 CDN 缓存。
  • 在 Next.js 中,你可以静态生成 带有或不带有数据 的页面。接下来我们分别看看这两种情况。

生成不带数据的静态页面

  • 默认情况下,Next.js 使用 “静态生成” 来预渲染页面但不涉及获取数据。如下例所示:
  • 请注意:
    • 此页面在预渲染时不需要获取任何外部数据。
    • 在这种情况下,Next.js 只需在构建时为每个页面生成一个 HTML 文件即可。

image-20240911161424443

image-20240911161433782

SSG-静态生成(二)

需要获取数据的静态页面生成

  • 当某些页面需要获取外部数据以进行预渲染,通常有两种情况:
    • 情况一:页面 内容 取决于外部数据:使用 Next.js 提供的 getStaticProps 函数。
    • 情况二:页面 paths(路径) 取决于外部数据:使用Next.js 提供的 getStaticPaths 函数(通常还要同时用 getStaticProps)。

情况一:页面 内容 取决于外部数据

  • 比如,发起网络请求拿到页面书籍列表的数据,并展示。
  • 具体的使用步骤是:
    • 1.先在getStaticProps函数中借助axios获取到数据
    • 2.拿到异步数据之后 return 给页面组件
    • 3.页面就可通过props拿到数据来渲染页面
    • 4.在build时,经过以上步骤,一个静态页面就打包生成

image-20240911161447524

SSG-静态生成(三)

情况二:页面 paths(路径) 取决于外部数据

  • 例如,新建一个动态路由页面,然后发起网络请求拿到书本列表,然后每本书的信息都使用单独详情页面显示。
  • 简单的理解就是,在build 阶段时,动态拿到n本书,然后根据n书动态生成n个静态详情页面。

image-20240911161500675

image-20240911161506254

静态生成应用场景

建议尽可能使用静态生成(无论有 与 没有数据),因为静态生成的页面可以构建一次,并可由 CDN 提供服。

我们可以为多种类型的页面使用静态生成,包括:

  • 营销页面、官网网站
  • 博客文章、投资组合
  • 电子商务产品列表、帮助和文档

如果在用户请求之前就可以预渲染页面,那么应该选择静态生成。反之,静态生成就不合适了。

例如,页面要显示经常更新的数据,并且页面内容会在每次请求时发生变化,这时可以这样选择:

  • 静态生成与客户端数据获取结合使用:
    • 我们可以跳过预呈现页面的某些部分,然后使用客户端 JS 来填充它们,但是客户端渲染是不利于SEO优化的,例如:
      • 在useEffect 中获取数据,在客户端动态渲染页面。
  • 服务器端呈现(也称动态呈现):
    • Next.js 会根据每个请求预呈现一个页面。缺点是稍微慢一点,因为页面无法被 CDN 缓存,但预渲染页面将始终是最新的。

服务器端渲染(SSR)

服务器端渲染(也称SSR 或 动态渲染)

  • 如果页面使用的是 服务器端渲染,则会在 每次页面请求时 重新生成页面的 HTML 。
  • 要对页面使用服务器端渲染,你需要 export 一个名为 getServerSideProps 的 async 函数。
  • 服务器将在每次页面请求时调用此函数。

例如,假设你的某个页面需要预渲染频繁更新的数据(从外部 API 获取)。你就可以编写 getServerSideProps 获取该数据并将 其传递给 Page ,如下所示:

image-20240911161521054

服务器端渲染(注意事项)

我们知道getStaticProps和getStaticPaths函数都是在build阶段运行,那么getServerSideProps函数的运行时机是怎么样的呢?

getServerSideProps运行时机:

  • 首先,getServerSideProps仅在服务器端运行,从不在浏览器上运行。
  • 如果页面使用 getServerSideProps,则:
    • 当直接通过URL请求此页面时,getServerSideProps在请求时运行,并且此页面将使用返回的 props 进行预渲染
    • 当通过 Link 或 router切换页面来请求此页面时,Next.js 向服务器发送 API 请求,服务器端会运行getServerSideProps

什么时候该使用getServerSideProps?

  • 当页面显示的数据必须在请求时获取的,才应使用getServerSideProps 。
    • 如:页面需要显示经常更新的数据,并且页面内容会在每次请求时发生变化。
  • 如过页面使用了getServerSideProps函数,那么该页面将在客户端请求时,会在服务器端渲染,页面默认不会缓存。
  • 如果不需要在客户端每次请求时获取页面数据,那么应该考虑在 客户端动态渲染 或 getStaticProps.

增量静态再成(ISR)

Next.js 除了支持静态生成 和 服务器端渲染,Next.js 还允许在构建网站后创建或更新静态页面。

这种模式称为:增量静态再生(Incremental Static Regeneration),简称(ISR)。

比如我们继续实现前面的案例:

  • 发起网络请求拿到页面书籍列表的数据,并展示。这次我们使用ISR渲染模式,让服务器端每隔5s重新生成静态书籍列表页面

image-20240911161539405

客户端渲染(CSR)

Next.js 除了支持在服务器端获取数据,同时也是支持在客户端获取数据,并在客户端进行渲染。

在客户端获取数据,需要在页面组件或普通组件的 useEffect 函数中获取,比如:

image-20240911161555727

Next.js 集成 Redux

安装依赖库

  • npm i next-redux-wrapper --save
    • 可以避免在访问服务器端渲染页面时store的重置
    • 该库可以将服务器端redux存的数据,同步一份到客户端上
    • 该库提供了HYDRATE调度操作
      • 当用户访问动态路由或后端渲染的页面时,会执行Hydration来保持两端数据状态一致
      • 比如:每次当用户打开使用了getStaticProps或getServerSideProps函数生成的页面时,HYDRATE将执行调度操作。
  • npm i @reduxjs/toolkit react-redux --save

创建counter模块的reducer

我们先创建counter模块的reducer: 通过createSlice创建一个slice。

createSlice主要包含如下几个参数:

  • name:用来标记slice的名词
    • redux-devtool中会显示对应的名词;
  • initialState:第一次初始化时的值;
  • reducers:相当于之前的reducer函数
    • 对象类型,并且可以添加很多的函数;
    • 函数类似于 redux 原来reducer中的一个case语句;
  • extraReducer:添加更多额外reducer处理other action
  • createSlice 返回值是一个对象
    • 对象包含所有的 actions 和 reducer;

image-20240911161617344

store的创建

configureStore用于创建store对象,常见参数如下:

  • reducer,将slice中的reducer可以组成一个对象传入此处;
  • middleware:可以使用参数,传入其他的中间件(自行了解);
  • devTools:是否配置devTools工具,默认为true;

image-20240911161631256

store接入应用

在app.js中将store接入应用:

  • Provider,内容提供者,给所有的子或孙子组件提供store对象;
  • store: 使用useWrappedStore函数导出的store对象;

image-20240911161641373

开始使用store

在函数式组件中可以使用 react-redux 提供的 Hooks API 连接、操作 store。

  • useSelector 允许你使用 selector 函数从 store 中获取数据(root state)。
  • useDispatch 返回 redux store 的 dispatch 引用。你可以使用它来 dispatch actions。
  • useStore 返回一个 store 引用,和 Provider 组件引用完全一致。

image-20240911161655493

image-20240911161705899

Redux Toolkit异步Action操作

在之前的开发中,我们通过redux-thunk中间件让dispatch中可以进行异步操作。

Redux Toolkit默认已经给我们继承了Thunk相关的功能:createAsyncThunk

image-20240911161719968

当createAsyncThunk创建出来的action被dispatch时,会存在三种状态:

  • pending:action被发出,但是还没有最终的结果;
  • fulfilled:获取到最终的结果(有返回值的结果);
  • rejected:执行过程中有错误或者抛出了异常;

我们可以在createSlice的entraReducer中监听这些结果:见右图

image-20240911161729826

项目介绍

网页云音乐-商城

image-20240911161810109

项目需安装的依赖

样式

  • npm i normalize.css --save
  • npm i sass --save
  • npm i classnames --save

Redux And Toolkit

  • npm i next-redux-wrapper --save
  • npm i @reduxjs/toolkit react-redux --save

Axios( 最新的版本发现有bug )

  • npm i axios@1.1.3 --save

AntDesign

  • npm i antd –save
  • npm i -D @types/antd

image-20240911161830333

安装 Ant Design 5

Ant Design 官网:https://ant.design/docs/react/use-in-typescript-cn

Next.js 应用安装Ant Design5

  • 第一步:
    • npm i antd
    • npm i -D @types/antd
  • 第二步:
    • 统一样式风格
  • 第三步:
    • 就可以开始使用了

注意事项:

  • antd 默认支持基于 ES modules 的 tree shaking
  • 直接引入 import { Button } from 'antd' 就会有按需加载的效果

image-20240911161841799

项目打包和部署

项目打包

  • 执行 npm run build (整个项目是部署产物)
  • 执行 npm run start 本地预览效果

使用Node部署

  • 运行:npm run start
  • 指定端口: PORT=9090 npm run start

使用PM2部署(推荐)

  • 项目根目录运行: pm2 start npm --name ”music-mall" -- run start
    • pm2 start npm :在当前目录执行npm
    • --name :指定应用程序的名称
    • -- :后面所有参数会传递给 npm 程序
  • OR: pm2 start “npm run start” –-name music-mall

image-20240911161900788

PM2 常用命令

PM2 常用命令

image-20240911161928579