技術 約26分で読めます

CloudflareがWordPress後継のサーバーレスCMS「EmDash」をベータ公開

いけさん目次

WordPressが誕生して24年。インターネットの40%以上を動かす巨大CMSだが、プラグインのセキュリティ問題は年々深刻化している。Cloudflareが4月2日にベータ公開した EmDash は、この構造的な問題をアーキテクチャごと作り直すことで解決しようとしている。Astro 6.0をベースにしたフルスタックサーバーレスCMSで、MITライセンスのオープンソースだ。

「WordPress後継」と銘打ってはいるが、24年の蓄積があるWordPressとv0.1.0のEmDashでは正面から比べられない領域が多い。逆に、WordPressが構造的に解決できない問題をEmDashがゼロから設計し直している領域もある。両者の強みと弱みを、領域ごとに掘り下げてみた。

全体比較

観点WordPressEmDashどちらが有利か
言語PHPTypeScript用途次第
テーマエンジン独自テンプレート(PHP)Astro 6.0用途次第
データストアMySQL/MariaDBD1(SQLite互換)WordPress(実績)
ホスティングどこでも。月数百円の共用サーバーでも動くCloudflare Workers、またはworkerdが動く環境WordPress(選択肢の広さ)
プラグイン数59,000+エコシステムはこれからWordPress(圧倒的)
テーマ数12,000+(公式ディレクトリ)公式テーマ数本WordPress(圧倒的)
プラグインの隔離なし。フルアクセスV8 isolateで完全分離EmDash(構造的優位)
管理画面成熟。非エンジニアでも扱える基本機能はあるが発展途上WordPress(完成度)
コミュニティ巨大。日本語情報も豊富ほぼゼロからのスタートWordPress(圧倒的)
ライセンスGPLv2MITEmDash(自由度)
初期コスト無料〜月数百円Cloudflare無料枠で動作可能互角
スケーラビリティサーバー増強やCDNが別途必要エッジで動作、オートスケールEmDash
認証パスワード(2FAはプラグイン)パスキー標準EmDash
コンテンツ課金WooCommerce等プラグインで対応x402ビルトインEmDash(手軽さ)
AIエージェント連携REST API(後付け)MCPサーバー内蔵EmDash
多言語対応プラグインで対応(WPML、Polylang等。成熟)Astro i18n + エッジルーティング(組み込み)用途次第

EmDashが勝っている項目はアーキテクチャに由来するもので、WordPressが後から追いつくのは構造的に難しい。WordPressが勝っている項目はエコシステムの厚さに由来するもので、EmDashが追いつくには数年単位の時間がかかる。どちらの差も簡単には埋まらない。

EmDashが構造的に勝つ領域

WordPressのプラグインセキュリティ問題

WordPressのプラグインは、インストールした瞬間にサイトのデータベースとファイルシステムへのフルアクセスを手にする。サンドボックスも権限分離もない。PHPの add_actionadd_filter でWordPressのあらゆるフックに割り込めるし、$wpdb 経由で生SQLも実行できる。つまりプラグインを1つ入れるとは、見知らぬ開発者にサーバーのrootを渡すのに近い行為だった。

graph LR
    subgraph WordPressのプラグインモデル
        P[プラグイン] -->|add_action/add_filter| H[全フック]
        P -->|$wpdb| DB[(MySQL)]
        P -->|file_get_contents等| FS[ファイルシステム]
        P -->|wp_remote_get等| NET[外部ネットワーク]
    end

この設計が生んだ被害は数字に表れている。

指標数値
2025年のWordPressエコシステム新規脆弱性10,794件(1日平均30件)
脆弱性の発生源がプラグイン96%
認証なしで悪用可能な脆弱性43%以上
高深刻度の脆弱性(2025年)過去2年の合計を超過
脆弱性を知りながら修正しなかった開発者52%

Patchstackのレポートによると、2026年のCVE総数は前年比15%増の約55,000件に達する見込みで、WordPress.orgのプラグイン審査キューは800件以上が滞留し、処理に最低2週間かかっている。

ただし、この数字だけでWordPressが危険だと断じるのはフェアではない。59,000以上のプラグインがあれば脆弱性の総数が多くなるのは当然だ。問題は「1つの脆弱なプラグインがサイト全体を危険にさらす」というアーキテクチャにある。そしてこの問題はWordPressが後付けで解決するのが極めて難しい。PHPの同一プロセスでプラグインを実行するモデルは、WordPressの根幹に組み込まれているからだ。

EmDashは各プラグインをDynamic Workerと呼ばれる独立したV8 isolateの中で実行する。

V8 isolateとは

