next.js-学习3

embedded/2025/3/1 2:54:41/

next.js-学习3

    • 6. 设置数据库
      • 1. 传代码到github https://github.com/
      • 2. github和Vercel链接,用Vercel预览和部署
      • 3. 创建数据库
      • 4. 初始化数据库
    • 7.读取数据
      • 1. 在/app/lib/data.ts中这两行是连接postgres的
      • 2. 在/app/dashboard/page.tsx中使用
      • 3.在/app/dashboard/page.tsx中使用
      • 4. /app/dashboard/page.tsx中使用
      • 5. card组件使用
    • 8.静态和动态渲染
    • 9.串流 解决加载缓慢导致白屏的问题
    • 10.部分预渲染 **Partial Prerendering (PPR)**

6. 设置数据库

1. 传代码到github https://github.com/

git init
git add README.md
git commit -m "first commit"
git branch -M main
//更改现有的远程仓库 URL,会让你输入密码
git remote set-url origin https://github.com/hexiaoming123/nextjs-dashboard.git
git push -u origin main

2. github和Vercel链接,用Vercel预览和部署

  1. https://vercel.com/signup
  2. 自己的推到next.js的项目,Settings->Project Settings->Framework Preset记得选Next.js,点击deploy部署
  3. 在这里插入图片描述

3. 创建数据库

  1. Storage中选postgres(好吧没了)请选https://vercel.com/marketplace/neon点击Install
  2. 在这里插入图片描述

4. 初始化数据库

  1. 点击Show secretCopy Snippet

  2. 把生成的.env.local内容写到本地的.env中,在.gitignore添加忽略.env

  3. 在这里插入图片描述

  4. pnpm run dev运行项目后请求http://localhost:3000/seed,这里会执行placeholder-data.ts,页面返回Database seeded successfully表示成功,我是失败了,因为没这个模块,无法安装,替代方式:

  5. 安装bcryptjs

    pnpm add bcryptjs
    
  6. app/seed/route.ts下修改

    import bcrypt from 'bcryptjs';
    

    如果访问http://localhost:3000/seed成功了,就删除这个文件避免下次再初始化数据。

  7. 取消app/query/route.ts中注释,删除

      return Response.json({message:'Uncomment this file and remove this line. You can delete this file when you are finished.',});
    

    ,访问:http://localhost:3000/query这个验证是否能查询出数据

  8. 在这里插入图片描述

  9. 关联上项目,不然提交github代码后构建会失败在这里插入图片描述

7.读取数据

1. 在/app/lib/data.ts中这两行是连接postgres的

  1. import postgres from 'postgres';const sql = postgres(process.env.POSTGRES_URL!, { ssl: 'require' });// ...
    

