react课程26-页面建立及Data处理

Last updated on October 18, 2024 pm

本节课包含项目分析、页面建立(包含加载和错误界面)、渲染方面的处理和cache问题。

一、信息

(1)项目分析

image-20241001192359765

image-20241001192124627

(2)suspense

在 React 中,Suspense 是一个用于管理异步操作(例如组件加载或数据获取)的机制。它允许你在组件渲染之前显示一个 “loading” 状态,直到所需的资源加载完毕。Suspense 主要用于处理动态导入的组件或与 React 的 Concurrent Mode 结合使用。

1
2
3
4
5
const LazyComponent = React.lazy(() => import('./LazyComponent'));

<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>

**React.lazy()**:这是 React 提供的一个方法,用于懒加载组件。它返回一个动态导入的 Promise,直到这个 Promise 解析后,组件才会被渲染。

**Suspense**:Suspense 包裹着懒加载的组件,负责在组件加载过程中显示一个 “占位符”(通常是一个 loading 状态)。一旦组件加载完成,它就会正常渲染。

fallback 属性:这是 Suspense 的关键属性,用来指定加载过程中要显示的内容。在上例中,当 LazyComponent 正在加载时,浏览器会先显示 <div>Loading...</div>,直到组件加载完成。

注意:

只用于客户端渲染:Suspense 目前主要用于客户端渲染,而不是在服务器端渲染(SSR)中。

结合数据加载(实验性):Suspense 的最大潜力是与 Concurrent Mode 结合,控制数据加载过程中的用户体验,但这部分功能还处于实验阶段。

(3)Dynamic Route Segment

我们需要为每个小屋创建一个url,总不能为每个id新建一个文件夹吧。

在 Next.js 中,动态路由段(dynamic route segment)是一种用于创建根据 URL 变化而生成不同页面的路由机制。它允许你在文件系统路由中定义一个动态的部分,这样页面路径可以根据参数动态变化。

特点
  • 文件名决定路由:文件系统会自动基于文件名生成相应的路由。
  • 动态参数:方括号内的内容会被当作动态参数,useRouter() 钩子可以读取这些参数。
  • 嵌套动态路由:你可以在不同层级嵌套动态路由,创建复杂的 URL 结构。
如何使用:

(4)专业术语们

image-20241001210353424

1、Serverless computing

无服务器计算是一种云计算模型,开发人员无需管理服务器,而是专注于编写和部署代码。背后的基础设施由云提供商自动管理,它根据需求动态分配资源并仅在代码运行时计费。尽管名称中包含“serverless”,实际上服务器仍然存在,只是由云提供商负责维护,开发者不必直接接触。

2、ISR:

增量静态再生(Incremental Static Regeneration,简称 ISR)是 Next.js 的一种功能,它允许你在保持静态生成的性能优势的同时,对某些页面进行更新。使用 ISR,可以在不重新构建整个站点的情况下,更新特定页面的内容。这种方式特别适合于内容经常变化但又不需要实时更新的页面,如博客文章、产品列表或新闻网站。

在用户请求某个页面时,如果页面的缓存过期(超过 revalidate 设置的时间),Next.js 会在后台生成一个新的页面副本并将其缓存。用户会立即获得之前缓存的页面,而新的副本会在下一次请求时提供。页面更新后的内容会在下一次用户访问时可见,从而实现内容的增量更新。

二、项目构建起步

app文件夹下创建不想要自动创建路径的文件夹,需要在命名前加”_”。

tailwind.config.js文件夹中找到theme-extend目录,可以在里面添加自定义主题。

npm i @heroicons/react 安装图标库


(1)修建网站布局

1、建立metadata
1
2
3
4
5
6
7
8
9
10
export const metadata = {
// title: 'The Wild Oasis', 最普通的方式
title: {
template: '%s / The Wild Oasis', //“%s”会被替换成其他界面的标题
default: 'Welcome The Wild Oasis ', //没有定义标题的界面,标题是这个
},

description:
'Luxurious cabin hotel,located int the heart of the Italian Dolomites,surrounded by beautiful mountains and dark forests',
};
2、icon

浏览器上方标题旁边的图标,只需要把图片放置在app文件夹根路径中,命名为icon,就设置好了

3、font