V8はGoogle ChromeやNode.jsが使うJavaScriptエンジンで、isolate(アイソレート)はその中の独立した実行環境を指す。各isolateは自分のヒープメモリを持ち、他のisolateのメモリには一切アクセスできない。Dockerコンテナのような仮想化とは異なり、OSレベルの仮想化オーバーヘッドがないため起動がミリ秒単位で完了する。Cloudflareの公称ではコンテナ比100倍高速だ。

隔離モデルの比較

観点WordPressEmDash
プラグインの実行環境PHPの同一プロセス内プラグインごとに独立したV8 isolate
メモリ空間共有(他のプラグインのメモリを読める)完全分離
DB操作$wpdb で生SQL実行可能API経由のみ。生SQLは書けない
ファイルシステムフルアクセスアクセス不可
ネットワーク制限なし明示的にホスト名を許可しない限り不可
権限モデル全権委任(インストール=フルアクセス)ケーパビリティベース(宣言した権限のみ付与)
脆弱なプラグインの影響範囲サイト全体(DB、ファイル、他プラグイン)そのプラグインに付与された権限の範囲内

WordPressでは、1つのプラグインが侵害されるとサイト全体のデータベース、ファイルシステム、他のプラグイン、さらには同一サーバー上の他サイトまで危険にさらす。EmDashでは、最悪の場合でもそのプラグインに付与された権限の範囲内で被害が止まる。

Cloudflare Workersのセキュリティモデルは多層防御になっている。

レイヤー保護内容
V8 isolateメモリ空間の完全分離
プロセスサンドボックスLinuxネームスペース + seccompでファイルシステム・ネットワークを遮断
コードン分離信頼レベル別にWorkerをプロセスグループに分離(Freeプランとエンタープライズは同居しない)
ハードウェア保護ランダムなメモリ保護キーでヒープデータを保護(バグがあっても92%の確率でハードウェアトラップ)
タイミング攻撃対策コード実行中は Date.now() を固定値に。マルチスレッドも提供しないためサイドチャネル攻撃を構造的に排除

WordPressにこれと同等の防御を後付けするのは、言語レベルの制約から事実上不可能だ。PHPのプロセスモデルでは、プラグイン間のメモリ分離もファイルシステムの隔離も実現できない。WAFやMalware Scannerで外側から守ることはできるが、プラグインが内側から暴れることを防ぐ手段はない。

ケーパビリティベースのアクセス制御

EmDashのプラグインは、マニフェストで宣言したケーパビリティ(権限)だけがbinding経由で注入される。データベースやファイルシステムへの直接アクセスは存在しない。

import { definePlugin } from "emdash";

export default () => definePlugin({
  id: "notify-on-publish",
  version: "1.0.0",
  capabilities: ["read:content", "email:send"],
  hooks: {
    "content:afterSave": async (event, ctx) => {
      // ctx にはread:contentとemail:sendの
      // ケーパビリティだけがbindingされている
      // DBへの直接アクセスやネットワーク接続は不可能
    }
  }
});

WordPressのプラグインがインストール時に「何ができるか」をユーザーに明示する仕組みは存在しない。Androidアプリがインストール時にパーミッションを要求するのと対照的に、WordPressプラグインは黙って全権を手にする。EmDashのケーパビリティモデルはAndroidのパーミッションに近く、ユーザーが何を許可しているのかが明確になる。

ただし、ケーパビリティベースのモデルにも限界はある。read:content の権限を持つプラグインは、そのスコープ内のコンテンツすべてを読める。「この記事だけ」「このフィールドだけ」といった粒度の制御がどこまで可能かは、ベータ段階の現時点ではドキュメントが不十分で判断しづらい。

graph LR
    subgraph WordPress
        WP_Plugin[プラグイン] -->|フルアクセス| WP_DB[(データベース)]
        WP_Plugin -->|フルアクセス| WP_FS[ファイルシステム]
        WP_Plugin -->|制限なし| WP_Net[外部ネットワーク]
    end
    subgraph EmDash
        ED_Plugin[プラグイン<br/>Dynamic Worker] -->|read:content のみ| ED_DB[(D1)]
        ED_Plugin -->|email:send のみ| ED_Email[メール送信API]
        ED_Plugin -.-x|アクセス不可| ED_FS[ファイルシステム]
        ED_Plugin -.-x|アクセス不可| ED_Net[外部ネットワーク]
    end

パフォーマンスとスケーラビリティ

WordPressはPHP + MySQLのクラシックなサーバーサイドアーキテクチャだ。リクエストのたびにPHPがHTML全体を生成し、MySQLにクエリを投げる。高速化にはページキャッシュプラグイン、CDN、場合によってはVarnishやRedisといったインフラ層の追加が必要になる。

