ブログトップ

公開日:

更新日:

11 min read

技術革新

CloudflareでMermaid図のビルドエラーに遭遇した話

CloudflareでMermaid図のビルドエラーに遭遇した話のイメージ

CloudflareでMermaid図のプラグインがビルドできていなかった…涙 ローカルで表示できていたから問題ないと思っていた。 Mermaid図を使用した記事の公開は、まだまだ先なので、その時に確認しようと思っていた。

ところがブログが自動更新されないので、ログを確認したら、5日前からエラーは発生していた。 そんなことに気づかずに、仕事にうつつを抜かしていた私はなんて間抜けなんだ。 へこむ…自己嫌悪に陥る。もう穴を掘って入りたくなる。探さないでくださいと書置きして、旅に出たい気分だ。

エラーの内容

エラーログを見てみると、以下のような内容が表示されていた。

   20:11:28.990	> blog-template@1.1.0 build
20:11:28.990	> astro build
20:11:28.990
20:11:31.217	11:11:31 AM [vite] Error when evaluating SSR module /opt/buildhome/repo/astro.config.mjs: failed to import "rehype-mermaid"
20:11:31.217	|- TypeError: (intermediate value).resolve is not a function
20:11:31.217	    at file:///opt/buildhome/repo/node_modules/.pnpm/mermaid-isomorphic@3.0.0_playwright@1.49.0/node_modules/mermaid-isomorphic/dist/mermaid-isomorphic.js:2:26
20:11:31.218	    at ModuleJob.run (node:internal/modules/esm/module_job:194:25)

解決への道のり

AIに教えを乞う。

Cloudflareでのビルドエラーについて、以下の解決方法があることが分かりました。

rehype-mermaidの問題と解決策

バージョンダウングレード rehype-mermaidの最新版3.0.0ではCloudflare Pagesでビルドが失敗する問題が確認されています。バージョン2.1.0にダウングレードすることで解決できます。

astro.config.mjsの設定

以下のような設定を推奨します:

   export default defineConfig({
	markdown: {
		syntaxHighlight: 'prism',
		rehypePlugins: [[rehypeMermaid, { strategy: 'pre-mermaid' }]]
	}
})

この設定により、Playwrightのブラウザインストールが不要になりますが、playwright本体のインストールは必要です。

エラーの原因を深掘り

なぜrehype-mermaidの最新版3.0.0ではCloudflare Pagesでビルドが失敗するのか?

その理由は以下の通りです:

内部で使用されているmermaid-isomorphicモジュールにおいて、.resolveメソッドが関数として認識されないという型エラーが発生しています。具体的には以下のエラーが表示されます:

   TypeError: (intermediate value).resolve is not a function
at file:///opt/buildhome/repo/node_modules/mermaid-isomorphic/dist/mermaid-isomorphic.js:2:26

バージョン2.1.0の使用 現状の解決策としては、rehype-mermaidのバージョンを2.1.0にダウングレードすることで、ビルドエラーを回避できます。

必要な設定

  • playwrightのインストールは必要
  • ただし、strategy: 'pre-mermaid'を設定することで、Playwrightのブラウザインストールは不要

このエラーは特にCloudflare Pages環境で顕著に発生する問題であり、ローカル環境では発生しない場合があります。

「特にCloudflare Pages環境で顕著に発生する」とある。 悪いのは私ではない。私は悪くない。私のせいではない。

せっかくの機会だ。原因究明にとことん付き合ってやろうじゃないか。 mermaid-isomorphicにエラーがあるのは分かった。 だから同じ問題を抱えていない旧バージョンを使え、というのも分かる。 ダウングレードという言葉は好きではない。 いわゆる「デグレ」だろう?昔なら大ごとなのだが、今はこんなに軽いものなのか。

Playwrightの役割を理解する

ここで新たな疑問が浮かんだ。Playwrightとは、なんぞや?

Playwrightは、Microsoftが開発したWebアプリケーションのE2E(エンドツーエンド)テストを自動化するためのオープンソースフレームワークです。

主な特徴

クロスブラウザ対応

  • Chromium、Firefox、WebKitなど主要ブラウザをサポート
  • Windows、Linux、macOSで動作
  • モバイル環境(iOS SafariやAndroid Chrome)にも対応

豊富な機能

  • ブラウザ操作の自動記録と再生
  • スクリーンショットやビデオ記録
  • ネットワークトラフィックの監視
  • 並列テスト実行による高速化

Mermaid図との関係

なるほど。それで、これが何でマーメイド図の表示に必要なのだ?

技術的な背景

ブラウザ環境の必要性 Mermaid.jsはブラウザAPIに依存して図を描画するため、通常のサーバーサイドレンダリングでは図を生成できません。

主な役割

サーバーサイドレンダリング

  • Playwrightはヘッドレスブラウザとして機能し、ビルド時にMermaid図をSVGやPNGに変換します
  • これにより、クライアントサイドでの描画処理が不要になります

レンダリング戦略 rehype-mermaidプラグインには以下の戦略があります:

  • img-png:PNG画像として出力
  • img-svg:SVG画像として出力
  • inline-svg:インラインSVGとして出力
  • pre-mermaid:クライアントサイドでの描画

最適化オプション

