Ryota Kondo

Ryota Kondo

2023/03/27

microCMS + Next.jsで埋め込んだツイートを表示する|パフォーマンス改善編

前回の「microCMS + Next.jsで埋め込んだツイートを表示する|基本編」に続き、今回はパフォーマンスを改善する方法について説明します。方法は①~③まであり、すべてを適用させることも可能です。

環境

  • Next.js 13.0.5
  • React 18.2.0
  • typescript 4.9.3
  • cheerio 1.0.0-rc.12

パフォーマンス改善

①load関数にHTMLElementを渡す

埋め込んだツイートを表示させるwindow.twttr.widgets.load()関数は引数なしだと<body>全体を検索します。この関数にツイートが含まれるHTMLElementを引数として渡すことで、必要最小限の検索範囲に絞ることができます。

参考|Scripting: Loading and Initialization | Docs | Twitter Developer Platform

ブログの記事詳細ページをサンプルコードとすると、下のような形です。ツイートが埋め込まれるリッチテキストエディタの要素に対してidを設定し、idからHTMLElementを取得する形となっています。

//  pages/blog/[id].tsx
import React, { useEffect } from "react";

declare global {
  // windowにtwttrが存在しないとエラーになるので、any型で宣言
  var twttr: any;
}

export default function BlogId({ blog }: Props) {

  const { asPath } = useRouter();
  const blogContentId = "blog_content";

  useEffect(
    () => {
      try {
        // ツイートが埋め込まれるHTMLElementを指定し、読込みを実行
        window.twttr.widgets.load(document.getElementById(blogContentId));
      } catch (err) {
        console.error(err);
      }
    },
    // ページ遷移時にもuseEffectを実行するため、asPathを指定
    [asPath]
  );

  return (
    <main>
      {/* リッチエディタの内容を展開 */}
      <div
        id={blogContentId} /* HTMLElement取得のためidを設定 */
        dangerouslySetInnerHTML={{
          __html: `${blog.body}`,
        }}
      />
    </main>
  );
}

②不要な外部スクリプト読込みを削除

埋め込んだツイートをmicroCMSのAPIから取得すると下のようになっており、外部スクリプトを読み込んでいます。このスクリプトは基本編pages/_document.tsxにて読み込むようにしました。そのため下の外部スクリプトの読み込みは不要となり、削除が可能です。

<blockquote class="twitter-tweet">
 // ツイート内容が入る
</blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

リッチエディタの内容を解析しスクリプトを削除する必要がありますので、cheerioというHTMLパーサーライブラリを使用します。まずは下のコマンドからインストールを実施してください。

npm install cheerio

最後にツイートを表示するページのgetStaticPropsにスクリプトを削除する処理を追加します。

//  pages/blog/[id].tsx
import React, { useEffect } from "react";
import { load } from "cheerio";  // インポートを追加

/* 間の処理は省略 */

export const getStaticProps = async (context) => {
  const id = context.params.id;
  const data = await client.get({ endpoint: "blogs", contentId: id });

  // ---- 追加する処理 ここから ----
  const $ = load(data.content);  // data.contentはリッチエディタ部
  // Twitter埋込の場合、scriptを削除する
  $("blockquote.twitter-tweet").each((_, elm) => {
    // 次の要素がscriptの場合、削除する
    if ($(elm).next().is("script")) {
      $(elm).next().remove();
    }
  });
  data.content = $.html();
  // ---- 追加する処理 ここまで ----

  return {
    props: {
      blog: data,
    },
  };
};

③公式ドキュメントで紹介されているスニペットを利用する

1ページに複数のツイートが埋め込まれる場合に有用な方法です。公式のドキュメントで「For best performance and reliability, include the widgets.js script in your template」と紹介されているスニペットを利用します。scriptの読み込みや埋め込みを行うfunctionの実行を効率化するとのことです。

参考|Set up Twitter for Websites | Docs | Twitter Developer Platform

具体的な実装は基本編pages/_document.tsxにて読み込むようにした、下のスクリプトの箇所を変更します。

<Script
  id="twitter-widget"
  src="https://platform.twitter.com/widgets.js"
  strategy="afterInteractive"
/>

変更後はこのようになります。

// pages/_document.tsx
import Document, { Html, Head, Main, NextScript } from "next/document";
import Script from "next/script";

export default class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head>
          {/* ===== 変更した処理 ここから ===== */}
          <Script id="twitter-snippet" strategy="afterInteractive">
            {`
                window.twttr = (function(d, s, id) {
                  var js, fjs = d.getElementsByTagName(s)[0],
                    t = window.twttr || {};
                  if (d.getElementById(id)) return t;
                  js = d.createElement(s);
                  js.id = id;
                  js.src = "https://platform.twitter.com/widgets.js";
                  fjs.parentNode.insertBefore(js, fjs);
                
                  t._e = [];
                  t.ready = function(f) {
                    t._e.push(f);
                  };
                
                  return t;
                }(document, "script", "twitter-wjs"));
              `}
          </Script>
          {/* ===== 変更した処理 ここまで ===== */}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

おわりに

microCMS + Next.jsで埋め込んだツイートを表示する|基本編」に続き、パフォーマンスを改善する方法について説明しました。

サイトにツイートを表示する際の参考となれば幸いです。

参考

この記事は以下の情報を参考にしました。

関連タグの記事

Ryota Kondo
Ryota Kondo

システムエンジニア・プログラマー|このブログサイトの運営もしており、思いついたことをまとめて記事を書いています💡