EmDashはCloudflare Workersで動作し、リクエストはユーザーに最も近いエッジロケーションで処理される。キャッシュ層もCDNも別途構築する必要がない。データストアのD1もエッジに配置されるため、DBクエリのレイテンシも小さい。

graph TD
    A[ブラウザ] -->|リクエスト| B[Cloudflare Workers<br/>EmDashコア]
    B --> C[Astro 6.0<br/>テーマエンジン]
    B --> D[D1<br/>SQLite互換DB]
    B --> E[R2<br/>メディアストレージ]
    B -->|capability binding| F[Dynamic Worker<br/>プラグインA]
    B -->|capability binding| G[Dynamic Worker<br/>プラグインB]
    F -.->|許可された操作のみ| D
    G -.->|許可された操作のみ| E
観点WordPressEmDash
実行環境オリジンサーバーエッジ(世界300+ロケーション)
スケールアップサーバー増強、ロードバランサー追加自動(Workers基盤が処理)
スケールダウンサーバーは動き続ける(固定コスト)リクエストゼロならコストゼロ
キャッシュプラグイン+CDNで構築エッジキャッシュが標準
DB接続オリジンからMySQLへのTCP接続エッジからD1へのローカルアクセス
Cold startPHPプロセス起動(数百ms)V8 isolate起動(数ms)

WordPressはトラフィックが急増するとサーバーが落ちる。ニュースサイトがバズった時に503を返すのは日常茶飯事で、対策にはインフラエンジニアの手が必要だ。EmDashはCloudflareの基盤に乗っている限り、スパイクに対して構造的に耐性がある。

ただし、WordPressのパフォーマンス問題はプラグインで十分に実用レベルまで解決できるケースが多い。WP RocketやCloudflare APOを使えば、静的サイト並みの速度は出る。「パフォーマンスのためにCMSを乗り換える」ほどの差が出るかは、サイトの規模と要件次第だ。

デフォルト認証の堅さの違い

観点WordPressEmDash
デフォルト認証パスワードパスキー(パスワードレス)
2FAプラグインで追加不要(パスキーが多要素認証を兼ねる)
SSO連携プラグインで対応(SAML/OIDC/LDAP)プラグインで対応(IdPメタデータ自動プロビジョニング)
パスワードDB存在する(bcryptハッシュ)存在しない

EmDashはパスワードの保存そのものがない。パスワードが存在しなければ、パスワードリスト攻撃もブルートフォースも成立しない。WordPress側はデフォルトがパスワード認証で、2FAの導入はサイト管理者の判断に委ねられている。ロールはどちらもadministrator、editor、author、contributorの4段階。

ただしWordPressの認証プラグインは十分に成熟していて、miniOrangeやWP SAML Authなどのプラグインでエンタープライズ級のSSO環境を構築できる。Active DirectoryやLDAPとの統合も実績が豊富だ。EmDashのSSO連携はこれから検証が進む段階で、エンタープライズ要件を満たせるかは未知数。

パスワードDBなしで認証できる仕組み

「パスワードDBが存在しない」と書いたが、サーバー側に何も保存しないわけではない。パスキー(FIDO2/WebAuthn)は公開鍵暗号を使った認証方式で、サーバーが保存するのはパスワードハッシュではなく公開鍵だ。

登録時の流れはこうなる。

  1. サーバーがチャレンジ(ランダムな値)を生成してブラウザに送る
  2. ブラウザが認証器(デバイスのセキュリティチップやUSBキー)に鍵ペアの生成を要求
  3. ユーザーが生体認証(指紋・顔)またはPINで本人確認
  4. 認証器が秘密鍵と公開鍵のペアを生成し、秘密鍵はデバイス内に保持
  5. 公開鍵とクレデンシャルIDをサーバーに送信し、サーバーはこれだけを保存

ログイン時は、サーバーがチャレンジを送り、デバイスの秘密鍵で署名し、サーバーが公開鍵で署名を検証する。パスワードのやり取りは一切発生しない。

sequenceDiagram
    participant U as ユーザー
    participant B as ブラウザ
    participant A as 認証器<br/>(セキュリティチップ)
    participant S as EmDashサーバー

    Note over U,S: 登録フロー
    B->>S: 登録リクエスト
    S->>B: チャレンジ + サーバー情報
    B->>A: 鍵ペア生成要求
    U->>A: 生体認証 or PIN
    A->>A: 秘密鍵・公開鍵ペア生成
    A->>B: 公開鍵 + クレデンシャルID + 署名
    B->>S: 公開鍵 + クレデンシャルID + 署名
    S->>S: 公開鍵を保存(パスワードは保存しない)

    Note over U,S: 認証フロー
    B->>S: ログインリクエスト
    S->>B: チャレンジ + クレデンシャルID
    B->>A: 署名要求
    U->>A: 生体認証 or PIN
    A->>A: 秘密鍵でチャレンジに署名
    A->>B: 署名データ
    B->>S: 署名データ
    S->>S: 保存済み公開鍵で署名を検証

