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

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 リクエストを行い、そのレスポンスを書き換えトランスフォーマーを通じてパイプします。最後に、書き換えられた本文を含むレスポンスを返します。
HTMLRewritingStream は TransformStream の一種で、Streams API Web 標準の一部です。これには2つの主なメリットがあります。まず、HTML はストリーミング方式で処理されます。ストリーミング方式では、ドキュメント全体が送信されて変換されるのを待つのではなく、ドキュメントが断片的に受信され、処理されてクライアントに送信されます。次に、リライターは TransformStream に基づく既存のパイプラインに適合するため、HTML の書き換えの前または後に実行するカスタムストリーミング変換がある場合は、次のように別の pipeThrough 呼び出しをチェーンするだけで済みます。
body.pipeThrough(aCustomTransformer)
.pipeThrough(htmlRewriter)
.pipeThrough(anotherCustomTransformer); API は、サポートされていない insert_implicit_close オプションと、書き換えられた要素に HTML をテキストとして含めることができる escapeHTML オプションの追加を除いて、 Akamai の html-rewriter インターフェースに従います。実装では、Cloudflare の lol-html Rust クレートを使用して、即座に解析と書き換えを行います。
パフォーマンスベンチマーク:Fastly HTMLRewritingStream vs LinkeDOM
ストリーミングベースの低レイテンシ解析および書き換えインフラストラクチャにより、HTMLRewritingStream は LinkeDOM のような純粋な JS ライブラリを大きく上回る性能を発揮します。以下のグラフは、画像タグの書き換えにかかる処理時間 (ミリ秒単位) とラベル、説明を示しています。

対数軸に注目してください。これは、HTMLRewritingStream の処理時間が LinkedDOM の処理時間の約20倍速いことを示しています。測定は、M3 MacBook Pro でのローカル実行で行われ、平均20回の実行が行われました。
この短いデモでは、ニコラス・ケイジの写真で画像を書き換えており、動作の違いを確認できます (LinkeDOM 実装でより多くの画像数を選択すると、CPU タイムアウトが発生する可能性があることに注意してください)。
結論: Fastly Compute によるエッジでの高性能 HTML 書き換え
Fastly JavaScript SDK の HTML リライター機能は、バージョン 3.35.0 で利用可能になりました。既存の Web 標準に適合する HTML を、人間工学に基づいた高性能な方法で書き換える手段を提供します。ぜひお試しいただき、Compute ワークロードにどのように役立っているかをお知らせください。