欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > Next.js【实用教程】2025最新版

Next.js【实用教程】2025最新版

2025/4/25 16:58:59 来源:https://blog.csdn.net/weixin_41192489/article/details/145588332  浏览:    关键词:Next.js【实用教程】2025最新版

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

Next.js 简介

Next.js 由 Vercel 开发和维护,旨在解决单页应用(SPA)和多页应用(MPA)在性能和 SEO 上的不足。

核心特性

  • 服务端渲染(SSR)-- 在服务器端预渲染页面,将 HTML 直接发送到客户端,从而提高了页面加载速度和 SEO 效果。
  • 静态生成(SSG)-- 在构建时生成 HTML 的方式,使得每个页面的内容都能在构建时生成并缓存,这样无需在每次请求时生成 HTML,从而显著提升页面性能。
  • 通过文件系统的结构快速创建页面路由。同时,API 路由功能使开发者能够直接在 Next.js 项目中创建后端 API
  • 增量静态再生成(ISR)-- 将部分页面静态化,并在内容更新时触发重新生成,以确保页面内容的新鲜度和快速访问。
  • 内置图像优化功能,可通过 <Image /> 组件自动进行图像懒加载、响应式优化和格式转换,有效减少加载时间并提升页面性能。
  • 对 CSS 模块、Sass 和 styled-jsx 原生支持,支持 Tailwind CSS 和其他流行的 CSS 框架

适用场景

  • 内容驱动的网站:如博客、新闻网站等,Next.js 的 SSG 和 ISR 特性使其在内容频繁更新时,能够保持高效的性能和良好的 SEO 表现。
  • 电商平台:对于电商网站,Next.js 的 SSR 和 ISR 能够确保页面快速响应,满足用户体验的需求,同时也便于动态加载产品信息。
  • Web应用:复杂的企业级应用或 SaaS 应用可以利用 Next.js 提供的 SSR、动态路由和 API 路由实现高性能的全栈架构。
  • 个人网站和组合展示:对于个人博客和作品展示,Next.js 提供了静态生成和图像优化功能,能够确保简洁高效的页面展示。

搭建开发环境,创建项目

  • 安装 Node.js
  • 创建项目
npx create-next-app@latest

在这里插入图片描述
在这里插入图片描述

会自动安装依赖

  • 用 vscode 打开项目,并启动
    在这里插入图片描述
    浏览器访问 http://localhost:3000/ 效果如下

在这里插入图片描述

项目目录

  • src\app\page.tsx 项目首页
  • src\app\layout.tsx 页面布局
  • public 静态资源,例如图像、字体等

页面路由

会根据 src\app 内的文件自动创建,具体对应关系范例如下:

路由文件路径
/src\app\page.tsx
/blogsrc\app\blog\page.tsx
/blog/动态参数src\app\blog\[slug]\page.tsx
  • 所有页面路由都对应一个 page.tsx
  • 含动态参数的路由,对应 [slug] 文件夹下的 page.tsx

页面中获取路由动态参数的方法如下

export default async function Page({params,
}: {params: Promise<{ slug: string }>;
}) {const { slug } = await params;return (<><h1>{slug} 篇博客的标题</h1><p>{slug} 篇博客的内容</p></>);
}
  • 页面函数组件的参数为 { params,}
  • 函数参数的类型为 { params: Promise<{ slug: string }>;},可见参数 params 是一个 Promise
  • 需用 await 同步获取到 params ,并解构出其中的 slug
  • 解构出的 slug 值即路由上的动态参数,以 /blog/1 为例,slug 的值为 1

路由跳转

Link

内置的 Link 组件,点击可实现路由跳转

import Link from "next/link";
 <Link href="/blog">板块--博客</Link>

页面布局

每个文件夹下的 layout.tsx 文件,即该文件夹对应路由的页面布局

布局布局文件路径
全局布局src\app\layout.tsx
/blog 的布局src\app\blog\layout.tsx

以 blog 板块的布局为例,src\app\blog\layout.tsx 的内容为

export default function BlogLayout({children,
}: {children: React.ReactNode;
}) {return (<><header>页头-博客板块</header><section>{children}</section></>);
}
  • BlogLayout 为任意自定义的布局函数名称
  • 函数的参数为 {children:children} , 简写为 {children}
  • 函数参数的类型为 {children:React.ReactNode}
  • 函数的返回内容需含有 {children} ,其他内容可任意自定义

后端服务

Next.js 不仅能构建前端页面,还同时提供了后端服务

src\app\api 内的 route.js 会自动生成后端接口

范例:src\app\api\blog\route.js

import { NextResponse } from "next/server";// 处理 GET 请求
export async function GET(request) {// 这里可以编写从数据库或其他数据源获取用户数据的逻辑const data = [{id: 1,title: "第1篇博客的标题",content: "第1篇博客的内容",},{id: 2,title: "第2篇博客的标题",content: "第2篇博客的内容",},];return NextResponse.json(data);
}

启动项目后,浏览器访问 http://localhost:3000/api/blog ,效果如下:

在这里插入图片描述

内置组件

图片 Image

Next.js 内置的 next/image 图像优化组件,通过以下功能提升图像性能:

  • 图片格式统一转换为 WebP,并根据设备尺寸自动调整分辨率
  • 避免了图片加载过程中的布局偏移(Layout Shift)
  • 默认情况下,图像在进入视窗时才加载,可选择使用模糊占位符。
  • 通过设置尺寸属性,图像可以根据屏幕大小自适应。