ポイントは、公開鍵が漏洩してもセキュリティ上の問題にならないこと。公開鍵から秘密鍵を逆算することは計算量的に不可能なので、パスワードハッシュの漏洩とはリスクの性質が根本的に異なる。

漏洩した場合パスワードDBパスキーの公開鍵DB
オフライン総当たり攻撃可能(弱いパスワードは数秒で解読)不可能(公開鍵から秘密鍵は導出できない)
クレデンシャルスタッフィング可能(使い回しパスワードで他サイトに侵入)不可能(鍵ペアはサイトごとに一意)
フィッシング有効(偽サイトでパスワードを入力させる)無効(認証器がオリジンを検証し、偽サイトでは署名しない)
DB漏洩後の対応全ユーザーにパスワード変更を強制対応不要(公開鍵だけでは認証できない)

パスキーが「多要素認証を兼ねる」のもこの仕組みによる。認証に必要なのはデバイスの所持(所有要素)と生体認証またはPIN(知識/生体要素)の2つ。1回の操作で2要素認証が完了するため、WordPressで2FAプラグインを別途導入する手間がそもそも要らない。

コンテンツ課金

EmDashはx402という「インターネットネイティブな決済の標準規格」をビルトインでサポートしている。コンテンツに価格とウォレットアドレスを設定するだけで、記事単位の従量課金が実装できる。エンジニアリング作業はゼロだとCloudflareは主張している。

WordPressで同等のことをやるにはWooCommerce + MemberPressの組み合わせが必要になる。決済プロバイダの契約、Stripeの設定、Webhookの構築、会員管理プラグインの導入と設定。動くようになるまでに数日から数週間かかる。しかもプラグイン間の互換性問題が頻繁に発生する。

一方で、WordPressのEC/課金プラグイン群は多様なビジネスモデルに対応できる。月額サブスクリプション、従量課金、クーポン、アフィリエイト、物理商品との統合。x402は記事単位の課金には向いているが、複雑な販売フローには対応しきれない可能性がある。

AIエージェント連携

各EmDashインスタンスにはModel Context Protocol(MCP)サーバーが内蔵されている。EmDash CLIからメディアアップロード、コンテンツ検索、スキーマ管理などをプログラマティックに操作でき、AIエージェントとの統合を前提にした設計だ。

プラグイン作成やテーマ移行のためのAgent Skillも用意されており、「Block Kit Agent Skill」でWordPressのブロックをEmDash向けに変換できる。

WordPressにもREST APIはあるが、後付けで追加されたもので、認証の設定やプラグインとの競合に悩まされることがある。MCPサーバーがビルトインという設計は、2026年のCMS選定基準として「AIエージェントとの親和性」を重視するなら、EmDashの明確なアドバンテージだ。

テーマ開発: PHP vs Astro

EmDashのテーマはAstroプロジェクトそのものだ。Pages、Layouts、Components、Styles、そしてSeedファイル(コンテンツタイプとフィールドを定義するJSON)で構成される。テーマにもデータベース操作の権限がない。コンテンツの取得はEmDashが提供するAPIを通じて行い、生SQLを書く余地がない。テーマとプラグインの両方でデータベースへの直接アクセスを排除することで、SQLインジェクションの攻撃面を構造的にゼロにしている。

WordPressのテーマはPHPファイルなので、テーマ内で $wpdb->query() を呼ぶことも、file_get_contents() で外部にリクエストを飛ばすこともできてしまう。実際、WordPress.orgのテーマディレクトリでもマルウェアを含むテーマが定期的に発見されている。EmDashではこの攻撃経路自体が存在しない。

観点WordPress テーマEmDash テーマ
言語PHP(テンプレートタグ)Astro + TypeScript
カスタマイズテーマカスタマイザー(GUI)コード編集(CLI/エディタ)
テーマストア12,000+(無料/有料)公式数本(これから)
DB操作可能(生SQL含む)不可能(API経由のみ)
セキュリティリスクテーマ経由のマルウェアが存在攻撃面がない
学習コストPHPの基礎でOKフロントエンド開発の知識が必要
ノーコード対応テーマカスタマイザー、Gutenbergなし

