Next.js 14 性能优化:从首屏加载到运行时优化的最佳实践

在现代 Web 应用中,性能优化直接影响用户体验和业务转化。Next.js 14 提供了多种内置的性能优化特性,今天我们就来深入探讨如何充分利用这些特性,以及一些实用的优化技巧。

图片和字体优化

1. 图片优化

Next.js 的 Image 组件供了强大的图片优化功能:

// components/OptimizedImage.tsx
import Image from 'next/image';
import { useState } from 'react';interface OptimizedImageProps {src: string;alt: string;width: number;height: number;
}export function OptimizedImage({src,alt,width,height
}: OptimizedImageProps) {const [isLoading, setLoading] = useState(true);return (<div className="relative overflow-hidden"><Imagesrc={src}alt={alt}width={width}height={height}quality={75} // 默认图片质量placeholder="blur" // 使用模糊占位blurDataURL="data:image/jpeg;base64,..." // 生成的 base64 图片className={`duration-700 ease-in-out${isLoading ? 'scale-110 blur-2xl' : 'scale-100 blur-0'}`}onLoadingComplete={() => setLoading(false)}priority={false} // 是否优先加载/></div>);
}// 使用自定义图片加载器
const imageLoader = ({ src, width, quality }) => {return `https://your-cdn.com/${src}?w=${width}&q=${quality || 75}`;
};// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {images: {loader: 'custom',loaderFile: './lib/imageLoader.ts',deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],formats: ['image/webp'],},
};

2. 字体优化

Next.js 14 提供了内置的字体优化:

// app/fonts.ts
import { Inter, Roboto_Mono } from 'next/font/google';export const inter = Inter({subsets: ['latin'],display: 'swap',preload: true,fallback: ['system-ui', 'arial'],adjustFontFallback: true, // 自动调整回退字体
});export const roboto_mono = Roboto_Mono({subsets: ['latin'],display: 'swap',
});// app/layout.tsx
import { inter } from './fonts';export default function RootLayout({children,
}: {children: React.ReactNode;
}) {return (<html lang="en" className={inter.className}><body>{children}</body></html>);
}// 自定义字体加载
import localFont from 'next/font/local';const myFont = localFont({src: [{path: '../public/fonts/font-regular.woff2',weight: '400',style: 'normal',},{path: '../public/fonts/font-bold.woff2',weight: '700',style: 'normal',},],display: 'swap',preload: true,
});

动态导入和代码分割

1. 组件动态导入

