我的Next.js项目Lighthouse性能评分低(37分)原因排查求助
电商网站性能优化问题:Lighthouse仅37分,怀疑_app或Redux配置问题
我搭建了电商网站,使用Lighthouse检测性能仅得37分。已尝试以下优化但无效果:
- 使用Next Image组件(图片为WebP格式)
- 使用Next Link组件
- 通过Tailwind全局配置引入字体
- 首页使用动态导入缩减文件体积
移除首页所有内容后性能仅小幅改善,怀疑问题出在_app目录或Redux配置,相关代码如下:
index页面代码
import styles from "../styles/Home.module.scss"; import Header from "@/components/header"; // import Footer from "@/components/footer"; import Main from "../components/home/main"; import FlashDeals from "../components/home/flashDeals"; // import Categorye from "../components/home/category"; import SubCategory from "@/models/SubCategory"; import db from "../utils/db"; import Product from "../models/Product"; // import ProductCard from "../components/productCard"; import dynamic from "next/dynamic"; import Head from "next/head"; import HeaderTags from "@/components/home/headerTags/HeaderTags"; import SaleCode from "@/components/home/saleCode/SaleCode"; const Categorye = dynamic(() => import("../components/home/category")); const ProductCard = dynamic(() => import("../components/productCard")); const Footer = dynamic(() => import("@/components/footer"), { ssr: false }); export default function Home({ products }) { return ( <div> <Head> <title> Anime majice, cene i rasprodaja za 2023. godinu - Roomy </title> <link rel="icon" href="/roomy.ico" /> <meta name="description" content="100% povrat novca ukoliko Vam se majica ne svidi iz bilo kog razloga! Besplatna i brza dostava! Pronađite majicu sa svojim omiljenim anime junakom." /> </Head> <Header /> <div className={styles.home}> <SaleCode /> <HeaderTags /> <div className={styles.container}> <Main /> <FlashDeals products={products} /> {/* <AdvantageSlider/> */} <div className={styles.home__category}> <Categorye header="Naruto Majice" products={products.filter( (product) => product?.subCategories[0]?.name === "Naruto" )} background="#11182c" slug={`/majice?category=649fef8a1b7123904696900e`} /> <Categorye header="One Piece Majice" products={products.filter( (product) => product?.subCategories[0]?.name === "One Piece" )} background="#11182c" slug={`/majice?category=649fef8a1b7123904696900e`} /> <Categorye header="AOT Majice" products={products.filter( (product) => product?.subCategories[0]?.name === "AOT" )} background="#11182c" slug={`/majice?category=649fef8a1b7123904696900e`} /> </div> <div className={`${styles.products} justify-center`}> {products.map((product) => ( <ProductCard product={product} key={product._id} /> ))} </div> </div> </div> <Footer /> </div> ); } // export async function getStaticProps() { export async function getServerSideProps() { db.connectDb(); let products = await Product.find() .sort({ createdAt: -1 }) .populate({ path: "subCategories", model: SubCategory, select: "name", }) .select("name subProducts slug subCategories") .lean(); return { props: { products: JSON.parse(JSON.stringify(products)), }, }; }
_app页面代码
import "@/styles/globals.scss"; import "../styles/globals.scss"; import { Provider } from "react-redux"; import store from "../store"; import { PersistGate } from "redux-persist/integration/react"; import { persistStore } from "redux-persist"; import { SessionProvider } from "next-auth/react"; import { Analytics } from "@vercel/analytics/react"; import "react-toastify/dist/ReactToastify.css"; import Script from "next/script"; import dynamic from "next/dynamic"; const Toastify = dynamic(() => import("@/components/toastify/Toastify"), { ssr: false }); let persistor = persistStore(store); export default function App({ Component, pageProps: { session, ...pageProps }, }) { return ( <SessionProvider session={session}> <Provider store={store}> <PersistGate loading={null} persistor={persistor}> <Toastify /> <Script strategy="afterInteractive" src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GOOGLE_ANALYTICS_ID}`} /> <Script id="google-analytics" strategy="afterInteractive"> { ` window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', '${process.env.GOOGLE_ANALYTICS_ID}'); `} </Script> <Script strategy="afterInteractive" src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GOOGLE_ADS_ID}`} /> <Script id="google-campaign" strategy="afterInteractive"> { ` window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', '${process.env.GOOGLE_ADS_ID}'); `} </Script> <Component {...pageProps} /> <Analytics /> </PersistGate> </Provider> </SessionProvider> ); }
针对性优化建议
1. _app页面优化
- 删除重复样式导入:代码中重复导入了
globals.scss,移除其中一条,减少不必要的资源加载。 - 优化Redux Persist阻塞逻辑:
PersistGate会阻塞页面渲染直到持久化数据加载完成,可改为:- 仅持久化必要状态(如用户登录信息),而非全量store
- 配置轻量化的
loading占位组件,避免首屏空白
- 合并第三方脚本:Google Analytics和Ads的GTAG脚本可合并加载,减少网络请求:
<Script strategy="lazyOnload" src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GOOGLE_ANALYTICS_ID}`} /> <Script id="google-tags" strategy="lazyOnload"> {` window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', '${process.env.GOOGLE_ANALYTICS_ID}'); gtag('config', '${process.env.GOOGLE_ADS_ID}'); `} </Script> - 延迟加载非核心组件:Toastify可通过
useEffect动态导入,避免占用首屏渲染资源。
2. Redux配置优化
- 精简持久化store:检查store中是否有冗余数据,只保留必须持久化的状态,减少初始化时间。
- 生产环境禁用冗余中间件:如日志、调试类中间件,只保留核心功能中间件。
3. 其他优化点
- 替换getServerSideProps为ISR:若产品数据不是实时更新,改用
getStaticProps结合增量静态再生,降低TTFB(首字节时间)。 - 调整动态导入策略:首屏必需的组件(如Categorye、ProductCard)无需动态导入,避免额外网络请求延迟渲染。
- 分析Lighthouse分项数据:查看TTFB、LCP、CLS等具体指标,定位精准性能瓶颈。
内容的提问来源于stack exchange,提问作者Filip Trivan
相关产品推荐
相关产品推荐

