NextJS Core Web Vitals - 移除渲染阻塞 CSS

终极 NextJS Core Web Vitals 指南 - 移除渲染阻塞 CSS

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2024-11-27

在 NextJS 中移除渲染阻塞 CSS

CSS 是渲染阻塞的。这意味着当浏览器在页面 head 中发现 CSS 时,在所有 CSS 被解析完成之前不会开始渲染。如果浏览器需要下载一个或多个外部 CSS 文件,这可能会占用宝贵的时间。在本文中,我将向你展示如何在 NextJS 应用中移除这些渲染阻塞的 CSS 文件以加速渲染。这将改善你的绘制指标(First Contentful Paint 和 Largest Contentful Paint)

默认情况下,NextJS 会为每个页面创建 2 个样式表。第一个是全局样式表,第二个是页面特定的样式表。这会花费我们多少时间?这取决于很多因素,比如访问者的设备、网络速度、网络连接协议、到服务器的距离、样式表的大小等。根据我所有客户在所有设备上的平均数据,我发现这大约需要 200 毫秒。在 NextJS 网站上,在快速 3G 连接下下载这 2 个样式表将需要 600 毫秒。这将使所有绘制指标延迟 600 毫秒。是时候采取行动移除这些渲染阻塞的样式表了!

nextjs css network

方案一:生成 Critical CSS

第一个也是最快的方案是生成 Critical CSS。Critical CSS 是渲染页面可见部分所需的 CSS 规则集合。这些规则以内联方式放置在页面的 HEAD 中。然后,浏览器会继续渲染,同时并行下载原始 CSS 文件。一旦原始 CSS 文件下载完成,它们就会被注入到页面中。

Critical CSS 现在已作为实验性功能在 NextJS 中可用。在 NextJS 中生成 Critical CSS 非常简单。只需在 next.config.js 中添加 experimental: { optimizeCss: true },并在项目中安装 critters@0.0.7 作为依赖即可。

const nextConfig = {
  reactStrictMode: true,
  experimental: { optimizeCss: true }
}

方案二:在页面 HEAD 中内联 CSS

如果你不想在 NextJS 应用中启用实验性功能来改善 Core Web Vitals,你可以考虑内联你的 CSS。你需要创建一个自定义 head 部分并在 _document.tsx 中引用它。

这种方法的缺点是内联 CSS 可能会比第一种方法更大。但是,如果你保持样式表简洁高效,这种方法很可能会显著改善你 NextJS 应用的 Core Web Vitals!

import { Html, Head, Main, NextScript } from "next/document";
import { readFileSync } from "fs";
import { join } from "path";

class InlineStylesHead extends Head {
  getCssLinks: Head["getCssLinks"] = ({ allFiles }) => {
    const { assetPrefix } = this.context;
    if (!allFiles || allFiles.length === 0) return null;
    return allFiles
      .filter((file: any) => /\.css$/.test(file))
      .map((file: any) => (
        <style
          key={file}
          nonce={this.props.nonce}
          data-href={`${assetPrefix}/_next/${file}`}
          dangerouslySetInnerHTML={{
            __html: readFileSync(join(process.cwd(), ".next", file), "utf-8"),
          }}
        />
      ));
  };
}

export default function Document() {
  return (
    <Html>
      <InlineStylesHead />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}  

方案三:Styled Components

Styled Components 是一个 CSS-in-JS 工具,允许你在 JavaScript 文件中编写 CSS。这有很多优势。例如,你可以复用类名,轻松移除未使用的 CSS 代码,与传统 CSS 文件相比更容易管理代码。对于 Core Web Vitals 来说,这意味着你只会注入该页面所需的样式。相当不错,对吧?

从 NextJS 12.1 版本开始,在 NextJS 应用中使用 Styled Components 比以往更加简单。在 next.config.js 中添加 compiler:{styledComponents: true},安装 styled-components(yarn add styled-components,安装完成后运行 yarn add -D @types/styled-components),更新 _document.js 文件以支持 Styled Components 的服务端渲染,就可以了!

const nextConfig = {
    reactStrictMode: true,
    compiler: {
    styledComponents: true,
  }
}
import Document, { DocumentContext } from "next/document";
import { ServerStyleSheet } from "styled-components";

export default class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }
}

Urgent Fix Required?

Google Search Console failing? I offer rapid-response auditing to identify the failure point within 48 hours.

Request Urgent Audit >>

  • 48hr Turnaround
  • Rapid Response
  • Failure Identification
NextJS Core Web Vitals - 移除渲染阻塞 CSSCore Web Vitals NextJS Core Web Vitals - 移除渲染阻塞 CSS