周口市网站建设_网站建设公司_内容更新_seo优化
2025/12/26 15:51:43 网站建设 项目流程

Next.js 深入解析

一、数据获取与渲染策略

1. getStaticPaths - SSG 动态路径生成

用于生成静态页面的动态路由路径。

// 示例:pages/posts/[id].js
export async function getStaticPaths() {return {paths: [// 1. 基础参数形式 pages/posts/[id].js → posts/1{ params: { id: '1' } },// 2. 嵌套动态路由 pages/[category]/[slug].js → tech/nextjs-guide{ params: { category: 'tech', slug: 'nextjs-guide' } },// 3. 可选catch-all路由 pages/[...slug].js → docs/nextjs/api{ params: { slug: ['docs', 'nextjs', 'api'] } },],// fallback 的三个选项(必选其一)fallback: false,    // 选项1: 只生成指定路径,其他路径返回404fallback: true,     // 选项2: 增量生成,显示加载状态降级方案fallback: 'blocking' // 选项3: 增量生成,阻塞等待生成完成};
}

参数说明

  • 输入参数一般为空,context 可能包含 locales(支持的语言列表)和 defaultLocale(默认语言),但在 Pages Router 中不常用。

2. getStaticProps - SSG 页面数据获取

用于在构建时获取页面所需的数据。

export async function getStaticProps(context) {// context.params 包含动态路由参数const { params } = context;return {props: {// 数据会被注入到页面组件},revalidate: 60, // ISR 关键:60秒后重新生成notFound: false, // 如果为true,返回404页面redirect: {destination: '/',permanent: false, // 临时重定向用307,永久重定向用308}};
}

重要特性

  • propsnotFoundredirect 三选一返回
  • revalidate 是 ISR(增量静态再生)的关键
  • SEO 友好:永久重定向用 308,临时用 307
  • 用户体验:notFound 比显示错误页更干净

参数来源

  • getStaticPaths 返回的动态路由参数
  • 全局注入的参数(国际化、预览模式等)

3. getServerSideProps - SSR 实时数据获取

每次请求时获取最新数据。

export async function getServerSideProps({ req, res, params, query, locale }) {// 参数说明:// req → HTTP 请求对象(包含 cookie、header 等)// res → HTTP 响应对象(可设置 header、cookie 等)// params.id → 来自 URL 路由:/user/123// query → 来自 URL 查询:/user/123?mode=compact// locale → 来自 Accept-Language header 或 URLreturn {props: {// 数据会被注入到页面组件}// 注意:没有 revalidate 参数};
}

二、渲染策略对比

策略 核心代码特征 使用场景
SSG getStaticProps()revalidate 静态内容页
ISR getStaticProps() + revalidate 频繁更新内容
SSR getServerSideProps() 个性化/实时数据
CSR useEffect() / useSWR() 用户交互数据

三、动态导入与代码分割

import dynamic from 'next/dynamic';const DynamicComponent = dynamic(() => import('../components/Hello'),{ssr: true, // 默认值,表示服务端加载loading: () => <p>Loading...</p>}
);

重要特性

  • ssr 参数默认为 true,表示服务端加载
  • 主要作用是代码分割:dynamic 包裹的组件会单独打包,按需加载
  • 与常规 import 不同:常规 import 的组件会被包含在主包中
  • 更像是 CSR 方案:React 先渲染 loading 占位符,JS 包下载完成后重新渲染为真实组件,没有水合过程

四、优化功能

1. Image 优化

  • 自动图片优化(尺寸、格式、懒加载)
  • 支持 WebP 等现代格式
  • 防止布局偏移

2. Font 优化

  • 自动字体优化和预加载
  • 减少布局偏移

3. Script 优化

  • 优化第三方脚本加载
  • 支持 strategy 属性(beforeInteractiveafterInteractivelazyOnload

五、路由系统

1. 页面路由(Pages Router)

  • 基于文件系统的路由
  • 支持动态路由:[id].js[...slug].js
  • 支持嵌套路由

2. 浅路由(Shallow Routing)

const router = useRouter();
router.push('/products?page=2',undefined, { shallow: true }  // 关键参数
);

使用场景:筛选排序、分页、标签页切换等

  • 普通路由跳转:改变 URL → 重新获取数据 → 重新渲染组件
  • 浅路由跳转:改变 URL → 直接更新 URL → 保持当前组件状态

3. API 路由

  • pages/api/ 目录下的文件可作为后端接口
  • 接收 reqres 参数
  • 让 Next.js 成为全栈框架

4. 中间件

  • 旧版本:在 pages/ 目录创建 _middleware.js 文件
  • 新版本推荐:在项目根目录创建 middleware.js 文件

六、App Router(现代方案)

1. 数据获取简化

  • getStaticProps → 直接使用 async 组件函数(默认 SSG,会缓存数据)
  • getStaticPathsgenerateStaticParams
    export async function generateStaticParams() {return [{ id: '1' }, { id: '2' }];
    }
    export const dynamicParams = true; // 相当于 fallback: true
    
  • getServerSideProps → 使用以下方式之一:
    import { unstable_noStore } from 'next/cache';
    export const dynamic = 'force-dynamic'; // 强制动态渲染
    // 或使用 cache: 'no-store'
    // 或使用动态函数(如 cookies(), headers())
    

2. Metadata API

  • 用于更好的 SEO
  • generateMetadata 函数可生成动态元数据

3. ISR 实现

export const revalidate = 60; // 每60秒重新验证
// 或
fetch(url, { next: { revalidate: 60 } });

4. 客户端组件

  • 需要在文件头部显式添加 'use client' 指令
  • 默认部分水合:服务器组件不水合,客户端组件水合

5. 动态导入优化

dynamic(..., { ssr: false }) // 主要用来延迟加载

水合条件

  1. 组件标记为 'use client'(需要交互)
  2. 组件在服务端渲染了 HTML(ssr: true 或默认)

无水合情况

  1. 服务器组件(无 'use client'
  2. 客户端组件但 ssr: false
  3. 纯 CSR 组件(无服务端渲染)

6. 流式渲染

  • App Router 自动支持流式渲染
  • 需要使用 <Suspense> 包裹异步内容
  • 每个 <Suspense> 边界独立流式传输

7. Server Actions

  • 使用 'use server' 声明的函数
  • 底层是网络通信,但封装为类似本地函数调用的体验
  • 简化表单处理,无需创建复杂 API 路由

8. 其他特性

  • 中间件:在项目根目录的 middleware.js 文件中定义,用于身份验证、国际化、重定向等
  • 路由组:用 ( ) 包裹文件夹名,用于组织文件夹结构
  • Cookie/Headers:在服务端组件中通过 cookies()headers() 函数获取请求信息
  • 拦截路由:通过 (.) 前缀实现同级目录拦截,常用于模态框
  • 客户端导航
    • usePathname:获取当前路径(根路径是 "/"
    • useSearchParams:获取查询参数
    • useRouter:切换路由
    • 注意:必须在客户端组件('use client')中使用,且 usePathnameuseSearchParams 会导致动态渲染

七、总结

开发建议

  1. 需要交互的组件:使用 'use client'
  2. 需要延迟加载的组件:使用 dynamic
  3. 需要定期更新的组件:使用 revalidate
  4. 简化数据获取:考虑使用 useSWR 进行状态管理

策略选择

  • 简单静态页面:使用 App Router 的默认 SSG
  • 需要实时数据:使用 dynamic = 'force-dynamic'unstable_noStore()
  • 频繁更新内容:使用 ISR(revalidate
  • 用户交互数据:使用 CSR(useEffect/useSWR

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询