// components/DynamicComponent.tsx
import dynamic from 'next/dynamic';
import { Suspense } from 'react';// 基础动态导入
const DynamicHeader = dynamic(() => import('./Header'), {loading: () => <p>Loading...</p>,ssr: true, // 是否服务端渲染
});// 带有自定义加载的动态导入
const DynamicChart = dynamic(() => import('./Chart').then(mod => mod.Chart),{loading: () => <ChartSkeleton />,ssr: false, // 禁用服务端渲染}
);// 使用 Suspense 包裹动态组件
export function DashboardPage() {return (<div><DynamicHeader /><Suspense fallback={<ChartSkeleton />}><DynamicChart /></Suspense></div>);
}

2. 路由分组和懒加载

// app/(marketing)/layout.tsx
import { Suspense } from 'react';// 营销相关页面的布局
export default function MarketingLayout({children
}: {children: React.ReactNode;
}) {return (<div className="marketing-layout"><Suspense fallback={<NavSkeleton />}><Navigation /></Suspense>{children}</div>);
}// app/(dashboard)/layout.tsx
// 仪表板相关页面的布局
export default function DashboardLayout({children
}: {children: React.ReactNode;
}) {return (<div className="dashboard-layout"><Suspense fallback={<SidebarSkeleton />}><Sidebar /></Suspense><main>{children}</main></div>);
}

缓存策略优化

1. 数据缓存

// lib/cache.ts
import { cache } from 'react';
import { Redis } from '@upstash/redis';const redis = new Redis({url: process.env.REDIS_URL,token: process.env.REDIS_TOKEN,
});// 使用 React 缓存
export const getCachedData = cache(async (key: string) => {// 首先尝试从 Redis 获取const cached = await redis.get(key);if (cached) return JSON.parse(cached);// 如果没有缓存,则获取新数据const data = await fetchData(key);// 存入 Redisawait redis.set(key, JSON.stringify(data), {ex: 3600 // 1小时过期});return data;
});// 使用示例
async function ProductPage({ id }: { id: string }) {const product = await getCachedData(`product:${id}`);return <ProductDetails product={product} />;
}

2. 静态生成优化

// app/products/[id]/page.tsx
import { generateMetadata } from 'next';// 生成静态路由
export async function generateStaticParams() {const products = await getTopProducts();return products.map((product) => ({id: product.id,}));
}// 静态元数据
export async function generateMetadata({ params }: {params: { id: string }
}): Promise<Metadata> {const product = await getProduct(params.id);return {title: product.name,description: product.description,openGraph: {images: [product.image],},};
}// 页面组件
export default async function ProductPage({params
}: {params: { id: string }
}) {const product = await getProduct(params.id);return (<div><h1>{product.name}</h1><ProductDetails product={product} /></div>);
}

首屏加载优化

1. 流式渲染

// app/page.tsx
import { Suspense } from 'react';
import { headers } from 'next/headers';async function SlowComponent() {const headersList = headers();const userAgent = headersList.get('user-agent');// 模拟慢速数据加载await new Promise(resolve => setTimeout(resolve, 2000));return (<div><p>User Agent: {userAgent}</p></div>);
}export default function HomePage() {return (<div><h1>即时加载的内容</h1><Suspense fallback={<LoadingSkeleton />}><SlowComponent /></Suspense><Suspense fallback={<CardsSkeleton />}><PopularProducts /></Suspense><Suspense fallback={<FeedSkeleton />}><RecentActivity /></Suspense></div>);
}

2. 预加载数据

// lib/prefetch.ts
export async function prefetchData() {// 预加载关键数据const promises = [prefetchNavigation(),prefetchUserData(),prefetchPopularProducts(),];await Promise.all(promises);
}// app/layout.tsx
export default async function RootLayout({children
}: {children: React.ReactNode
}) {// 在布局组件中预加载数据await prefetchData();return (<html><body>{children}</body></html>);
}

Core Web Vitals 优化

1. 性能监控

// lib/analytics.ts
export function reportWebVitals({id,name,label,value,
}: {id: string;name: string;label: string;value: number;
}) {// 发送性能指标到分析服务fetch('/api/analytics', {method: 'POST',body: JSON.stringify({id,name,label,value,// 添加其他上下文信息page: window.location.pathname,timestamp: Date.now(),}),});
}// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {experimental: {instrumentationHook: true,},
};// instrumentation.ts
export function register() {if (process.env.NEXT_RUNTIME === 'nodejs') {// 服务端监控require('./monitoring/server').setup();}
}

2. 性能优化实践

// components/OptimizedList.tsx
import { useVirtualizer } from '@tanstack/react-virtual';
import { useIntersectionObserver } from '@/hooks/useIntersectionObserver';// 虚拟列表优化
export function OptimizedList({ items }: { items: any[] }) {const parentRef = useRef<HTMLDivElement>(null);const virtualizer = useVirtualizer({count: items.length,getScrollElement: () => parentRef.current,estimateSize: () => 50,});return (<div ref={parentRef} className="h-[500px] overflow-auto"><divstyle={{height: `${virtualizer.getTotalSize()}px`,position: 'relative',}}>{virtualizer.getVirtualItems().map((virtualItem) => (<divkey={virtualItem.key}style={{position: 'absolute',top: 0,left: 0,width: '100%',height: `${virtualItem.size}px`,transform: `translateY(${virtualItem.start}px)`,}}><ListItem item={items[virtualItem.index]} /></div>))}</div></div>);
}// 图片懒加载优化
export function LazyImage({ src, alt }: { src: string; alt: string }) {const imgRef = useRef<HTMLImageElement>(null);const { isIntersecting } = useIntersectionObserver(imgRef);return (<imgref={imgRef}src={isIntersecting ? src : ''}alt={alt}loading="lazy"decoding="async"/>);
}

3. 构建优化

// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({enabled: process.env.ANALYZE === 'true',
});/** @type {import('next').NextConfig} */
const nextConfig = {// 优化构建配置poweredByHeader: false,compress: true,productionBrowserSourceMaps: false,// 优化图片配置images: {minimumCacheTTL: 60,deviceSizes: [640, 750, 828, 1080, 1200, 1920],imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],},// 实验性功能experimental: {optimizeCss: true, // 启用 CSS 优化scrollRestoration: true, // 启用滚动位置恢复serverActions: true, // 启用服务端操作},// webpack 配置webpack: (config, { dev, isServer }) => {// 优化生产环境构建if (!dev && !isServer) {config.optimization.splitChunks = {chunks: 'all',minSize: 20000,maxSize: 244000,minChunks: 1,maxAsyncRequests: 30,maxInitialRequests: 30,cacheGroups: {defaultVendors: {test: /[\\/]node_modules[\\/]/,priority: -10,reuseExistingChunk: true,},default: {minChunks: 2,priority: -20,reuseExistingChunk: true,},},};}return config;},
};module.exports = withBundleAnalyzer(nextConfig);