開発者にとってはAstro + TypeScriptのほうがモダンで書きやすいが、非エンジニアにとってはWordPressのテーマカスタマイザーやGutenbergのほうが圧倒的にアクセスしやすい。この差は技術の問題ではなく、ターゲットユーザーの違いだ。

WordPressが明確に勝つ領域

エコシステムの厚み

59,000以上のプラグインと12,000以上のテーマ。何かやりたいことがあれば、だいたい既存プラグインで解決する。ECサイトならWooCommerce、SEOならYoast SEO、フォームならContact Form 7、バックアップならUpdraftPlus。それぞれのプラグインに専門の開発者コミュニティがあり、ドキュメントもチュートリアルも豊富だ。

EmDashのプラグインエコシステムは文字通りゼロからのスタートだ。SEOプラグイン、フォームビルダー、バックアップツール、メール配信連携。WordPressで当たり前に使えるものの多くが、EmDashではまだ存在しないか、自分で作る必要がある。

非エンジニアの運用性

WordPressは20年以上かけて「ITに詳しくない人でも使えるCMS」としての地位を確立してきた。管理画面はブラウザだけで完結し、記事の投稿、画像のアップロード、テーマの変更、プラグインのインストールまでGUIで行える。Gutenbergエディタのブロックベースの編集は、Notionライクな体験に近づいている。

EmDashの管理画面は機能的に必要最低限で、ターゲットが明らかにエンジニア寄りだ。テーマのカスタマイズにはコードを書く必要があるし、プラグイン開発もTypeScriptの知識が前提になる。「ブログを書きたいだけの人」にとって、EmDashは過剰に技術的だ。

ホスティングの自由度

WordPressは月額数百円のレンタルサーバーから、AWS上のエンタープライズ構成まで、あらゆる環境で動く。さくらインターネット、エックスサーバー、ロリポップ。日本のレンタルサーバーのほとんどがWordPressのワンクリックインストールに対応している。自社サーバーに置くこともクラウドに置くこともできるし、サーバーの引っ越しも確立された手順がある。

EmDashの最適な実行環境はCloudflare Workersだ。workerd(Cloudflare Workersのオープンソースランタイム)を使えば他の環境でも動作するとされているが、現時点でworkerdでのセルフホスティングの実績はほぼない。実質的にCloudflareに依存する運用になりやすく、Cloudflareのサービス変更や価格改定の影響を直接受ける。ベンダーロックインとまでは言えないが、WordPress比で選択肢は大幅に狭い。

情報量とコミュニティ

WordPressで困ったことがあれば、検索すればほぼ確実に日本語の解決策が見つかる。Stack Overflow、Qiita、Zenn、個人ブログ。日本語の書籍も数十冊は出ている。WordPressの開発者を雇うのも簡単で、PHPとWordPressの経験者は世界中にいる。

EmDashで困ったら、現時点では公式ドキュメントとGitHubのIssueしか頼るものがない。日本語の情報はゼロに等しい。開発者の採用も難しく、「EmDash経験者」という人材はまだ存在しない。

既存資産と業務フロー

WordPressで構築された数億のサイトが存在し、それぞれにカスタマイズされたテーマ、プラグイン設定、運用フローが確立されている。移行ツールがあっても、業務フローの再構築コストは技術的な移行コストより大きい。

WooCommerceで構築したECサイト、bbPressで動いているフォーラム、LearnDashで作ったオンラインコース。プラグインに依存した複雑なサイトほど移行のハードルは高い。EmDashのプラグインエコシステムがこれらをカバーするには年単位の時間がかかる。

WordPressからの移行

WordPress管理画面からWXRファイル(WordPress eXtended RSS)をエクスポートしてインポートする方法と、EmDash Exporterプラグインをインストールしてセキュアなエンドポイント経由で移行する方法の2つが用意されている。後者はWordPressのアプリケーションパスワードで保護され、メディアファイルの自動移行にも対応する。移行にかかる時間は「数分」とのこと。

カスタム投稿タイプはEmDashのCollectionsに変換される。WordPressテーマの移行には wordpress-theme-to-emdash というAgent Skillが用意されている。

コンテンツの移行は比較的容易だが、テーマのルック&フィールの再現とプラグイン機能の置き換えが本当のボトルネックになる。シンプルなブログなら「数分」で移行できるだろうが、プラグインを10個以上使っているサイトでは、移行プロジェクト自体が数週間かかる可能性がある。

v0.1.0ベータの中身

