ブログに戻る

フォロー&ご登録

Fastly JavaScript SDK を使用した HTML の書き換え

Sy Brand

WebAssembly の Staff Software Engineer

中央にレバーがあり、手がそのレバーを前方に押しているキーボードのイラスト

閲覧者向けにウェブページをカスタマイズするには、他のソースから取得した HTML を書き換える必要があります。例えば他チームが所有するサービスにリクエストを送信し、応答の一部を選択的に変更する必要があるケースが考えられます。あるいは、ページの静的部分をユーザーに近いエッジ側でキャッシュし、リクエストのレイテンシを最小化する物理的な場所でカスタマイズを実行したい場合もあるでしょう。Fastly Compute JavaScript SDK には、ストリーミング HTML リライターが新たに搭載されました。既存の Web 標準に適合する使いやすい API でこれらの目標を達成し、汎用的なサーバーサイド DOM 操作ソリューションを上回るパフォーマンスを発揮します。

HTML リライターは JS SDK バージョン 3.35.0 で利用可能で、ドキュメントは @fastly/js-compute ドキュメントで入手可能です。

HTMLRewritingStream API の仕組み

JS SDK には、CSS セレクターに書き換えコールバックを登録できる HTMLRewritingStream タイプが用意されています。リライターがセレクタに一致する要素を検出すると、登録されたコールバックを呼び出します。このコールバックは要素の属性を操作し、該当要素の周辺のコンテキストからコンテンツを追加または削除することができます。このタイプのインスタンスを作成した後、HTML ストリームをパイプして渡すことができます。例えば、任意の h1 タグの先頭に 「Header:」というテキストを追加し、div タグに属性を追加したい場合は、次のように書くことができます。

/// <reference types="@fastly/js-compute" />

import { HTMLRewritingStream } from 'fastly/html-rewriter';

async function handleRequest(event) {
 let transformer = new HTMLRewritingStream()
   .onElement("h1", e => e.prepend("Header: "))
   .onElement("div", e => e.setAttribute("special-attribute", "top-secret"));
 let body = (await fetch("https://example.com/")).body.pipeThrough(transformer);

 return new Response(body, {
   status: 200,
   headers: new Headers({
     "content-type": "text/html"
   })
 })
}

addEventListener("fetch", (event) => event.respondWith(handleRequest(event)));

2つのコールバック (1つは H1 タグ用、もう1つは div 用) を使用して HTMLRewritingStream を構築します。HTML ページを取得するために HTTP リクエストを行い、そのレスポンスをリライターを通じてパイプします。最後に、書き換えられた本文を含むレスポンスを返します。

HTMLRewritingStreamTransformStream の一種で、Streams API Web 標準の一部です。これには2つの主なメリットがあります。まず、HTML はストリーミング方式で処理されます。ストリーミング方式では、ドキュメント全体が送信されて変換されるのを待つのではなく、ドキュメントが断片的に受信され、処理されてクライアントに送信されます。次に、リライターは TransformStream に基づく既存のパイプラインに適合するため、HTML の書き換えの前または後に実行するカスタムストリーミング変換がある場合は、次のように別の pipeThrough 呼び出しをチェーンするだけで済みます。

body.pipeThrough(aCustomTransformer)
    .pipeThrough(htmlRewriter)
    .pipeThrough(anotherCustomTransformer);

API は、Akamai の html-rewriter インターフェースに準拠しています。ただし insert_implicit_close オプションはサポートされていません。また、書き換え対象の要素に HTML をテキストとして含めることができる escapeHTML オプションが追加されています。実装では、Cloudflare の lol-html Rust クレートを使用して、即座に解析と書き換えを行います。

パフォーマンスベンチマーク : Fastly HTMLRewritingStream vs LinkeDOM

ストリーミングベースの低レイテンシ解析および書き換えインフラストラクチャにより、HTMLRewritingStreamLinkeDOM のような純粋な JS ライブラリを大きく上回る性能を発揮します。以下のグラフは、ラベルと説明を含む画像タグを書き換えた際の処理時間 (ミリ秒単位) を示しています。

対数軸に注目してください。これは、HTMLRewritingStream の処理時間が LinkedDOM と比べて約20倍高速であることを示しています。測定は、M3 MacBook Pro でのローカル実行で行われ、20回の実行結果を平均しています。

この短いデモでは、ニコラス・ケイジの写真を使った画像書き換え処理の違いを確認できます (LinkeDOM 実装では、画像数を多く選択すると、CPU タイムアウトが発生する可能性があることに注意してください)。

結論: Fastly Compute によるエッジでの高性能 HTML 書き換え

Fastly JavaScript SDK の HTML リライター機能は、バージョン 3.35.0 で利用可能になりました。既存の Web 標準に適合した、使いやすく高性能な HTML 書き換え手段を提供します。ぜひお試しいただき、Compute ワークロードでの活用についてお知らせください。

始める準備はできましたか?

ぜひご連絡ください