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

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能正常返回数据就可以了。

在这里插入图片描述

相关文章:

  • 【Multipath网络层协议】MPTCP工作原理
  • 【项目管理】基于 C 语言的 QQ 聊天室实现(TCP + 多线程 + SQLite3)
  • Hadoop完全分布式安装配置
  • Rider 安装包 绿色版 Win/Mac/Linux 适合.NET和游戏开发者使用 2025全栈开发终极指南:从零配置到企业级实战
  • 面向对象基础
  • 本地搭建dify结合ollama+deepseek方法详解
  • 2025最新智能优化算法:人工旅鼠算法(Artificial Lemming Algorithm, ALA)求解23个经典函数测试集,MATLAB
  • Spring原理
  • Android 布局系列(四):ConstraintLayout 使用指南
  • 毕业项目推荐:基于yolov8/yolo11的野生菌菇检测识别系统(python+卷积神经网络)
  • fastchat 支持llama3 harmbench PAIR攻击支持 llama3
  • SpringBoot + vue 管理系统
  • 零基础学习OpenGL(一)创建一个窗口
  • JAVA面试_进阶部分_23种设计模式总结
  • PhpStorm 绿色版 安装包 Win/Mac/Linux 商业的PHP集成开发环境 2025全栈开发终极指南:从零配置到企业级实战
  • docker镜像和容器(二)
  • 系统农场商城:打造绿色生态的未来购物新体验
  • mac电脑中使用无线诊断.app查看连接的Wi-Fi带宽
  • 【DeepSeek-R1背后的技术】系列十三:归一化方式介绍(BatchNorm, LayerNorm, Instance Norm 和 GroupNorm)
  • 【R语言】Kmeans算法
  • 【社论】警惕隐形和新型统计造假问题
  • 嘴巴总是发干,喝水也不管用?小心是这几种疾病的警报
  • 保利、北京建工联合体45.45亿元竞得北京海淀区宅地,溢价率11.95%
  • 广西隆林发生一起山洪灾害,致4人遇难
  • 文化破冰,土耳其亚美尼亚合拍摄影大师阿拉·古勒传记片
  • 北方首场高温将进入鼎盛阶段,江南华南多地需警惕降雨叠加致灾