現在のバージョンはv0.1.0プレビューベータ。npm create emdash@latest で即座にセットアップでき、Cloudflareへのワンクリックデプロイボタンも提供されている。管理画面を試すだけならemdashcms.comのPlaygroundがある。GitHubリポジトリはemdash-cms/emdashで、MITライセンス。

Cloudflareはここ数ヶ月、Workers上で動くプラットフォームを矢継ぎ早に出している。VoidZeroのViteネイティブデプロイプラットフォームvinextによるNext.jsの再実装、そしてWorkers上のリアルタイム分析基盤。EmDashはこの流れの延長にある。

Webサイトにサードパーティスクリプトが仕込む脅威については、Cloudflareが先日公開したClient-Side SecurityのGNN+LLM検出でも取り上げた。EmDashはそもそもプラグインが悪事を働けないアーキテクチャにすることで、問題の根を断とうとしている。

多言語対応

最近のWebサイトは多言語対応を求められる場面が増えている。越境ECやグローバル企業のコーポレートサイトはもちろん、個人ブログでも英語版を用意するケースが珍しくなくなった。WordPressとEmDashでは、多言語化のアプローチが根本的に異なる。

WordPressの多言語対応

WordPress本体には多言語機能がない。多言語化にはWPML、Polylang、TranslatePressといったプラグインを導入する必要がある。

プラグイン方式価格特徴
WPML投稿を言語ごとに複製有料($39〜/年)最も普及。WooCommerceとの統合が強い
Polylang投稿を言語ごとに複製無料版ありWPMLより軽量。無料で始められる
TranslatePressフロントエンドから翻訳を編集無料版あり見た目を確認しながら翻訳できる
MultilingualPressマルチサイトで言語ごとにサイトを分離有料エンタープライズ向け。サイト間の独立性が高い

WPMLとPolylangは「投稿を言語ごとに複製する」方式で、日本語の記事と英語の記事が別々の投稿として管理される。記事数が2倍、3倍に膨れ上がり、管理が煩雑になる。言語スイッチャーの配置、hreflangタグの出力、URL構造の設定(サブディレクトリ /en/ かサブドメイン en.example.com か)まで、プラグインの設定項目は多い。

さらに、多言語プラグインは他のプラグインとの互換性問題が発生しやすい。キャッシュプラグインが言語別のページをキャッシュし損ねたり、SEOプラグインが正しいhreflangを出力しなかったり、ECプラグインの商品ページの翻訳でフィールドが欠落したり。プラグイン同士の組み合わせが爆発的に増えるため、トラブルシューティングに時間を取られがちだ。

ただし、これらのプラグインは10年以上の実績があり、翻訳メモリ、翻訳者ロール管理、翻訳進捗トラッキング、外部翻訳サービス(DeepL、Google翻訳)との統合など、業務で必要な機能は一通り揃っている。大規模な多言語サイトの運用ノウハウも蓄積されている。

EmDashの多言語対応

EmDashはAstro 6.0のビルトインi18nルーティングをベースにしている。Astroのi18n機能はフレームワークレベルで言語別ルーティングをサポートしており、プラグインの後付けではなく設計に組み込まれている。

// astro.config.ts(EmDashテーマ側の設定)
export default defineConfig({
  i18n: {
    defaultLocale: "ja",
    locales: ["ja", "en", "zh-hans", "ko"],
    routing: {
      prefixDefaultLocale: false
      // ja: /articles/slug
      // en: /en/articles/slug
    }
  }
});

Cloudflare Workersで動作する利点が大きいのは、ロケール検出とコンテンツ振り分けの部分だ。

graph TD
    A[ブラウザ] -->|リクエスト| B[Cloudflare Workers<br/>エッジロケーション]
    B -->|Accept-Language<br/>CF-IPCountry| C{ロケール判定}
    C -->|ja| D[日本語コンテンツ]
    C -->|en| E[英語コンテンツ]
    C -->|zh-hans| F[中国語コンテンツ]
    D --> G[D1から取得<br/>エッジキャッシュ]
    E --> G
    F --> G

WordPressの多言語プラグインはオリジンサーバーでロケール判定を行い、該当する言語の投稿をMySQLから取得する。EmDashではCloudflare Workersがエッジでロケールを判定し、D1から言語別コンテンツを返す。リクエストがオリジンに到達する前にすべてが完結するため、多言語サイト特有の「言語判定 → リダイレクト → コンテンツ取得」のレイテンシが構造的に小さい。

D1のコンテンツスキーマでは、翻訳がCollectionsのフィールドとして管理される。投稿を言語数だけ複製するWordPressの方式と異なり、1つのコンテンツエントリに複数言語のフィールドが紐づく。