写在最后

Next.js 14 提供了丰富的性能优化工具和特性。在实际应用中,需要注意以下几点:

  1. 合理使用图片和字体优化
  2. 实施有效的代码分割策略
  3. 优化数据缓存和预加载
  4. 监控和优化 Core Web Vitals
  5. 持续进行构建优化

在下一篇文章中,我们将深入探讨 Next.js 14 的部署与运维策略。如果你有任何问题或建议,欢迎在评论区讨论!

如果觉得这篇文章对你有帮助,别忘了点个赞 👍

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

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

相关文章

Vue开发环境搭建上篇:安装NVM和NPM(cpnm、pnpm)

文章目录 引言I 安装NVM1.1 Windows系统安装NVM,实现Node.js多版本管理1.2 配置下载镜像1.3 NVM常用操作命令II NPM永久使用淘宝源安装 cnpm安装pnpm【推荐】see also: vscode常用插件引言 淘宝镜像:http://npm.taobao.org 和 http://registry.npm.taobao.org 已在 2022.06.3…

x86_64 Ubuntu 编译安装英伟达GPU版本的OpenCV

手把手带你在Linux上安装带GPU加速的opencv库&#xff08;C版本&#xff09;_opencv linux-CSDN博客 cmake \-D CMAKE_BUILD_TYPERELEASE \-D OPENCV_GENERATE_PKGCONFIGON \-D CMAKE_INSTALL_PREFIX/usr/local \-D OPENCV_EXTRA_MODULES_PATH/home/hwj/opencv/opencv_contrib…

计算机毕业设计Python+卷积神经网络租房推荐系统 租房大屏可视化 租房爬虫 hadoop spark 58同城租房爬虫 房源推荐系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

bypy上传配置

bypy upload 上传文件权限不足时 使用此方法,改变权限保存 : w ! sudo tee % 好使但是没有进度条 CMAKE 的配置方法

三维动画的常用“视觉特效”有哪些?

在当今的视觉盛宴中&#xff0c;三维动画技术宛如一位神奇的魔法师&#xff0c;为视觉特效&#xff08;VFX&#xff09;领域施下了变革的咒语。从大荧幕上的震撼电影&#xff0c;到让人沉浸其中的视频游戏&#xff0c;再到夺人眼球的广告以及精细的模拟场景&#xff0c;三维动画…

《Cocos Creator游戏实战》非固定摇杆实现原理

为什么要使用非固定摇杆 许多同学在开发摇杆功能时&#xff0c;会将摇杆固定在屏幕左下某一位置&#xff0c;不会让其随着大拇指触摸点改变&#xff0c;而且玩家只有按在了摇杆上才能移动人物&#xff08;触摸监听事件在摇杆精灵上)。然而&#xff0c;不同玩家的大拇指长度不同…

Text组件的用法

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了页面之间传递数据相关的内容,本章回中将介绍如何使用Text Widget。闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的Text Widget就是显示文字内容的组件,其实我们一直在使用它,只是没有详细介…

强大且灵活的终端工具Tabby的强大功能与详细配置指南

文章目录 前言1. Tabby下载安装2. Tabby相关配置3. Tabby简单操作4. ssh连接Linux4.1 ubuntu系统安装ssh4.2 Tabby远程ssh连接ubuntu 5. 安装内网穿透工具5.1 创建公网地址5.2 使用公网地址远程ssh连接 6. 配置固定公网地址 前言 大家好&#xff01;今天我要给大家安利一个超级…

基于Spring Boot的阿坝州旅游系统

一、系统背景与目的 随着旅游业的快速发展和互联网技术的不断进步&#xff0c;越来越多的游客开始通过网络平台来查询旅游信息、预订旅游产品。为了满足游客对阿坝州旅游信息的需求&#xff0c;提升阿坝州旅游业的整体服务水平&#xff0c;基于Spring Boot技术框架开发了一款阿…

IMX芯片启动方式

一、启动方式选择 a)概述 BOOT 的处理过程是发生在 I.MX6U 芯片上电以后,芯片会根据 BOOT_MODE[1:0]的设置 来选择 BOOT 方式。 BOOT_MODE[1:0]的值是可以改变的,有两种方式,一种是改写 eFUSE(熔 丝),一种是修改相应的 GPIO 高低电平。第一种修改 eFUSE 的方式只能修改一次…