图片存于目录 public\images 中

在这里插入图片描述

import Image from "next/image";

本地图片

      <Imagesrc="/images/风景.png"alt="图片-风景"width={600}height={400}// 开启响应式 -- 根据宽高比调整图像尺寸,确保在不同设备上始终显示最佳比例。layout="responsive" // 禁用懒加载 -- 可提高页面加载图片的优先级priority// 图片加载时的占位图blurDataURL="/images/img_loading.png"/>

远程图片

需先在 next.config.ts 中配置图片域名

import type { NextConfig } from "next";const nextConfig: NextConfig = {// 配置图片域名images: {remotePatterns: [{hostname: "se2.360simg.com",},],},
};export default nextConfig;

再在页面中使用

      <Imagesrc="https://se2.360simg.com/t01d8935450f8ea8ffb.png"alt="图片-远程"width={600}height={400}priority // 提高页面加载时的优先级blurDataURL="/images/img_loading.png"/>

响应式图片 sizes

<Imagefillsrc="/example.png"sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"/>

图片加载占位符 blurDataURL

  • 需同时设置 placeholder="blur"
  • blurDataURL 的值为 base64的图片(建议用极小的)
import Image from "next/image";const fs = require("fs");const imagePath = "./public/images/img_loading.png";
const imageBuffer = fs.readFileSync(imagePath);
const base64Image = imageBuffer.toString("base64");
const blurDataURL = `data:image/jpeg;base64,${base64Image}`;export default function Page() {return (<><Imagesrc="https://se2.360simg.com/t01d8935450f8ea8ffb.png"width={600}height={400}placeholder="blur"// 图片加载时的占位图blurDataURL={blurDataURL}/></>);
}

在这里插入图片描述

字体

“next/font” 模块对字体进行了优化:

  • 避免网络请求,提高了隐私性和性能
  • 自托管的网页字体不会有布局偏移

传统的 Web 字体加载方式:网络请求字体文件,在字体加载完成前,页面显示为空白或默认字体,加载完成后,页面的字体突然改变,可能引发布局偏移

Google 字体 【默认】

在创建项目时,便自动采用了 Google 字体 ,见 src\app\layout.tsx

import { Geist, Geist_Mono } from "next/font/google";
const geistSans = Geist({variable: "--font-geist-sans",subsets: ["latin"],
});const geistMono = Geist_Mono({variable: "--font-geist-mono",subsets: ["latin"],
});
      <bodyclassName={`${geistSans.variable} ${geistMono.variable} antialiased`}>

本地字体

  1. 将本地字体文件放入 src\app 中,如 src\app\昆明海鸥体.ttf

    百度云盘下载链接: https://pan.baidu.com/s/1rLFdlFoD5oTVNMUM6e4pOA?pwd=4526

  2. 将 src\app\layout.tsx 修改为

    import type { Metadata } from "next";import "./globals.css";// 引入本地字体处理函数 localFont
    import localFont from "next/font/local";// localFont函数将本地字体文件转换为字体类名
    const myFont = localFont({src: "./昆明海鸥体.ttf",
    });export const metadata: Metadata = {title: "Create Next App",description: "Generated by create next app",
    };export default function RootLayout({children,
    }: Readonly<{children: React.ReactNode;
    }>) {return (<html lang="en">// body 上添加字体类名<body className={myFont.className}>{children}</body></html>);
    }
    

效果如下:

在这里插入图片描述

实战范例

在这里插入图片描述

src\app\page.tsx

import Link from "next/link";export default function Page() {return (<><h1>首页</h1><div><Link href="/blog">板块--博客</Link></div><div><Link href="/note">板块--笔记</Link></div></>);
}

src\app\layout.tsx

import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";const geistSans = Geist({variable: "--font-geist-sans",subsets: ["latin"],
});const geistMono = Geist_Mono({variable: "--font-geist-mono",subsets: ["latin"],
});export const metadata: Metadata = {title: "Create Next App",description: "Generated by create next app",
};export default function RootLayout({children,
}: Readonly<{children: React.ReactNode;
}>) {return (<html lang="en"><bodyclassName={`${geistSans.variable} ${geistMono.variable} antialiased`}><header>页头--全局</header>{children}</body></html>);
}

src\app\blog\page.tsx

在这里插入图片描述

import Link from "next/link";interface blog {id: number;title: string;content: string;
}
export default async function Page() {const data = await fetch("http://localhost:3000/api/blog");const blogList = await data.json();return (<><h1>博客列表</h1><ul>{blogList.map((blog: blog) => (<li key={blog.id}><Link href={`/blog/${blog.id}`}>{blog.title}</Link></li>))}</ul></>);
}

src\app\blog\layout.tsx

export default function BlogLayout({children,
}: {children: React.ReactNode;
}) {return (<><header>页头-博客板块</header><section>{children}</section></>);
}

src\app\blog[slug]\page.tsx

在这里插入图片描述

export default async function Page({params,
}: {params: Promise<{ slug: string }>;
}) {const { slug } = await params;return (<><h1>{slug} 篇博客的标题</h1><p>{slug} 篇博客的内容</p></>);
}

src\app\api\blog\route.js

import { NextResponse } from "next/server";// 处理 GET 请求
export async function GET(request) {// 这里可以编写从数据库或其他数据源获取用户数据的逻辑const data = [{id: 1,title: "第1篇博客的标题",content: "第1篇博客的内容",},{id: 2,title: "第2篇博客的标题",content: "第2篇博客的内容",},];return NextResponse.json(data);
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词