当前位置: 首页 > article >正文

next.js-学习3

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" /> */}
            {/* <Card
              title="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();
 //打开注释封装card
  return (
    <>
      <Card title="Collected" value={totalPaidInvoices} type="collected" />
      <Card title="Pending" value={totalPendingInvoices} type="pending" />
      <Card title="Total Invoices" value={numberOfInvoices} type="invoices" />
      <Card
        title="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.kler.cn/a/566692.html

相关文章:

  • USRP4120-通用软件无线电平台
  • C语言一维数组的全面解析
  • CAN总线通信协议学习1——物理层
  • HarmonyOS 5.0应用开发——多线程Worker和@Sendable的使用方法
  • 版图自动化连接算法开发 00004 ------ 给定一个点,添加一个中间点实现 Manhattan 方式连接两个给定的坐标点
  • I2S音频开发(使用USB音频进行验证)
  • ESP32 S3开发笔记(环境搭建,成功烧录)
  • Windows逆向工程入门之MASM整数存储机制
  • Grok3使用体验与模型版本对比分析
  • Haption:机器人遥操作触觉力反馈技术革新解决方案
  • 工程化与框架系列(10)--微前端架构
  • 量子计算如何优化交通流量:未来智能出行的钥匙
  • 欢乐力扣:存在重复元素二
  • go基础语法
  • Stable Diffusion在中国的生态分析报告
  • Redis如何设置密码
  • SpringCloud/Boot集成LogBack
  • 网络安全有必要学编程吗?
  • 入门基础项目(SpringBoot+Vue)
  • fortify安全扫描Access Control: Database问题解决