Gatsby v4とWordPressでハマった

本サイト(https://ebisu.com/)は、GatsbyJSとWordPressをメインとした構成になっています。Gatsby v4が登場したのに合わせて更新しようとしたものの、なかなかしんどいことになったのでメモを残したいと思います。

まず、本サイトでは、過去の諸々が含まれているWordPressを活かすため、WordPressからのHTMLをunifiedを使ってhtmlAstに変換した上で、ショートコードやブロックなどを色々と加工しています。

ただ、gatsby-source-wordpresscreateNodeFieldを許してくれなかったもので(現在もだめ?)、回避策として紹介されていたcreateResolversを採用していました。

そして、v4が登場したので、Gatsbyをv4へ、gatsby-source-wordpressをv6へと更新します。

問題なく更新できたように思えましたが、ページを直接開くと画像が読み込まれない現象に気が付きます。Safariで画像が表示されない問題も報告されていたので、画像まわりは独自の実装にしようとhtmlAstをいじり始めたところで、Gatsby v4で導入されたParallel Query Runningが落ちまくります。

Issuesを探してみると、Parallel Query Runningは大飯食らいのようでオプションを色々設定してもねじ伏せるのは現状では不可能。なので、問題を抱えているならv3に帰るのが現状の解決策と言う話に。

https://github.com/gatsbyjs/gatsby/discussions/32389

画像問題の方も、Safari以外でも問題報告がいくつか出ています。ただし、明確な解決策はありません。気になったのは、HTMLReactParserだと<script>が消えてしまうので、dangerouslySetInnerHTMLを使うようにという話になっています。


<script type="module">
  const t =
    "undefined" != typeof HTMLImageElement &&
    "loading" in HTMLImageElement.prototype
  if (t) {
    const t = document.querySelectorAll("img[data-main-image]")
    for (let e of t) {
      e.dataset.src &&
        (e.setAttribute("src", e.dataset.src), e.removeAttribute("data-src")),
        e.dataset.srcset &&
          (e.setAttribute("srcset", e.dataset.srcset),
          e.removeAttribute("data-srcset"))
      const t = e.parentNode.querySelectorAll("source[data-srcset]")
      for (let e of t) e.setAttribute("srcset", e.dataset.srcset), e.remove
      Attribute("data-srcset")
      e.complete && (e.style.opacity = 1)
    }
  }
</script>

もともと、gatsby-source-wordpressの画像はGatsbyImage相当の独自の実装でしたが、v6からさらに新しくなったようです。

これは、いろいろと絡んでそうだということで、この段階でのv4への移行は諦めました。


そして、gatsby@4.8のリリースノートでSafariの問題が解決したとのことですので、検証を再開しました。

しかし、うちの環境の問題は変化なしです。となると、根本的な見直しを考えなければなりません。

まずは、Parallel Query Runningの問題を解決しないとhtmlAstもいじれませんから、そちらから。
環境を変えても、メモリを増やしても、オプションを調整してもメモリを食い尽くしてくれます。ギリギリでも耐えてくれればいいんですが…。

v3では問題なかった処理にほんの少しの処理を加えるだけでも落ち始めるのはなぜ?と頭を抱えていたところで、Migrating from v3 to v4の内容を思い出します。

Gatsby v4ではParallel Query Runningが導入されたことでライフサイクルのどこで処理をするかがシビアになり、v3までで許されていたことが色々と非推奨になっています。たとえば、createResolversでcreateRemoteFileNodeを使うようなことは禁じ手となりました

となると、createResolversでhtmlAstを処理したりで重くなるのが原因か?ということで、createNodeでノードを作成して、WordPressのノードに継ぎ足す正攻法へ。

これが正解だったようで、Parallel Query Runningが落ちなくなります。

htmlAstの処理を増やしても落ちなくなれば、あとはどうにでもなります。

gatsby-source-wordpress@v6の画像まわりを調べてみると、unifiedではHTMLReactParserのように<script>を消してしまうことはないものの、適切なタイミングで処理が実行されないため、うまく機能していないことが見えてきます。

ですから、Reactの方で<script>相当の処理を追加するか、htmlAstの段階で処理をしてしまうか、他のものに置き換えるかという選択になります。

ひととおり試してみた結果、GatsbyImageの構造に組み替えることを選択(gatsby-source-wordpressが処理してくれるメディアファイルの処理をそのまま流用したいので、GatsbyImageのコンポーネントへの置き換えではなく、HTML&CSSを再構成しています)。

CSSの当たり方にも若干の変化があるようで、そのあたりを含めた検証がもう少し残っていますが、ひとまず、v4の移行はできそうなところまで来ました。
長かった…。

しかし、v4はもう4.9なんですよね…。

Compass Booksシリーズ