likes
comments
collection
share

Next.js 优化打包体积减少69%

作者站长头像
站长
· 阅读数 5

Next.js 优化打包体积减少69%

本文主要是针对具体问题的解决,性能优化的实践,提供一个思路和方法,各位看官具体情况需要具体处理。

项目背景

笔者首先是从网站的使用体验上,感觉速度没有之前快了,于是打开了network 和 lighthouse

发现 next.js 构建产物 _app-178bb03084901d5c.js 有499KB,这么大,同时 lighthouse 也指出了一些其他问题。

"next": "13.1.6",
"react": "18.2.0",
"react-dom": "18.2.0",

在不同网速下,情况如下

Next.js 优化打包体积减少69%

开始优化

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.js 优化打包体积减少69%

优化产物体积

安装 [@next/bundle-analyzer](https://www.npmjs.com/package/@next/bundle-analyzer) 是 Next.js 的一个插件,可帮助您管理 JavaScript 模块的大小。它生成每个模块的大小及其依赖关系的可视化报告。您可以使用这些信息来删除较大的依赖项、拆分代码或仅在需要时加载某些部分,从而减少传输到客户端的数据量。

npm i @next/bundle-analyzer
# or
yarn add @next/bundle-analyzer
# or
pnpm add @next/bundle-analyzer

然后修改  next.config.js

const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})
 
/** @type {import('next').NextConfig} */
const nextConfig = {}
 
module.exports = withBundleAnalyzer(nextConfig)

分析依赖包

ANALYZE=true npm run build
# or
ANALYZE=true yarn build
# or
ANALYZE=true pnpm build

执行分析命令后~

Next.js 优化打包体积减少69%

我们就看到,这个体积确实大,发现 highlight.js,加载了全部语言包,这对我来说不是必须的,应该采用异步或者轻量加载的方式。但是我的代码中没有使用highlight.js,通过pnpm why highlight.js 发现被其他库引入的(react-syntax-highlighter),找到了问题的源头,于是开始修改相关组件。其中之一

// 轻量导入的方式
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';

Next.js 优化打包体积减少69%

优化 Cumulative Layout Shift

顶部的“轮播图”是根据systemconfig api 返回结果动态渲染的,它导致 “布局偏移”,因为他不一定存在。设置元素的 displayvisibilityopacity 等 CSS 属性来隐藏元素,这种方式是不行的。

Next.js 的服务端渲染解决问题,决定这个“轮播图”是否出现,通过服务端提前拿到是否展示轮播图的结果,这样客户端就不会出现偏移了

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元素。

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, 有了很明显的提升。

Next.js 优化打包体积减少69%

优化过的依赖体积,由原来的 485KB 减少到 154KB,优化大约百分之69%

Next.js 优化打包体积减少69%

优化过的 network

Next.js 优化打包体积减少69%

结语

下次见各位看官,Next.js国际化多语言探索实践~