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がすべて解析されるまでレンダリングを開始しません。ブラウザが1つ以上の外部CSSファイルをダウンロードする必要がある場合、貴重な時間がかかる可能性があります。この記事では、NextJSアプリでレンダーブロッキングCSSファイルを削除してレンダリングを高速化する方法を紹介します。これにより、ペイント指標(First Contentful PaintおよびLargest Contentful Paint)が改善されます

デフォルトでは、NextJSはページごとに2つのスタイルシートを作成します。1つ目はグローバルスタイルシート、2つ目はページ固有のスタイルシートです。これにどのくらいの時間がかかるでしょうか?それは、訪問者のデバイス、ネットワーク速度、ネットワーク接続プロトコル、サーバーまでの距離、スタイルシートのサイズなど、多くの要因に依存します。私のすべてのクライアントにおいて、すべてのデバイスの平均では、約200msかかることがわかっています。NextJSのウェブサイトでは、高速3G接続でこれら2つのスタイルシートのダウンロードに600msかかります。これにより、すべてのペイント指標が600ms遅延します。これらのレンダーブロッキングスタイルシートを削除する時です!

nextjs css network

オプション1: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 }
}

オプション2:ページのHEADにCSSをインライン化する。

Core Web Vitalsを改善するためにNextJSアプリで実験的機能を有効にしたくない場合は、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>
  );
}  

オプション3:Styled Components

Styled Componentsは、JavaScriptファイル内にCSSを記述できるCSS-in-JSツールです。これには多くの利点があります。たとえば、クラス名を繰り返し使用でき、未使用の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();
    }
  }
}

Your dev team is busy.

Delegate the performance architecture to a specialist. I handle the optimization track while your team ships the product.

Discuss Resource Allocation >>

  • Parallel Workflows
  • Specialized Expertise
  • Faster Delivery
NextJS Core Web Vitals - レンダーブロッキングCSSを削除するCore Web Vitals NextJS Core Web Vitals - レンダーブロッキングCSSを削除する