Next.js 提供了对自定义字体的强大支持,可以通过 @next/font 动态加载 Google Fonts 或本地字体,不再需要手动从 CDN 引入字体文件。(隐私+性能)

在 CSS 中,antialiased 通常用来处理字体的渲染方式,主要作用是让字体显示得更加清晰和平滑

  • 导入字体函数:import { Josefin_Sans } from 'next/font/google';

  • 进行字体配置:

1
2
3
4
const josefin = Josefin_Sans({
subsets: ['latin'],
display: 'swap',
}); //在字体加载之前,页面会使用系统默认字体,加载后再切换为指定字体,避免空白或闪烁的问题
  • 运用字体设置:className={``${josefin.className}``}
4、图像优化

import Image from 'next/image';


方法一:<Image src="/logo.png" height="60" width="60" alt="The Wild Oasis logo" />(必须指定高度和宽度,否则会报错)

方法二:(静态导入)先导入图像,再直接放置进组件里,接入导入后名字叫logo:

<Image src="logo" quality={10} alt="The Wild Oasis logo" />

(无需设置高度和宽度,quality越高图像质量越高越清晰,大小越大)

fill(填充),placeholder:blur(模糊加载)


  • 自动图像优化

Next.js 会自动根据设备的分辨率、视窗大小和图像的具体需求对图像进行优化。它会生成不同尺寸的图像并根据设备加载合适的版本,这样可以减少不必要的资源浪费和页面加载时间。

  • 延迟加载(Lazy Loading)

默认情况下,next/image 使用延迟加载技术(lazy loading),只有当图像滚动到视口中时才会进行加载。这可以减少首屏加载时间,提高用户体验。

  • 响应式图像处理

next/image 支持自动生成不同尺寸的响应式图像。当你指定图像宽度和高度时,Next.js 会为不同的屏幕大小和分辨率生成合适的图像版本,确保图像在各种设备上都能高效加载。

  • 现代图像格式支持

Next.js 会自动为支持的浏览器提供现代化的图像格式(如 WebP)。WebP 图像格式比传统的 JPEG 和 PNG 更加高效,能大幅减少图像的文件大小,提高加载速度。

  • 图像裁剪和调整

Next.js 允许对图像进行动态裁剪、缩放和调整大小。例如,你可以为不同的屏幕设置不同的宽度和高度,Next.js 会自动处理这些操作。

  • 图像缓存

Next.js 的图像优化功能支持缓存优化后的图像。优化后的图像会被存储在服务器或 CDN 中,确保在后续的页面加载中更快地提供这些图像,从而减少对服务器的请求负担。

  • 兼容性处理

Next.js 会根据用户的浏览器特性自动加载最合适的图像格式,并提供最佳的显示效果。例如,对于支持 WebP 的浏览器,Next.js 会提供 WebP 格式图像,而对于不支持的浏览器,会提供 JPEG 或 PNG 格式。

  • 减少带宽和流量消耗

通过加载更小、优化后的图像,Next.js 帮助大幅减少带宽消耗,尤其在移动端网络速度较慢的情况下,这对提高用户体验有很大帮助。

5、如何使Image非静态导入图像动态大小
1
2
3
4
5
6
7
8
<div className="relative aspect-square col-span-2">
<Image
src="@/public/about"
fill
className="object-cover"
alt="Family that manages The Wild Oasis"
/>
</div>
  • 指定父类容器

relative:这表示父容器采用了相对定位(position: relative),这是 next/image 中使用 layout="fill" 时的必需条件。这样图像才能根据父容器的大小进行定位和调整。

aspect-square:这通常是一个 Tailwind CSS 的类,表示容器的宽高比为1:1,也就是一个正方形。通过这个类,父容器将被强制保持宽度与高度相等。

col-span-2:这是典型的网格布局类,表示这个 div 占据了网格中的 2 列宽度。这通常用于 grid 布局中来控制元素的宽度。

  • 设置图像格式

layout="fill":这是 next/image 组件的一个属性,表示图像将填充整个父容器的空间。由于父容器已经通过 relative 定位并设置了宽高比(正方形),图像将按照父容器的大小动态调整。无需指定图像的宽度和高度,Next.js 会自动计算和优化。