【QT开发自制小工具】PDF/图片转excel---调用百度OCR API接口

前言 前几年WPS还可以免费处理5页以内的PDF转excel&#xff0c;现在必须付费了&#xff0c;而且百度其他在线的PDF转excel都是要收费的&#xff0c;刚好前几年调研过百度OCR的高精度含位置接口&#xff0c;依然是每天可以免费调用50次&#xff0c;本篇是基于此接口&#xff0c;…

Flink调优----反压处理

目录 概述 1.1 反压的理解 1.2 反压的危害 定位反压节点 2.1 利用 Flink Web UI 定位 通过 WebUI 看到 Map 算子处于反压&#xff1a;​编辑 分析瓶颈算子 2.2 利用 Metrics 定位 根据指标分析反压 可以进一步分析数据传输 反压的原因及处理 3.1 查看是否数据倾斜 …

RabbitMQ工作模式(详解 工作模式:简单队列、工作队列、公平分发以及消息应答和消息持久化)

文章目录 十.RabbitMQ10.1 简单队列实现10.2 Work 模式&#xff08;工作队列&#xff09;10.3 公平分发10.4 RabbitMQ 消息应答与消息持久化消息应答概念配置 消息持久化概念配置 十.RabbitMQ 10.1 简单队列实现 简单队列通常指的是一个基本的消息队列&#xff0c;它可以用于…

追风赶月莫停留,平芜尽处是春山—记一次备考经历(下)

追风赶月莫停留&#xff0c;平芜尽处是春山—记一次备考经历&#xff08;上&#xff09; 上篇是对政治、英语、专业的总结&#xff0c;这篇是对数学的总结。 数学二-高数 从之前考试得出的结论“得数学者得天下”&#xff0c;所以特别重视数学&#xff0c;70%的时间都用在了…

【设备 磁盘】重要备份存放U盘的风险 + winhex 磁盘清零(清理windows无法格式化的磁盘)

简述 清理用设备管理器和DiskGenious无法打开的磁盘 winhex安装 官网https://www.x-ways.net/winhex/下载&#xff0c;解压后以管理员身份运行 注意&#xff1a;非完全版不能像磁盘写入编辑后的数据 使用 解压后直接点击打开即可 打开磁盘 “全选”后&#xff0c;选择…

虚幻引擎是什么?

Unreal Engine&#xff0c;是一款由Epic Games开发的游戏引擎。该引擎主要是为了开发第一人称射击游戏而设计&#xff0c;但现在已经被成功地应用于开发模拟游戏、恐怖游戏、角色扮演游戏等多种不同类型的游戏。虚幻引擎除了被用于开发游戏&#xff0c;现在也用于电影的虚拟制片…

CI/CD是什么?

CI/CD 定义 CI/CD 代表持续集成和持续部署&#xff08;或持续交付&#xff09;。它是一套实践和工具&#xff0c;旨在通过自动化构建、测试和部署来改进软件开发流程&#xff0c;使您能够更快、更可靠地交付代码更改。 持续集成 (CI)&#xff1a;在共享存储库中自动构建、测试…

LabVIEW软件开发的未来趋势

LabVIEW软件开发的未来趋势可以从以下几个方面来分析&#xff1a; ​ 1. 与AI和机器学习的深度结合 趋势&#xff1a;LabVIEW正在向集成AI和机器学习方向发展&#xff0c;尤其是在数据处理、预测性维护和自动化控制领域。 原因&#xff1a;AI技术的普及使得实验和工业场景中的…

Ruby+Selenium教程

什么是 Minitest&#xff1f; Minitest 是 Ruby 的测试框架&#xff0c;提供一整套测试工具。它运行速度快&#xff0c;支持 TDD、BDD、模拟和基准测试 以下是使用Ruby、Selenium WebDriver和Minitest 的脚本&#xff0c;用于断言 Restful Booker Platform 的“页面标题”等于…

【Select 语法全解密】.NET开源ORM框架 SqlSugar 系列

系列文章目录 &#x1f380;&#x1f380;&#x1f380; .NET开源 ORM 框架 SqlSugar 系列 &#x1f380;&#x1f380;&#x1f380; 文章目录 系列文章目录前言一、Select 执行位置二、返回一个字段和多个字段三、单表返回DTO四、多表返回DTO4.1 手动DTO4.2 实体自动映射14.…