2. 在/app/dashboard/page.tsx中使用

  1. import { Card } from '@/app/ui/dashboard/cards';
    import RevenueChart from '@/app/ui/dashboard/revenue-chart';
    import LatestInvoices from '@/app/ui/dashboard/latest-invoices';
    import { lusitana } from '@/app/ui/fonts';export default async function Page() {return (<main><h1 className={`${lusitana.className} mb-4 text-xl md:text-2xl`}>Dashboard</h1><div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">{/* <Card title="Collected" value={totalPaidInvoices} type="collected" /> */}{/* <Card title="Pending" value={totalPendingInvoices} type="pending" /> */}{/* <Card title="Total Invoices" value={numberOfInvoices} type="invoices" /> */}{/* <Cardtitle="Total Customers"value={numberOfCustomers}type="customers"/> */}</div><div className="mt-6 grid grid-cols-1 gap-6 md:grid-cols-4 lg:grid-cols-8">{/* <RevenueChart revenue={revenue}  /> */}{/* <LatestInvoices latestInvoices={latestInvoices} /> */}</div></main>);
    }
    

3.在/app/dashboard/page.tsx中使用

import { fetchRevenue } from '@/app/lib/data';export default async function Page() {const revenue = await fetchRevenue();// ...
}

取消注释,取消/app/ui/dashboard/revenue-chart.tsx中注释,页面显示出了柱状图

4. /app/dashboard/page.tsx中使用

  1. import { fetchRevenue, fetchLatestInvoices } from '@/app/lib/data';const latestInvoices = await fetchLatestInvoices();//在revenue下边加上
    
  2. 取消注释,取消/app/ui/dashboard/latest-invoices注释,显示出了Latest Invoices最新的5条消息

5. card组件使用

  1. /app/dashboard/page.tsx中

    import {fetchRevenue,fetchLatestInvoices,fetchCardData,
    } from '@/app/lib/data';//latestInvoices下边加上const {numberOfInvoices,numberOfCustomers,totalPaidInvoices,totalPendingInvoices,} = await fetchCardData();
    

    await Promise.all 可以同时加载多个接口

8.静态和动态渲染

​ 静态渲染是页面不会随数据改变而改变,动态渲染是随着数据改变而改变。

  1. 例如/app/lib/data.ts中打开fetchRevenue函数注释,模拟:一个接口加入个3s的耗时,另一个接口也跟着受了影响

    export async function fetchRevenue() {try {// We artificially delay a response for demo purposes.// Don't do this in production :)console.log('Fetching revenue data...');await new Promise((resolve) => setTimeout(resolve, 3000));const data = await sql<Revenue[]>`SELECT * FROM revenue`;console.log('Data fetch completed after 3 seconds.');return data;} catch (error) {console.error('Database Error:', error);throw new Error('Failed to fetch revenue data.');}
    }
    

    点击home的时候页面会等3s的空白才能出来概览页

9.串流 解决加载缓慢导致白屏的问题

创建/app/dashboard/loading.tsx文件

export default function Loading() {return <div>Loading...</div>;
}

加载的时候右侧空白会变为Loading…,成功后右侧显示页面

在这里插入图片描述

/app/dashboard/loading.tsx加载骨架

import DashboardSkeleton from '@/app/ui/skeletons';export default function Loading() {return <DashboardSkeleton />;
}

在这里插入图片描述

在/app/dashboard下创建overview文件夹,移动/app/dashboard下的loading.tsx和page.tsx,这样以后访问概念就不会影响其他页面了,http://localhost:3000/dashboard/overview

开始优化加载页面,/dashboard/overview/page.tsx中,

import { fetchLatestInvoices, fetchCardData } from '@/app/lib/data'; // 删除 fetchRevenue
const revenue = await fetchRevenue() // 删除这行

使用Suspense 和RevenueChartSkeleton

import { Suspense } from 'react';
import { RevenueChartSkeleton } from '@/app/ui/skeletons';

包裹

<Suspense fallback={<RevenueChartSkeleton />}><RevenueChart /></Suspense>

修改/app/ui/dashboard/revenue-chart.tsx文件

import { fetchRevenue } from '@/app/lib/data';//添加
import { Revenue } from '@/app/lib/definitions'; //移除
export default async function RevenueChart() { // 组件异步,移除参数const revenue = await fetchRevenue(); // 在组件内部获取数据

这样再访问http://localhost:3000/dashboard/overview会很快加载出来

/dashboard/overview/page.tsx中,

import { fetchCardData } from '@/app/lib/data'; // 删除 fetchLatestInvoices
//更新
import {RevenueChartSkeleton,LatestInvoicesSkeleton,
} from '@/app/ui/skeletons';
// 删除 const latestInvoices = await fetchLatestInvoices()
//更新<LatestInvoices />不要怕报错,下个组件会删除参数就不报错了
<Suspense fallback={<RevenueChartSkeleton />}><RevenueChart /></Suspense><Suspense fallback={<LatestInvoicesSkeleton />}><LatestInvoices /></Suspense>

/app/ui/dashboard/latest-invoices.tsx中

import { LatestInvoice } from '@/app/lib/definitions';//删除
import { fetchLatestInvoices } from '@/app/lib/data';//添加
export default async function LatestInvoices() {//删除了参数const latestInvoices = await fetchLatestInvoices();//在组件中直接获取数据

/app/dashboard/overview/page.tsx中,避免表头的cards不一起刷新,提到一个公共组件

import CardWrapper from '@/app/ui/dashboard/cards';//导入组件
import { Card } from '@/app/ui/dashboard/cards';//删除组件
//导入 CardsSkeleton组件
import {RevenueChartSkeleton,LatestInvoicesSkeleton,CardsSkeleton,
} from '@/app/ui/skeletons';
//使用CardWrapper组件<Suspense fallback={<CardsSkeleton />}><CardWrapper /></Suspense>//删除<Card组件

/app/ui/dashboard/cards.tsx中

import { fetchCardData } from '@/app/lib/data';//导入fetchCardData
export default async function CardWrapper() {
//使用fetchCardData函数const {numberOfInvoices,numberOfCustomers,totalPaidInvoices,totalPendingInvoices,} = await fetchCardData();//打开注释封装cardreturn (<><Card title="Collected" value={totalPaidInvoices} type="collected" /><Card title="Pending" value={totalPendingInvoices} type="pending" /><Card title="Total Invoices" value={numberOfInvoices} type="invoices" /><Cardtitle="Total Customers"value={numberOfCustomers}type="customers"/></>);
}

10.部分预渲染 Partial Prerendering (PPR)

  1. PPR 只在 Next.js canary 可用 (next@canary),Next.js 14开始引入的这个特性

    pnpm install next@canary
    
  2. 对于今天构建的大多数web应用程序,你要么为整个应用程序选择静态和动态渲染,要么选择特定的路由。在Next.js中,如果你在路由中调用一个动态函数(比如查询数据库),整个路由就会变成动态的

  3. 然而,大多数路由并不是完全静态或动态的。例如,考虑一个电子商务网站。您可能希望静态地呈现大部分产品信息页面,但也可能希望动态地获取用户的购物车和推荐产品,这允许您向用户显示个性化的内容

  4. 组件不依赖于数据,也不是针对用户个性化的,所以它可以是静态的。

    中的组件依赖于经常更改的数据,并且将针对用户进行个性化处理,因此它们可以是动态的。

  5. 在这里插入图片描述

  6. js 14引入了部分预渲染的实验版本——一个新的渲染模型,它允许你在同一条路径上结合静态和动态渲染的优点。例如:在这里插入图片描述

  7. 当用户访问路由时:

    提供一个静态路由shell,其中包括导航栏和产品信息,确保快速初始加载。

    外壳留下了一些洞,其中动态内容(如购物车和推荐产品)将异步加载。

    异步孔是并行流,减少了页面的总体加载时间

  8. next.config.ts中加入PPR选项,为Next.js应用启用PPR

     /* config options here */experimental: {ppr: 'incremental',},
    

    /app/dashboard/layout.tsx中加入

    export const experimental_ppr = true;
    

    这样在加载的时候会自动去部分预渲染,以后在生产中可能会很受欢迎,目前先稳稳别在生产用。

    推送到github上去项目访问:https://nextjs-dashboard-git-main-hes-projects-5f35bd0a.vercel.app/dashboard/overview能正常返回数据就可以了。

在这里插入图片描述


http://www.ppmy.cn/embedded/168946.html

相关文章

判断奇数偶数

题目描述 给定一个整数&#xff0c;判断该数是奇数还是偶数。如果 n是奇数&#xff0c;输出 odd&#xff1b;如果 n是偶数&#xff0c;输出 even。 输入格式 输入仅一行&#xff0c;一个整数 n&#xff0c;−100≤n≤100。 输出格式 输出仅一行&#xff0c;如果 n 是奇数&…

【Kubernetes】API server 限流 之 maxinflight.go

这个文件实现了一个基于信号量(Channel)的简单限流器。 基础知识 总共有四种channel 带缓冲的channel nonMutatingChan、mutatingChan 都是带缓冲的channel &#xff0c;这类channel 的特点是&#xff1a; 这允许最多 mutatingLimit /nonMutatingLimit 个请求同时获取令牌并执…

redis存取list集合

一 、存取为list类型 RestController RequestMapping(“/test”) Slf4j publicclassTestController Autowired private RedisTemplate redisTemplate; ApiOperation(“redis-savelist”) PostMapping(“/redis/save/list”) public void redisSaveList() { Listlist …

【软考-架构】1.1、计算机硬件-CPU校验码

计算机硬件组成 中央处理单元 运算器 算术逻辑单元ALU&#xff08;实现对数据的算术和逻辑运算&#xff09;;累加寄存器AC&#xff08;运算结果或源操作数的存放区&#xff09;;数数据缓冲寄存器DR&#xff08;暂时存放内存的指令或数据&#xff09;;状态条件寄存器PSW&#x…

STM32--SPI通信讲解

前言 嘿&#xff0c;小伙伴们&#xff01;今天咱们来聊聊STM32的SPI通信。SPI&#xff08;Serial Peripheral Interface&#xff09;是一种超常用的串行通信协议&#xff0c;特别适合微控制器和各种外设&#xff08;比如传感器、存储器、显示屏&#xff09;之间的通信。如果你…

DeepSeek模型昇腾部署优秀实践

2024年12月26日&#xff0c;DeepSeek-V3横空出世&#xff0c;以其卓越性能备受瞩目。该模型发布即支持昇腾&#xff0c;用户可在昇腾硬件和MindIE推理引擎上实现高效推理&#xff0c;但在实际操作中&#xff0c;部署流程与常见问题困扰着不少开发者。本文将为你详细阐述昇腾 De…

React表单状态管理深度解析:Form.useWatch与onChange技术选型指南

React表单状态管理深度解析&#xff1a;Form.useWatch与onChange技术选型指南 一、核心机制对比 1.1 底层原理图解 #mermaid-svg-YteLGfOvYI1ayxbC {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-YteLGfOvYI1ayxb…

ubuntu:桌面版磁盘合并扩容

下载gparted磁盘编辑器 apt-get install gparted 打开gparted 更改目标分区大小 当遇到这个报错时&#xff0c;需要在命令行执行原分区的挂载指令 查看该分区信息 记住该目录&#xff0c;并在命令行执行 mount -o remount -rw /# 示例&#xff1a;mount -o remount -rw /v…