Next.js 优化打包体积减少69%
本文主要是针对具体问题的解决,性能优化的实践,提供一个思路和方法,各位看官具体情况需要具体处理。
项目背景
笔者首先是从网站的使用体验上,感觉速度没有之前快了,于是打开了network 和 lighthouse
发现 next.js
构建产物 _app-178bb03084901d5c.js
有499KB,这么大,同时 lighthouse 也指出了一些其他问题。
jsx
"next": "13.1.6",
"react": "18.2.0",
"react-dom": "18.2.0",
在不同网速下,情况如下
开始优化
Lighthouse和核心网页指标
- Largest Contentful Paint (LCP) :衡量加载 性能。 为了提供良好的用户体验,LCP 必须在网页首次开始加载后的 2.5 秒内发生。
- Interaction to Next Paint (INP) :衡量互动 。为了提供良好的用户体验,网页的 INP 不得超过 200 毫秒。
- Cumulative Layout Shift (CLS) :衡量视觉稳定性 。为了提供良好的用户体验,必须将 CLS 保持在 0.1. 或更低
Google 的性能评估工具,用于优化网站性能、可访问性、最佳实践和 SEO。优化前如下图
优化产物体积
安装 [@next/bundle-analyzer](https://www.npmjs.com/package/@next/bundle-analyzer)
是 Next.js 的一个插件,可帮助您管理 JavaScript 模块的大小。它生成每个模块的大小及其依赖关系的可视化报告。您可以使用这些信息来删除较大的依赖项、拆分代码或仅在需要时加载某些部分,从而减少传输到客户端的数据量。
jsx
npm i @next/bundle-analyzer
# or
yarn add @next/bundle-analyzer
# or
pnpm add @next/bundle-analyzer
然后修改 next.config.js
jsx
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
})
/** @type {import('next').NextConfig} */
const nextConfig = {}
module.exports = withBundleAnalyzer(nextConfig)
分析依赖包
jsx
ANALYZE=true npm run build
# or
ANALYZE=true yarn build
# or
ANALYZE=true pnpm build
执行分析命令后~
我们就看到,这个体积确实大,发现 highlight.js,加载了全部语言包,这对我来说不是必须的,应该采用异步或者轻量加载的方式。但是我的代码中没有使用highlight.js,通过pnpm why highlight.js
发现被其他库引入的(react-syntax-highlighter),找到了问题的源头,于是开始修改相关组件。其中之一
jsx
// 轻量导入的方式
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
优化 Cumulative Layout Shift
顶部的"轮播图"是根据systemconfig api 返回结果动态渲染的,它导致 "布局偏移",因为他不一定存在。设置元素的 display
、visibility
或 opacity
等 CSS 属性来隐藏元素,这种方式是不行的。
Next.js 的服务端渲染解决问题,决定这个"轮播图"是否出现,通过服务端提前拿到是否展示轮播图的结果,这样客户端就不会出现偏移了
jsx
export async function getServerSideProps(content: any) {
const baseurl = `http://${process.env.HOSTNAME || 'localhost'}:${process.env.PORT || 3000}`;
const { data } = (await (await fetch(`${baseurl}/api/platform/getSystemConfig`)).json()) as {
data: SystemConfigType;
};
return {
props: {
...(await serviceSideProps(content)),
showCarousel: data.showCarousel
}
};
}
优化图片
首先使用 next/image 优化图像,减小图片大小,使用 priority 对影响LCP的图像优先渲染。
应该对检测为最大内容绘制 (LCP) 元素的任何图像使用优先级属性。具有多个优先级图像可能是合适的,因为不同的图像可能是不同视口尺寸的LCP元素。
jsx
import Image from 'next/image'
export default function Page() {
return (
<Image
src="/profile.png"
width={500}
height={500}
alt="Picture of the author"
priority
/>
)
}
使用 tinify.cn/ 压缩图片大小,使用更好格式的图片
优化无障碍访问
这里只做了小小的处理,给相关的按钮增加了id,能够提高页面的可访问性,这里就不多说了
总结
这里是网站优化过之后的 lighthouse, 有了很明显的提升。
优化过的依赖体积,由原来的 485KB
减少到 154KB
,优化大约百分之69%
优化过的 network
结语
下次见各位看官,Next.js国际化多语言探索实践~