Next.js 13 App Router实战踩坑与性能优化指南

去年年底,我接了一个海外客户的项目,要求使用 Next.js 13 的 App Router 开发一个数据分析平台。说实话,当时虽然对 Next.js 已经很熟悉了,但对 App Router 这个相对较新的特性还是有些忐忑。现在项目已经成功上线,我想和大家分享一下在这个过程中的实战经验和踩坑记录。

为什么选择 App Router?

最开始和客户沟通技术选型时,我其实在犹豫要不要用 App Router。毕竟 Pages Router 已经用了很多年,相当稳定。但仔细评估后,还是决定采用 App Router,主要考虑了这几个方面:

首先,App Router 采用的 React Server Components 架构能带来更好的性能。在我们的数据分析平台中,有大量的数据展示组件,如果全部在客户端渲染,不仅初始加载慢,而且会占用大量客户端资源。使用 Server Components,我们可以在服务器端完成大部分渲染工作,只将必要的交互部分放在客户端。

其次,App Router 的并行路由和拦截路由特性,完美解决了我们的一些交互需求。比如数据分析平台需要在查看数据列表时,点击某条数据在右侧弹出详情面板,这种场景用拦截路由实现非常优雅。

实战经验分享

1. Server Components 的正确使用姿势

在实际开发中,我发现很多开发者对 Server Components 的使用还存在误解。最常见的问题是不清楚什么时候该用 Server Components,什么时候该用 Client Components。

我总结了一个简单的判断标准:如果组件需要处理用户交互(比如 onClick)、使用浏览器 API(比如 window)或者使用 React hooks,那就必须用 Client Components;其他情况,优先使用 Server Components。

举个例子,在我们的数据图表组件中:

// DataChart.tsx
'use client' // 因为需要用到 echarts,所以标记为 client component
import { useEffect, useRef } from 'react'
import * as echarts from 'echarts'export default function DataChart({ data }) {const chartRef = useRef(null)useEffect(() => {const chart = echarts.init(chartRef.current)chart.setOption({// 图表配置})}, [data])return <div ref={chartRef} style={{ width: '100%', height: '400px' }} />
}// DataDisplay.tsx
// 这个组件不需要标记 'use client',默认是 Server Component
import { fetchData } from '@/lib/data'
import DataChart from './DataChart'export default async function DataDisplay() {// 在服务器端获取数据const data = await fetchData()return (<div><h2>数据分析</h2><DataChart data={data} /></div>)
}

2. 数据获取的优化策略

在 App Router 中,数据获取的方式发生了很大变化。我们不再需要使用 getStaticProps 或 getServerSideProps,而是可以直接在组件中使用 async/await。

但是,这里有个容易被忽视的性能优化点。看下面这个例子:

async function getData(id: string) {const res = await fetch(`https://api.example.com/data/${id}`, {next: {revalidate: 3600 // 缓存一小时}})return res.json()
}export default async function Page({ params }: { params: { id: string } }) {const data = await getData(params.id)return <div>{/* 渲染数据 */}</div>
}

这段代码看起来没什么问题,但在实际项目中,我们发现当用户快速切换不同的数据页面时,性能表现并不理想。后来我们采用了 React Suspense 和并行数据请求的方式进行优化:

import { Suspense } from 'react'
import Loading from './loading'// 预加载数据
const preloadData = (id: string) => {void getData(id)
}export default async function Page({ params }: { params: { id: string } }) {// 路由变化时预加载下一页数据return (<Suspense fallback={<Loading />}><DataContent id={params.id} /></Suspense>)
}

3. 路由拦截的实践技巧

App Router 的路由拦截(Intercepting Routes)是一个非常强大的特性。在我们的项目中,最典型的应用是实现类似 Modal 弹窗的数据详情页:

app/data/page.tsx[id]/page.tsx@modal/[id]/page.tsx

这种结构允许我们在列表页面点击某条数据时,以 Modal 形式展示详情,而直接访问详情页面时则显示完整页面。这大大提升了用户体验。

但在实践中我们也发现了一个问题:如果 Modal 中的内容较多,第一次加载时会有明显的延迟。解决方案是使用 Suspense 配合 loading.tsx:

// @modal/[id]/page.tsx
export default async function ModalPage({ params }: { params: { id: string } }) {return (<div className="modal"><Suspense fallback={<LoadingSpinner />}><DataDetail id={params.id} /></Suspense></div>)
}

性能优化的关键点

经过这个项目的实践,我总结了几个关键的性能优化点:

  1. 合理使用 Server Components

    不是所有组件都适合作为 Server Components。需要频繁更新的数据展示组件,反而更适合作为 Client Components,避免频繁的服务器端渲染。

  2. 优化数据加载策略

    使用 Suspense 和 React.lazy() 实现更细粒度的加载控制,配合 loading.tsx 提供更好的加载体验。

  3. 缓存策略的调整

    根据数据的实时性要求,合理设置 revalidate 时间,避免不必要的重新验证。

写在最后

Next.js 13 的 App Router 确实带来了很多令人兴奋的新特性,但也需要我们改变一些既有的开发习惯。通过这个项目,我深刻体会到了它的强大之处,也踩了不少坑。希望这些经验能帮助到同样在使用 App Router 的同学。

如果你也在使用 Next.js 13,欢迎在评论区分享你的经验和想法。如果觉得这篇文章有帮助,别忘了点个赞 👍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/64521.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 中快速插入大量数据

在 MySQL 中快速插入大量数据&#xff08;例如 20 万条记录&#xff09;可以通过多种方法实现。以下是一些优化技巧和步骤&#xff0c;可以帮助你高效地插入大量数据&#xff1a; 1. 禁用索引和约束&#xff08;如果可能&#xff09; 在插入大量数据之前&#xff0c;禁用索引和…

Chrome 浏览器原生功能截长屏

我偶尔需要截取一些网页内容作为素材&#xff0c;但偶尔内容很长无法截全&#xff0c;需要多次截屏再拼接&#xff0c;过于麻烦。所以记录下这个通过浏览器原生功能截长屏的方案。 注意 这种方案并不是百分百完美&#xff0c;如果涉及到一些需要滚动加载的数据或者悬浮区块&am…

Python+OpenCV系列:AI看图识人、识车、识万物

在人工智能风靡全球的今天&#xff0c;用 Python 和 OpenCV 结合机器学习实现物体识别&#xff0c;不仅是酷炫技能&#xff0c;更是掌握未来的敲门砖。本篇博文手把手教你如何通过摄像头或图片输入&#xff0c;识别人、动物、车辆及其他物品&#xff0c;让你的程序瞬间具备 AI …

关于如何正确在测试用例中mock静态方法的问题

文章目录 情况一&#xff1a;希望在测试用例中直接执行静态方法的逻辑情况二&#xff1a;不希望在测试用例中执行静态方法的逻辑插桩方法坑1: 报错SubclassByteBuddyMockMaker原因与解决方案坑2&#xff1a;报错 the existing static mock registration must be deregistered原…

Shell自定义(二)

1.Shell自定义 1.初始化 定义全局变量environ&#xff0c;把g_env的内容用memset初始化为0&#xff0c;这里用malloc开辟的空间为对应环境变量的长度1&#xff0c;多1位置是最后结束符0&#xff0c;strcpy把此时的对应的环境变量拷贝到g_env里面&#xff0c;下面是新增一个环…

PHPstudy中的数据库启动不了

法一 netstat -ano |findstr "3306" 查看占用该端口的进程号 taskkill /f /pid 6720 杀死进程 法二 sc delete mysql

安装与配置MongoDB 6.0以支持远程连接

安装与配置MongoDB 6.0以支持远程连接 目录 安装curl工具下载并导入MongoDB 6.0 PGP密钥向APT导入MongoDB 6.0版软件包的资源链接安装MongoDB依赖libssl1.1安装MongoDB启动并检查MongoDB服务状态进入MongoDB Shell交互式执行环境设置MongoDB开机自启配置MongoDB允许远程连接 …

Hive其一,简介、体系结构和内嵌模式、本地模式的安装

目录 一、Hive简介 二、体系结构 三、安装 1、内嵌模式 2、测试内嵌模式 3、本地模式--最常使用的模式 一、Hive简介 Hive 是一个框架&#xff0c;可以通过编写sql的方式&#xff0c;自动的编译为MR任务的一个工具。 在这个世界上&#xff0c;会写SQL的人远远大于会写ja…

百度智能云千帆AppBuilder升级,百度AI搜索组件上线,RAG支持无限容量向量存储!

百度智能云千帆 AppBuilder 发版升级&#xff01; 进一步降低开发门槛&#xff0c;落地大模型到应用的最后一公里。在千帆 AppBuilder 最新升级的 V1.1版本中&#xff0c;企业级 RAG 和 Agent 能力再度提升&#xff0c;同时组件生态与应用集成分发更加优化。 • 企业级 RAG&am…

解决Ubuntu 20.04上编译OpenCV 3.2时遇到的stdlib.h缺失错误

解决Ubuntu 20.04上编译OpenCV 3.2时遇到的stdlib.h缺失错误 您在 Ubuntu 20.04 上编译 OpenCV 3.2 时遇到的错误与 C 标准库的头文件配置问题有关。错误消息指出系统无法找到 <stdlib.h>&#xff0c;这通常与预编译头文件的处理、GCC 版本或者头文件搜索路径有关。下面…

Swagger自动文档工具以及gin-swagger的使用

什么是 Swagger&#xff1f; Swagger 是一个开源的 API 设计和文档工具&#xff0c;旨在帮助开发者更高效地设计、构建、记录和测试 RESTful API。它基于 OpenAPI 规范&#xff08;前身为 Swagger 规范&#xff09;&#xff0c;通过自动化的方式生成交互式 API 文档、客户端 S…

网络视频监控平台/安防监控/视频综合管理Liveweb视频汇聚平台解决方案

一、当前现状分析 当前视频资源面临以下问题&#xff1a; 1&#xff09;不同单位在视频平台建设中以所属领域为单位&#xff0c;设备品牌众多&#xff0c;存在的标准不一&#xff0c;各系统之间也没有统一标准&#xff1b; 2&#xff09;各单位视频平台建设分散、统筹性差&am…

为什么要用单例模式?

‌单例模式是一种创建型设计模式&#xff0c;用于确保某个类只有一个实例&#xff0c;并提供一个全局访问点&#xff0c;使得其他类可以轻松访问该实例‌。 使用单例模式的主要原因包括以下几点&#xff1a;‌ ‌确保唯一性‌&#xff1a;在某些情况下&#xff0c;我们需要确…

c语言——数据结构【链表:单向链表】

上篇→快速掌握C语言——数据结构【创建顺序表】多文件编译-CSDN博客 一、链表 二、单向链表 2.1 概念 2.2 单向链表的组成 2.3 单向链表节点的结构体原型 //类型重定义,表示存放的数据类型 typedef int DataType;//定义节点的结构体类型 typedef struct node {union{int l…

在Linux中使用`scp`进行远程目录文件复制

在Linux系统中&#xff0c;scp&#xff08;安全复制协议&#xff09;是一个使用SSH&#xff08;安全外壳协议&#xff09;进行文件和目录安全传输的命令。它允许在远程主机之间复制文件和目录&#xff0c;具有很强的安全性&#xff0c;是一种常用的文件传输工具。以下是如何使用…

【AI图像生成网站Golang】项目测试与优化

AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与优化 六、项目测试与优化 在开发过程中&#xff0c;性能优化是保证项目可扩展性和用户体验的关键步骤。本文将详细介绍我如何使用一…

Mybatis映射关系

目录 多对一 方式一&#xff1a;一条sql语句&#xff08;级连属性映射&#xff09; 方式二&#xff1a;一条sql语句&#xff08;association&#xff09; 方式三&#xff1a;两条sql语句&#xff0c;分步查询 一对多 方式一&#xff1a;collection 方式二&#xff1a;分…

单片机:实现计数器(附带源码)

一、单片机计数器功能概述 单片机中的计数器一般是由硬件定时器模块实现的&#xff0c;计数器可以被配置为不同的模式&#xff0c;例如&#xff1a; 普通计数模式&#xff1a;计数器从零开始增加&#xff0c;直到某个最大值后清零或中断。事件计数模式&#xff1a;计数器根据…

隐私清理工具Goversoft Privazer

PrivaZer 是一款专为隐私保护而生的 Windows 系统清理工具&#xff0c;支持深度扫描、清除无用文件和隐私痕迹。 PrivaZer - 深度扫描磁盘&#xff0c;自动清理上网痕迹&#xff0c;全面保护 Windows 的网络隐私 释放磁盘空间 硬盘空间告急&#xff0c;想清理却又无从下手&…

基于Spring Boot的医院质控上报系统

一、系统背景与意义 医院质控上报系统旨在通过信息化手段&#xff0c;实现医院质量控制的标准化、流程化和自动化管理。该系统能够帮助医院实时监控医疗质量数据&#xff0c;及时发现和处理潜在的质量问题&#xff0c;从而确保医疗服务的安全性和有效性。同时&#xff0c;系统…