className="object-cover":这是一个 CSS 类,通常与 Tailwind CSS 一起使用。object-cover 的作用是让图像保持其原始比例并填满整个容器。如果图像的比例和容器不匹配,它将裁剪图像的一部分,而不是拉伸或压缩图像,从而保持图像的完整性。

6、嵌套layout

我们在app文件夹下放至了layout,但是在文件夹下的account路径下也需要layout布局,那么可以直接在此文件夹中创建layout.js,放置相应的navigation组件即可。

(2)连接supabse

1、根目录下新建.env.local文件夹

这个文件夹负责放置supabase的URL和KEY。

服务器端变量:例如数据库连接信息、API 密钥等敏感信息放在 .env.local 中,并且不加 NEXT_PUBLIC_ 前缀。

客户端变量:如果你需要某些环境变量在浏览器中使用(如公共 API 的 URL),可以加上 NEXT_PUBLIC_ 前缀。

URL还是正常的URL,而KEY不用settings->API->Project API keys->(anon public)的key,而是(service_role)中的KEY。(为了绕过RLP)

⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️无语了我亲爱的环境变量配置⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️

SUPABASE_URL=https://mmyxdnpmmlqmyjxjypmw.supabase.co

SUPABASE_KEY=service_role

🚫不能有空格、🚫没有引号、🚫后面不能加分号。。。🚫字母大小写别写错

我说怎么一直连接不上。。。GPT你真的有毛病一开始不跟我说问了一个小时了才说。。。

2、lib文件夹下建立supabase.js
1
2
3
4
5
6
7
8
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_KEY
);

export default supabase;

三、Data处理

现在获取data变得非常方便,仅仅是把RSC设置成async方程,然后直接: const cabins = await getCabins();类似这样就可以了。

(1)准备工作

1、允许加载远程图像

我们在调取cabins的数据的时候,会加载supabase上的cabin图像,因此在 Next.js 中配置 remotePatterns 的目的是为了允许应用加载来自特定远程服务器的图像。通过指定 protocolhostnameportpathname,可以控制哪些外部图像源被允许在的应用中使用。

1
2
3
4
5
6
7
8
9
10
11
12
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'mmyxdnpmmlqmyjxjypmw.supabase.co',
port: '',
pathname: '/storage/v1/object/public/cabin-images/**',
},
],//没有指定端口,表示使用默认端口443
},//**表示任何以前面开头的路径都可以被加载
};
2、利用suspense使旋转器只放置在需要加载的组件

suspense只能包裹一个组件来使用

在加载cabins界面的时候,如果正在加载cabins数据,整个界面都会被Spinner组件遮挡,包括一部分静态文字,这样会导致bad UX。所以我们可以把获取cabins和渲染cabins的部分提取到一个组件中,然后导入到cabins界面,用suspense包裹住,就🆗了。这里suspense的fallback组件会覆盖cabins界面本身设置的loading组件。

3、Cabin 组件

在Cabins界面时,每个cabin有一个按钮,点击进入详细界面,url设置为cabin/${id}

我们在cabins文件夹下建立[cabinId]动态文件夹。里面建立page.js就是相应的cabin界面。

让Page组件接收{params}作为参数, const cabin = await getCabin(params.cabinId);就可以获得cabin数据。

4、动态metadata

我们想要给cabin界面也设置浏览器标题,同时标题中含有cabin id,于是可以使用函数来动态创建。

1
2
3
4
export async function generateMetadata({ params }) {
const { name } = await getCabin(params.cabinId);
return { title: `Cabin ${name}` };
}
5、设置Error Bundaries

与之前的错误边界处理方式不同,在这里我们只需要在app的根目录下创建一个文件夹:error.js,然后返回一个组件,接收error、reset函数。于是就可以在界面上显示error.message,并且设置按钮,click函数为reset。

image-20241001203443894

⚠️需要声明“use client”

6、not-found error

在app的根目录下创建一个文件夹:not-found.js,填写相应内容即可,当用户访问不存在的URL的时候就会进入这个界面。

但是我们想要在用户试图访问不存在的id的cabin界面时也进入这个错误界面(默认是显示上面的error界面),于是我们可以找到service文件中的getCabin函数,在error下,调用notFound();

我们还想要动态定义cabin下not-found界面的信息,于是可以在[cabinId]文件夹下也创建一个not-found文件夹,写入想要的信息即可。