観点WordPressEmDash
多言語の実装プラグイン(後付け)フレームワーク組み込み
コンテンツ構造言語ごとに投稿を複製1エントリに複数言語フィールド
URL構造プラグインの設定に依存Astro i18nルーティング
ロケール検出オリジンサーバーで処理エッジで処理
hreflangタグプラグインが出力フレームワークが自動出力
翻訳管理翻訳メモリ、進捗管理、翻訳者ロール基本的なフィールド管理のみ
機械翻訳連携DeepL、Google翻訳プラグインありAPI経由で可能だが公式統合はまだ
RTL対応プラグインで対応可能Astroのdir属性で対応
実績数百万の多言語サイトが稼働中ベータ段階

EmDashのアーキテクチャ的な優位性は明確だが、翻訳ワークフローの成熟度ではWordPressに大きく差をつけられている。翻訳メモリ(過去の翻訳を再利用して一貫性を保つ仕組み)、翻訳者ごとのロール管理、翻訳の進捗トラッキング、翻訳エージェンシーとの連携。企業の多言語サイト運用で必要になるこれらの機能は、EmDashでは未整備だ。

個人ブログや小規模サイトなら、EmDashのフレームワーク組み込み方式のほうがシンプルで扱いやすい。プラグインの互換性を気にする必要がなく、エッジでの高速な言語振り分けが最初から使える。一方、50言語対応の企業サイトや、翻訳者チームが並行作業する大規模プロジェクトでは、WordPressの翻訳プラグイン群が提供するワークフロー支援が不可欠になる。

URL構造とルーティング

業務でCMSを使う場合、ドメイン構成やパーマリンク(URL構造)のカスタマイズは避けて通れない。SEOの都合でURLにカテゴリを含めたい、リダイレクトルールを細かく制御したい、サブディレクトリ配下に設置したい。WordPressではこのあたりを functions.php で柔軟にいじれるのが強みだった。

WordPressのURL制御

WordPressのパーマリンク設定は管理画面のGUIでも変更できるが、業務レベルのカスタマイズは functions.php でRewrite APIを叩くことになる。

// functions.php: カスタム投稿タイプのURLを /news/slug/ にする
function custom_news_rewrite() {
    add_rewrite_rule(
        '^news/([^/]+)/?$',
        'index.php?post_type=news&name=$matches[1]',
        'top'
    );
}
add_action('init', 'custom_news_rewrite');

// パーマリンク構造を /%category%/%postname%/ に変更
function custom_permalink_structure() {
    global $wp_rewrite;
    $wp_rewrite->set_permalink_structure('/%category%/%postname%/');
}

.htaccess(Apache)や nginx.conf でのリダイレクトルール追加、add_rewrite_tag によるカスタムクエリ変数の登録、template_redirect フックでの条件分岐リダイレクトなど、PHPレベルで何でもできる。20年分のStack Overflowの回答が蓄積されているので、やりたいことを検索すればほぼ確実にコード片が見つかる。

EmDashのURL制御

EmDashはAstro 6.0ベースなので、ルーティングもAstroの仕組みに従う。Astroのルーティングはファイルベースで、src/pages/ ディレクトリのファイル構造がそのままURLになる。TypeScriptで書ける。

src/pages/
├── index.astro          → /
├── about.astro          → /about
├── articles/
│   └── [slug].astro     → /articles/any-slug
└── [lang]/
    └── articles/
        └── [slug].astro → /en/articles/any-slug

動的ルーティングは [slug].astro[...path].astro(キャッチオール)で実現する。getStaticPaths() で生成するパスを制御できるため、カテゴリ付きURLも表現可能だ。

// src/pages/[category]/[slug].astro
export async function getStaticPaths() {
  const posts = await getCollection("posts");
  return posts.map((post) => ({
    params: {
      category: post.data.category,
      slug: post.slug,
    },
    props: { post },
  }));
}
// → /tech/my-article, /diary/my-diary のようなURLが生成される

リダイレクトは astro.config.ts で宣言的に書ける。

// astro.config.ts
export default defineConfig({
  redirects: {
    "/old-path": "/new-path",
    "/blog/[...slug]": "/articles/[...slug]",
  },
});

WordPressの functions.php + Rewrite APIに相当する柔軟性は、Astroのファイルベースルーティング + astro.config.ts + ミドルウェアの組み合わせでカバーできる。ミドルウェアを使えばリクエストの前処理(認証チェック、リダイレクト、ヘッダー操作)もTypeScriptで書ける。

// src/middleware.ts
import { defineMiddleware } from "astro:middleware";