軽量化の方法

  • strategy: 'pre-mermaid'を設定することで、Playwrightのブラウザインストールを回避できます
  • ただし、この場合は描画が若干遅くなる可能性があります

ビルドプロセスの可視化

他にも気になる。「rehype-mermaidプラグイン」だが、何のプラグインだろうか? そもそも”rehype”とはなんぞや? などだらけである。 これはシーケンス図にしたほうが分かりやすそうだ。 ビルド時のPlaywrightとMermaid図の生成プロセスを詳細に説明してもらおう。

こんなん、出ましたけど…

sequenceDiagram autonumber participant Dev as 開発者 participant Build as ビルドプロセス participant Unified as unifiedパイプライン participant Remark as remark participant Rehype as rehypeエコシステム participant RehypeMermaid as rehype-mermaid participant PW as Playwright participant Mermaid as Mermaid.js Dev->>Build: ビルド開始 Build->>Unified: Markdownファイル処理開始 Unified->>Remark: Markdown解析 Remark->>Rehype: HTML変換 Rehype->>RehypeMermaid: mermaidコードブロック検出 RehypeMermaid->>+PW: ヘッドレスブラウザ起動 PW->>+Mermaid: mermaidコード渡す Mermaid-->>-PW: SVG/PNG生成 PW-->>-RehypeMermaid: 画像データ返却 RehypeMermaid->>Rehype: 変換されたHTML返却 Rehype->>Build: 最終HTML生成 Build-->>Dev: ビルド完了

これは分かりやすい。あっぱれじゃ!

シーケンスの説明

ビルドプロセス開始

  • 開発者がビルドコマンドを実行すると、ビルドプロセスが開始されます
  • ビルドプロセスはunifiedパイプラインにMarkdownファイルの処理を依頼します
  • unifiedパイプラインは、テキストコンテンツを処理するための統一的なインターフェースを提供するフレームワークです

Markdown処理

  • unifiedパイプラインがremarkを使用してMarkdownの解析を行います
  • remarkからrehypeエコシステムにHTML変換が行われます
  • rehypeは、HTMLを処理するためのプラグインエコシステムです
  • その後、rehype-mermaidプラグインがmermaidコードブロックを検出します

図の生成

  • rehype-mermaidがPlaywrightを使用してヘッドレスブラウザを起動します
  • PlaywrightがMermaid.jsに検出されたmermaidコードを渡します
  • Mermaid.jsが図をSVG/PNG形式で生成し、Playwrightに返却します
  • 生成された画像データはrehype-mermaidに返却されます

ビルド完了

  • rehype-mermaidが変換されたHTMLをrehypeエコシステムに返却します
  • rehypeが最終的なHTMLを生成し、ビルドプロセスに渡します
  • ビルドプロセスが完了し、開発者に結果が返されます

なるほど、astroでjavascriptであるMermaid.jsを動かして作図させるために、 ヘッドレスブラウザが必要なのだな。 rehype-mermaidはrehypeのプラグインだったという訳じゃ。

ただ「ヘッドレス」なる言葉が、まだもやもやしているのだが、それは別の機会に深掘りしよう。

まとめ

問題と解決方法をまとめてみた。

問題の概要

  • CloudflareでMermaid図のプラグインのビルドが失敗
  • エラー内容:TypeError: (intermediate value).resolve is not a function
  • rehype-mermaidの最新版3.0.0で発生する問題

解決方法

  1. rehype-mermaidのバージョンを2.1.0にダウングレード

package.jsonを修正する方法を説明します:

(1) モジュールのインストールで解決

  1. まず、現在のバージョンをアンインストール:
   npm uninstall rehype-mermaid
## もしくは
pnpm uninstall rehype-mermaid
  1. バージョン2.1.0を指定してインストール:
   npm install rehype-mermaid@2.1.0
## もしくは
pnpm add rehype-mermaid@2.1.0

(2) package.jsonを直接編集する場合:

  1. package.jsonのdependencies(またはdevDependencies)内で、rehype-mermaidの行を以下のように変更:
   {
	"dependencies": {
		"rehype-mermaid": "2.1.0"
	}
}
  1. 変更後、以下のコマンドを実行:
   npm install

変更後は、ビルドを実行して正常に動作するか確認することをお勧めします。

  1. astro.config.mjsに以下の設定を追加:
   export default defineConfig({
	markdown: {
		rehypePlugins: [[rehypeMermaid, { strategy: 'pre-mermaid' }]]
	}
})

※すでに追加されていれば何もしない

注意点

  • playwrightパッケージ本体のインストールは必要
  • strategy: 'pre-mermaid'の設定により、Playwrightのブラウザインストールは不要
  • この問題はCloudflare Pages環境特有の問題で、ローカル環境では発生しない場合がある

これらの対応により、CloudflareでのMermaid図の生成が正常に動作するようになります。

おわりに

外部のプラットフォームを使っていると、様々な問題に直面する。 実績のあるプラットフォームを使う場合でも、ローカルで問題なかったからと安心せずに、きちんとデプロイ完了まで向き合うことが大事であると、初心を思い出させてくれた。

人生とは、生きている限り勉強が続くのだ。

今回の教訓:デプロイは最後まで確認すべし!