image-20241001204330663

(2)Data Rendering的两种方式

npm run build 打包后可以在最下方看到哪些文件是静态渲染,哪些是动态

此处[cabinId]界面是动态渲染,因为nextjs并不知道究竟有多少id


image-20241001210123404 image-20241001210232473

(3)Dynamic->Static

1、如何让next.js知道动态URL段的所有可能值

由于静态界面性能好、更安全等特性,我们想要把动态界面也渲染成静态界面。cabins是有限长度,也很好传递各个id。

1
2
3
4
5
6
export async function generateStaticParams() {
const cabins = await getCabins();
const ids = cabins.map((cabin) => ({ cabinId: String(cabin.id) }));

return ids;
}

generateStaticParams 是 Next.js 中用于 静态生成动态路由参数 的函数。该函数主要用于在构建时生成页面的路径参数,使得这些路径能够在静态站点生成时创建对应的静态页面。其返回的数组会被 Next.js 用来生成静态页面。对于每个 cabinId,Next.js 会生成对应的静态页面。

2、SSG

SSG(Static Site Generation)Next.js 中的一种渲染方法,允许在构建时生成页面的 HTML,而不是在每次用户请求时动态生成。这种方法可以显著提高页面的加载速度和性能,因为静态页面可以通过 CDN 缓存并在全球范围内快速提供给用户。

由于上面的操作,使得整个APP都是静态渲染,于是可以在next.config.js文件中配置: output:”export“,然后运行npm run build,会生成一个out包。使用vscdode打开整个包,下载以下插件之后,会在编译器右下角看到go Live,点击后会生成静态界面。

image-20241001213503801image-20241001213600236

但是界面中使用Image组件的所有图片都无法被渲染了。因为**next/image 依赖服务端功能**,Image 组件依赖 Next.js 的内置图像优化功能,这在静态导出时并不可用。默认情况下,next export 不支持自动优化图像。

解决问题可以使用Cloudinary图像优化:搜索next.js static export 找到Image Optimization部分,里面有较为详细的配置信息。

3、Patial Pre-Rendering (PPR)

image-20241001214756971

四、Caching in Next.js

(1)概念

image-20241001235341827

image-20241018162754853

image-20241001235407728

1、相同的url和options

2、可以是不同user

no-store 是一种缓存控制指令,指示浏览器和任何中间缓存(如代理服务器)都不应缓存响应。每次请求时,客户端都会向服务器请求新鲜的数据,而不是使用任何先前的缓存内容。unstable_noStore 是 Next.js 中的一个实验性特性,旨在为某些请求提供更细粒度的缓存控制。它允许你在服务器端返回响应时,指定某些内容不应被缓存。这与普通的 noStore 方法类似,但由于它是实验性特性,因此可能在未来的版本中发生变化或被替换。

避免缓存:当你希望确保某些 API 响应或页面请求不被缓存时,可以使用 unstable_noStore。这对于处理动态内容、实时数据或敏感信息尤为重要。

开发和调试:在开发期间,使用 unstable_noStore 可以确保你始终获得最新的数据或页面渲染,避免缓存引起的混淆。

API 请求:在发送 API 请求时,如果你希望强制获取新数据而不是从缓存中读取,可以在请求配置中使用 unstable_noStore

(2)模拟生产环境的caching 和ISR

在package.json 中加入”prod”: “next build && next start” 然后终端输入npm run prod就可以模拟生产环境了。

⚠ For production Image Optimization with Next.js, the optional ‘sharp’ package is strongly recommended. Run ‘npm i sharp’, and Next.js will use it automatically for Image Optimization.(终端的警告)

1、关闭data cache

如果这时候在数据库修改某个值,是不会在网页上显示的,就算刷新也不行,因为这是一个完全静态的界面,所以我们想要关掉data cache(同时也能关掉full route cache)

在cabins的page代码中设置:export const revalidate = 0;(每次修改都需要重新run)

2、ISR

只需要修改上面的值为我们想要自动刷新的间隔就可。注意时间的单位是秒。

3、noStore

import { unstable_noStore } from 'next/cache';


react课程26-页面建立及Data处理
http://example.com/2024/10/01/react课程26-页面建立及Data处理/
Author
Yaodeer
Posted on
October 1, 2024
Licensed under