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.mzph.cn/bicheng/65147.shtml

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

相关文章

php8.0版本更新了哪些内容

PHP 8.0版本是PHP语言的一个重要更新&#xff0c;它引入了许多新特性和改进&#xff0c;旨在提高性能、增强代码的可读性和可维护性。以下是PHP 8.0版本更新的主要内容&#xff1a; 一、性能提升 JIT编译器&#xff1a;PHP 8.0引入了Just-In-Time&#xff08;JIT&#xff09;…

在 Ubuntu 服务器上添加和删除用户

在 Ubuntu 服务器上添加和删除用户通常使用命令行工具&#xff0c;如 adduser、useradd、deluser 等。以下是详细的步骤和说明&#xff1a; 添加用户 使用 adduser 命令 adduser 是一个更为友好的脚本&#xff0c;用于创建新用户并设置相关信息。 添加新用户 sudo adduser 用…

docker 部署win系统

1、拉取docker win镜像 docker push crpi-k5k93ldwfc7o75ip.cn-hangzhou.personal.cr.aliyuncs.com/upsnap/windows:latest 2、配置docker-compose.yml文件 services:windows:image: dockurr/windowscontainer_name: windowsenvironment:VERSION: "11"devices:- …

复习打卡大数据篇——Hadoop HDFS 03

目录 1. HDFS元数据存储 2. HDFS HA 高可用 1. HDFS元数据存储 HDFS中的元数据按类型可以分为&#xff1a; 文件系统的元数据&#xff1a;包括文件名、目录名、修改信息、block的信息、副本信息等。datanodes的状态信息&#xff1a;比如节点状态、使用率等。 HDFS中的元数…

209.长度最小的子数组

力扣题目链接(opens new window) 给定一个含有 n 个正整数的数组和一个正整数 s &#xff0c;找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组&#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0。 示例&#xff1a; 输入&#xff1a;s 7, nums…

NLP中的神经网络基础

一&#xff1a;多层感知器模型 1&#xff1a;感知器 解释一下&#xff0c;为什么写成 wxb>0 &#xff0c;其实原本是 wx > t ,t就是阈值&#xff0c;超过这个阈值fx就为1&#xff0c;现在把t放在左边。 在感知器里面涉及到两个问题&#xff1a; 第一个&#xff0c;特征提…

week 11 - BCNF

1. More on functional dependencies (功能依赖的更多内容) Lossless decomposition (无损分解) 研究如何在分解表的过程中不丢失信息&#xff0c;也就是说&#xff0c;通过分解后的表可以无损地重建原始表。 2. BCNF (Boyce-Codd Normal Form, BCNF范式) &#xff08;1&…

golangci-lint安装与Goland集成

golangci-lint安装与Goland集成 1.golangci-lint概述2.golangci-lint安装3.Goland 中集成 golangci-lint4.golangci-lint 的使用5.排除代码检查 1.golangci-lint概述 golangci-lint是用于go语言的代码静态检查工具集 官网地址&#xff1a;golangci-lint 特性&#xff1a; 快…

GPUStack v0.4.1 单节点与多节点安装与部署指南 Docker PowerShell

Introduce GPUStack 是一个开源的 GPU 集群管理器&#xff0c;专为运行 AI 模型而设计。它以其广泛的硬件兼容性而闻名&#xff0c;支持多种品牌的 GPU&#xff0c;并能在 Apple MacBook、Windows PC 和 Linux 服务器上运行。 GPUStack支持各种AI模型&#xff0c;包括大型语言…

GoFrame框架介绍

GoFrame是一款功能强大、设计精良且易用的Go语言开发框架&#xff0c;以下为你详细介绍它的相关特点和内容&#xff1a; ### 框架概述 GoFrame是为了提升Go语言开发者的编码效率以及项目的整体可维护性、可扩展性等而打造的开发框架&#xff0c;它涵盖了从基础的网络通信、数据…

【Docker】部署MySQL容器

关于docker&#xff0c;Windows上使用Powershell/CMD执行指令&#xff0c;Linux系统直接使用终端执行指令。 拉取MySQL 也可以跳过拉取步骤&#xff0c;直接run&#xff0c;这样本地容器不存在的话&#xff0c;会自动拉取最新/指定的版本。 # 默认拉取最新版本 docker pull …

黑马程序员JavaWeb开发教程(前端部分) ---笔记分享

总结 此篇文章记录的内容是不全的&#xff0c;我觉得基础的部分没有记录&#xff0c;我想主要学的是此课程的后端部分&#xff0c;前端部分学校有学习过&#xff0c;我就开倍速一带而过啦&#xff0c;还有就是学校学的是Vue3和此视频讲的Vue2还是有一定区别的。希望能对大家有…

SpringCloud 系列教程:微服务的未来(二)Mybatis-Plus的条件构造器、自定义SQL、Service接口基本用法

本篇博客将深入探讨 MyBatis-Plus 的三个核心功能&#xff1a;条件构造器、自定义 SQL 和 Service 接口的基本用法。通过对这些功能的学习和掌握&#xff0c;开发者能够更加高效地使用 MyBatis-Plus 进行业务开发。 目录 前言 条件构造器 自定义SQL Service接口基本用法 总结…

知识增强式生成KAG

随着人工智能技术的不断发展&#xff0c;尤其是在自然语言处理领域&#xff0c;知识增强式生成&#xff08;KAG&#xff09;作为一种新兴的技术框架&#xff0c;正逐步脱颖而出。与其前身——检索增强式生成&#xff08;RAG&#xff09;相比&#xff0c;KAG在处理特定领域知识、…

Nginx区分PC端和移动端访问

在使用Nginx时&#xff0c;可以通过$http_user_agent变量来判断用户访问的客户端类型&#xff0c;从而提供不同的内容或服务。下面是一个基于$http_user_agent变量来判断是否为PC访问的Nginx配置示例。 1. 理解$http_user_agent变量的含义及其在Nginx中的用途 $http_user_agen…

1.监督学习(上)

一.线性回归(Linear Regression Model): 输出无限多可能的数字。 【示例1】房价预测: 【图一】 假设您想根据房屋的大小预测房屋的价格,横轴:以平方英尺为单位的房屋大小,纵轴:是以千美元为单位的房屋价格。这里的小十字字中的每一个都是一所房子,其大小和价格是最…

前端编程图表化助手!Echarts入门

Echarts-一个基于javaScript的开源可视化图表库 在日常编程中&#xff0c;我们经常会用到类似饼图、柱状图等&#xff0c;而在网页中使用原生html和css很难做到类似效果。那么作为前端工程师&#xff0c;我们如何做出来一份好看而且实用的图标呢&#xff1f; 那么接下来&…

C#WPF基础介绍/第一个WPF程序

什么是WPF WPF&#xff08;Windows Presentation Foundation&#xff09;是微软公司推出的一种用于创建窗口应用程序的界面框架。它是.NET Framework的一部分&#xff0c;提供了一套先进的用户界面设计工具和功能&#xff0c;可以实现丰富的图形、动画和多媒体效果。 WPF 使用…

444444444444

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤1.引入库2.读入数据 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;…

项目练习:Vue项目中使用Vuex实现全局功能开发

文章目录 一、场景说明二、代码实现1、通用方法封装2、store配置3、使用Vuex 一、场景说明 我们在开发的过程中&#xff0c;都要求能够把通用方法进行抽象封装&#xff0c;供全局使用 这样&#xff0c;代码更优雅简练。 Vue中就可以用Vuex实现全局方法的开发。 这一篇&#x…