export const onRequest = defineMiddleware(async (context, next) => {
  const url = new URL(context.request.url);
  
  // /old-blog/* を /articles/* にリダイレクト
  if (url.pathname.startsWith("/old-blog/")) {
    const newPath = url.pathname.replace("/old-blog/", "/articles/");
    return context.redirect(newPath, 301);
  }
  
  return next();
});

URL制御の比較

観点WordPressEmDash (Astro)
パーマリンク設定GUI + functions.phpastro.config.ts + ファイル構造
動的ルーティングRewrite API(正規表現)[slug].astro(ファイルベース)
リダイレクト.htaccess / functions.phpastro.config.ts / ミドルウェア
ミドルウェアフックシステム(actions/filters)src/middleware.ts(TypeScript)
サブディレクトリ配置site_url / home_url 設定base オプション
カスタムクエリ変数add_rewrite_tagURLパラメータ / Astro.url.searchParams
言語PHPTypeScript
情報量膨大(20年分の事例)Astro公式ドキュメント中心

「TypeScriptでルーティングを書けるのか?」という疑問に対する答えはイエスだ。むしろAstroのファイルベースルーティングはWordPressのRewrite APIより直感的で、正規表現地獄に陥りにくい。ミドルウェアの仕組みも functions.php のフックシステムより見通しが良い。

ただし、EmDashのルーティングがCloudflare Workers上でどこまで自由に動くかは別の話だ。Astro単体なら何でもできるが、EmDashはプラグインとテーマのサンドボックス化を優先している。テーマ側のルーティングに制約がかかっている可能性はある。ベータ段階ではこのあたりのドキュメントが薄く、実際に試してみないとわからない部分が多い。

WordPress側のRewrite APIは強力だが、内部的にはすべてのルールが wp_options テーブルに rewrite_rules として保存され、リクエストのたびにマッチングが走る。ルールが増えるほどパフォーマンスに影響する設計で、大規模サイトでは flush_rewrite_rules() のタイミングに気を遣う必要がある。EmDash(Astro)のファイルベースルーティングはビルド時に解決されるため、ランタイムのオーバーヘッドがない。

WordPressの24年

記事の冒頭で「24年」と書いたが、この数字の重みを簡単に振り返っておく。

2003年、当時19歳のMatt MullenwegがMike Littleと共にb2/cafelogというPHP製ブログツールをフォークして作ったのがWordPressの始まりだ。当初は個人ブログ用の小さなツールに過ぎなかった。

ver出来事
20030.70b2/cafelogからフォークして誕生
20041.2プラグインAPIを導入。エコシステムの起点
20051.5テーマシステム導入。同年Automattic社設立
20052.0WYSIWYGエディタ搭載
20082.5管理画面の大幅リデザイン
20103.0カスタム投稿タイプ追加。「ブログ」から「CMS」への転換点
2011WooCommerce登場。ECプラットフォームとしても確立
20154.4REST APIをコアに統合
20185.0Gutenbergブロックエディタ導入。コミュニティを二分する論争に
20246.xMullenweg vs WP Engine紛争。ガバナンス問題が表面化
20266.8+Webの40%超を占有。年間脆弱性報告は1万件超

転換点は2010年のWordPress 3.0だ。カスタム投稿タイプの導入で、ブログ以外の用途(ECサイト、企業サイト、ポートフォリオ、不動産サイト)にWordPressが使われ始めた。翌2011年にWooCommerceが登場し、WordPressはEC基盤としても定着した。

2018年のGutenberg導入は最も物議を醸した変更だった。クラシックエディタからブロックベースの編集に強制移行する方針に「既存のワークフローが壊れる」と猛反発が起き、旧エディタを復元するClassic Editorプラグインのインストール数は500万を超えた。今でも現役だ。

2024年にはWordPressの創始者MullenwegがWP Engineを公の場で批判し、WordPress.orgのプラグインディレクトリからWP Engine関連プラグインへのアクセスを一時遮断した。オープンソースのガバナンスと商業利用の境界について、コミュニティ全体の議論に発展した。

24年かけて築いたエコシステムは、技術的には負債を抱えている。PHPのプロセスモデルに由来するセキュリティの構造的問題はこの記事で述べた通りだ。しかしその負債の上に、59,000のプラグインと12,000のテーマ、何百万人もの開発者、そして数えきれないビジネスが乗っている。EmDashが「技術的に正しいアーキテクチャ」で挑むのは、この積み上げだ。


このブログがAstro製なので、EmDashがAstro 6.0ベースというだけで気になって調べた。プラグインサンドボックスの設計は筋が通っていて、WordPressが20年抱えてきた問題への回答としては説得力がある。v0.1.0でどこまで実用に耐えるかは別だが、気が向いたら触ってみたい。