HTMLStream APIを使用して、リアルタイムの株式データやチャットレコードなどのプレゼンスポイント (POP) に関するHTMLストリーミングデータを処理できます。 さらに、HTMLStream APIを使用すると、HTMLストリーミングデータをチャンクで送信して、データ送信を高速化できます。
背景情報
エッジルーチンは、さまざまなフロントエンド開発シナリオに最適です。 User-Agentヘッダー、地理的位置、IPアドレスなどの特別なデータがPOPから送信されます。 そのため、POP上でHTMLページのフローをリアルタイムで変更する必要があります。 従来、正規表現は、HTMLページのフローを修正するためのアドホックパーサを作成するために使用される。 しかしながら、この従来のアプローチはエラーを引き起こす可能性があり、ストリーム処理をサポートしない。 parse5やhtmlparser2などのオープンソースのJavaScriptパーサーは、大量のメモリリソースを消費し、システムパフォーマンスを低下させます。 これらの問題に対処するために、Edge RoutineはPOPでのストリーム処理をサポートするパーサーを提供します。 このパーサーを使用して、HTMLコードとページを変更できます。
パーサーはEdgeルーチンで構築されており、web標準に基づいていません。
例:
シナリオ
HTMLページのすべてのアンカータグ
<a/>を変更してhttp://www.taobao.comにリンクする必要がある場合は、エッジルーチンで次のコードを使用します。サンプルコード
async function handleRequest(request) { // 1. In this example, the HTML page that you want to modify is returned. const response = await fetch("http://www.example.com"); // 2. Configure the stream processing-based parser to manage HTML content. The parser supports multiple CSS selectors. // Specify the method for capturing the syntax and register a callback function for rewriting. const htmlStream = new HTMLStream( response.body, // Specify the HTML flow that you want to modify. [[ "a", // The element selector. This specifies that all the anchor tags are selected. { // Register a callback function. The element callback function can be called in the anchor tags or in the element nodes of the Document Object Model (DOM) API. // In the callback function, you can change the event object (e). element: function(e) { // Modify the href attribute. e.setAttribute("href", "http://www.taobao.com"); } } ]]); // 3. Return the modified request to the browser. HTMLStream is a readable stream. // You can use HTMLStream in all scenarios that support ReadableStream. return new Response(htmlStream); } export default { async fetch(request) { return handleRequest(request); } };結果分析
上記のサンプルコードは、HTMLStream APIを使用してHTMLフローをリアルタイムで変更する方法を示しています。 次のセクションでは、HTMLStreamの仕組みについて説明します。
Fetch APIは、要求のフロー式を取得します。 ただし、エッジルーチンは、ネットワーク層から応答本文を取得していない可能性があります。 その結果、データバッファリングによって生じるガーベッジコレクションの頻度が低減される。
HTMLStreamは、TransformStream操作をサポートするフローでもあります。 HTMLStreamがフローを受信した後、HTMLStreamは書き換えコールバック関数を呼び出して、指定されたHTMLページをリアルタイムで変更します。 HTMLページを変更する場合は、HTMLページの生データストリームを取得する必要があります。 次に、前のサンプルコードの手順2で説明したように、作成したHTMLフローに生データストリームを配置できます。
HTMLStreamの最初のパラメータは、HTMLページの生データストリームを表すストリームです。
HTMLStreamの2番目のパラメーターは配列で、リライターのグループを表します。 リライタは、セレクタを含む配列である。 セレクターは、オブジェクトを変更して選択するHTMLコンテンツを指定するために使用されます。 オブジェクトの一部の属性は、コールバック関数として呼び出されます。 前の例の
["a" , {....}]は、要素が2の配列を表すリライターを宣言するために使用されます。 前の例の文字列 "a" は、ドキュメント内のすべてのアンカータグを見つけるために使用される要素セレクタを表します。 前の例のオブジェクトは、コールバックオブジェクトを指定します。 要素セレクターを使用する場合、オブジェクトには次のコールバック関数を含めることができます。要素コールバック関数。 このコールバック関数のシグネチャは関数 (e) です。 このコールバック関数は、要素セレクタによって選択された要素が解析されるときに呼び出されます。commentsコールバック関数。 このコールバック関数のシグネチャは関数 (e) です。 このコールバック関数は、要素内にネストされたコメントが解析されるときに呼び出されます。textコールバック関数。 このコールバック関数のシグネチャは関数 (e) です。 このコールバック関数は、要素内のテキストが解析されるときに呼び出されます。 このコールバック関数は複数回呼び出すことができます。 ストリーム処理により、HTMLStreamは文字列のチャンクを処理している可能性があります。
HTMLStreamに直接応答できます。 ただし、HTMLStreamはデータをバッファリングしません。 parse5およびhtmlparser2とは異なり、HTMLStreamはDOMツリーを生成しないため、処理時間とメモリ消費量が大幅に削減されます。 このように、HTMLStreamは、HTMLコンテンツを解析するときに高いスループットと同時実行性を提供できます。
リライター
リライタは、書き換えたいオブジェクトを登録するために使用されます。 オブジェクトは、2つの要素からなる配列です。
配列の最初の要素は、string型またはnullでなければなりません。
String: 要素またはタグを見つけるために使用される要素セレクタを指定します。
null: リライターがドキュメント全体に適用されることを指定します。
説明ほとんどの場合、文書全体にリライタを適用する必要はありません。 リライターがドキュメント全体に適用されている場合、要素を見つけることはできません。
配列の2番目の要素はJavaScriptオブジェクトでなければなりません。 このオブジェクトは、登録したコールバック関数に返されます。
要素セレクターを使用する場合、このオブジェクトは要素コールバック関数として名前が付けられます。 ドキュメントセレクタを使用する場合、このオブジェクトはドキュメントコールバック関数として名前が付けられます。
HTMLStream操作には、1つ以上のリライターを指定できます。 複数の要素セレクタを指定できますが、ドキュメントセレクタは1つだけです。
要素セレクタの構文
要素セレクタ構文は、CSSセレクタ構文のサブセットです。 要素セレクタのプログラミング言語は、CSSセレクタのプログラミング言語とは異なる場合があります。 次のセクションでは、要素セレクタの構文について説明します。
*: すべての要素またはタグを指定します。div:divという名前のタグを指定します。 この形式で他のタグ名を指定できます。 HTMLとカスタムタグがサポートされています。E#id: Eという名前のタグを指定します。タグのIDはidで指定します。E.Class: Eという名前のタグを指定します。タグのクラスはclassで指定します。E[attr]: Eという名前のタグを指定します。タグの属性は、名前attrを含む。要素属性:
E[attr="a"]: Eという名前のタグを指定します。タグの属性はattrを含み、attrはaに設定される。 値は大文字と小文字を区別します。E[attr ^="a"]: Eという名前のタグを指定します。タグの属性はattrを含み、attrはaに設定される。 値は大文字と小文字を区別しません。E[att r$="a"]: Eという名前のタグを指定します。タグの属性は、値がaで終わるattrを含む。E[attr ^="a"]: Eという名前のタグを指定します。タグの属性は、値がaで始まるattrを含む。E[attr *="a"]: Eという名前のタグを指定します。タグの属性は、値がaを含むattrを含む。E[attr |="a"]: Eという名前のタグを指定します。タグの属性には、値が-で始まり、コンマ (,) で区切られたattrが含まれます。 例: en-ch、en-us。
要素間の順序:
E F: Eという名前の親要素に存在するFという名前のタグを指定します。E > F: 親要素がEというタグであるFというタグを指定します。
E:not(S): Eという名前の要素を指定します。Sは別の要素セレクタである。 要素Eは、セレクタがfalseに設定されている場合にのみ選択できます。
要素セレクタのコールバック関数
次の表に、要素セレクタでサポートされるコールバック関数を示します。
コールバック関数 | 説明 | コールバック関数シグネチャ |
要素 | 選択された要素が完全に解析された後に呼び出される非非同期コールバック関数。 | コールバック関数のシグネチャは関数 (e) です。 この署名は、Elementオブジェクトに保持されます。 詳細については、「要素」をご参照ください。 |
コメント | 選択した要素にコメントがある場合に呼び出される非非同期コールバック関数。 | コールバック関数のシグネチャは関数 (e) です。 この署名は、Commentsオブジェクトに保持されます。 詳細については、「コメント」をご参照ください。 |
text | コールバック関数に返されたテキストが解析されたときに呼び出される非非同期コールバック関数。 | コールバック関数のシグネチャは関数 (e) です。 この署名は、TextChunkオブジェクトに保持されます。 詳細については、「TextChunk」をご参照ください。 説明 このコールバック関数は、複数回呼び出すことができる。 HTMLStreamが生のHTMLデータからテキストのチャンクを読み取るとき、このコールバック関数はチャンクが解析されるたびに呼び出されます。 テキスト全体を表示する場合は、すべてのテキストチャンクをロードしてマージする必要があります。 |
要素セレクタは、前述のコールバック関数をすべて無視できます。 この場合、関連する要素は処理なしで直接印刷されます。 テキストの特定のチャンクを変更する場合は、必要なコールバック関数を登録するだけで済みます。
ドキュメントセレクタ
文書セレクタは、指定された文書を選択するために使用される。 ドキュメントセレクタを使用するには、リライター配列の最初の要素をnullに設定します。 HTMLStream操作では、1つのドキュメントセレクタのみを設定できます。
ドキュメントセレクタのコールバック関数
ドキュメントセレクタのコールバック関数は、要素セレクタのコールバック関数に似ています。 次の表に、ドキュメントセレクタでサポートされるコールバック関数を示します。
コールバック関数 | 説明 | コールバック関数シグネチャ |
doctype | 指定されたドキュメント内のドキュメント型宣言 (DOCTYPE) が解析されるときに呼び出される非非同期コールバック関数。 | コールバック関数のシグネチャは関数 (e) です。 この署名は、Doctypeオブジェクトに保持されます。 詳細については、「Doctype」をご参照ください。 |
コメント | 指定されたドキュメントにコメントがある場合に呼び出される非非同期コールバック関数。 | コールバック関数のシグネチャは関数 (e) です。 この署名は、Commentsオブジェクトに保持されます。 詳細については、「コメント」をご参照ください。 |
text | 指定されたドキュメントにテキストノードがある場合に呼び出される非非同期コールバック関数。 | コールバック関数のシグネチャは関数 (e) です。 この署名は、TextChunkオブジェクトに保持されます。 詳細については、「TextChunk」をご参照ください。 説明 このコールバック関数は、複数回呼び出すことができる。 HTMLStreamが生のHTMLデータからテキストのチャンクを読み取るとき、このコールバック関数はチャンクが解析されるたびに呼び出されます。 テキスト全体を表示する場合は、すべてのテキストチャンクをロードしてマージする必要があります。 |
ドキュメント | 指定されたドキュメントが完全に解析された後に呼び出される非非同期コールバック関数。 このコールバック関数は、HTMLドキュメントの末尾にデバッグ情報などのコンテンツをコメントとして追加します。 この情報はトラブルシューティングに使用できます。 | コールバック関数のシグネチャは関数 (e) です。 この署名は、Docendオブジェクトに保持されます。 詳細については、「Docend」をご参照ください。 |
エラー処理
エッジルーチンは、上記のコールバック関数によってスローされるすべてのJavaScript例外をキャッチします。 一方、HTMLStreamはHTMLストリームの処理を停止し、例外を外部レイヤに伝播します。
reader.readメソッドがJavaScriptでトリガーされると、例外が再びスローされます。
Edge Routineの実行中にHTMLStreamでreader.readメソッドが呼び出された場合、Edge Routineは例外を非表示にします。 たとえば、エッジルーチンがクライアントに応答を返すときに例外が発生した場合、応答は中断され、クライアントは応答の一部のみを受け取ります。 これは、HTMLStreamがデータをストリームとして扱うためです。 この場合、ストリームは、すべてのデータがクライアントに返される前に中断されてもよい。 例外を処理するためにHTMLStreamで使用されるメソッドは、TransformStreamで使用されるメソッドに似ています。 TransformStreamは、データをストリームとして書き込み、読み取りも行います。
コールバックのパラメーター
各コールバック関数は、選択されたHTMLタグまたは他の関連情報を表すオブジェクトを受け取る。 このオブジェクトは、コールバックパラメータとも呼ばれます。 このトピックでは、Element、TextChunk、Commentsなどのコールバックパラメーターについて説明します。
すべてのパラメータをコールバック関数に渡す必要があります。 パラメータのメソッドまたは属性がコールバック関数の外部で呼び出された場合、JavaScript例外がスローされます。 この問題を回避するには、目的のパラメータを他のJavaScriptオブジェクトまたはデータ構造に渡すことができます。
このトピックで説明するメソッドのオプションは、オブジェクトを表します。 オブジェクトのHTML属性をtrueまたはfalseに設定できます。 trueはHTMLコンテンツを指定し、falseはテキストコンテンツを指定します。 HTML属性をfalseに設定すると、HTMLStreamは
html encoding/escaping関数を呼び出します。
要素
定義
このオブジェクトは、Elementコールバック関数が呼び出されたときに返されます。 このオブジェクトは、選択したHTMLタグを表します。
Attributes
tagName(string): タグの名前を指定します。attributes(iterator):[name, value]形式で指定されたすべての属性を見つけるイテレータを返します。removed(bool): 要素を削除するかどうかを指定します。 この属性は読み取り専用です。 remove() メソッドを呼び出して、要素を削除できます。 通常、すでに削除されている要素を無視するようにこの属性を設定する必要があります。namespaceURI: SVGやScript要素などの要素の名前空間URI。 この属性は読み取り専用です。
変更方法
属性の変更
getAttribute(name): 指定された要素の属性名を照会します。
setAttribute(name, value): 指定された要素の属性名を設定し、指定された要素の属性名を変更します。
hasAttribute(name): 指定された要素に属性名が存在するかどうかを照会します。
removeAttribute(name): 指定された要素から属性名を削除します。
説明属性名と値の両方が文字列型である必要があります。
コンテンツの変更
before(data, option): 指定した要素 (要素タグ) の前にコンテンツを挿入します。
after(data, option): 指定した要素 (要素タグ) の後にコンテンツを挿入します。
prepend(data, option): 指定した要素の内容の前 (要素の開始タグの後) に内容を挿入します。 例:
<div>(prepend) | aaaa |(append)</div>append(data, option): 指定した要素の内容の後 (要素の終了タグの前) に内容を挿入します。 例:
<div>(prepend) | aaaa |(append)</div>replace(data, option): タグとネストされたタグを含む要素全体を置き換えます。
setInnerContent(data, option): 要素の内容を指定し、タグと属性を保持します。
remove(): 指定された要素を削除します。 要素が削除されると、削除された属性の値がtrueに変わります。
removeAndKeepContent(): 指定された要素のタグと属性を削除し、コンテンツを保持します。
TextChunk
定義
このオブジェクトは、Textコールバック関数が呼び出されると返されます。 このオブジェクトは、選択したHTMLテキストのチャンクを表します。
Attributes
removed(bool): 要素を削除するかどうかを指定します。 この属性は読み取り専用です。 remove() メソッドを呼び出して、要素を削除できます。 通常、すでに削除されている要素を無視するようにこの属性を設定する必要があります。text(string): テキストの内容を指定します。 この属性は読み取り専用です。 テキストは、テキストのチャンクであってもよい。 文字列が空の場合、テキストの最後のチャンクが返されることを示します。 この場合、テキストのすべてのチャンクをマージできます。lastInTextNode(bool): テキストの最後のチャンクかどうかを指定します。 この属性は読み取り専用です。 この属性の値がtrueの場合、text属性は空の文字列を返します。
変更方法
コンテンツの変更
before(data, option): 指定した要素 (要素タグ) の前にコンテンツを挿入します。
after(data, option): 指定した要素 (要素タグ) の後にコンテンツを挿入します。
replace(data, option): タグとネストされたタグを含む要素全体を置き換えます。
remove(): 指定された要素を削除します。 要素が削除されると、削除された属性の値がtrueに変わります。
Comments
定義
このオブジェクトは、Commentsコールバック関数が呼び出されると返されます。 このオブジェクトは、選択したHTMLコンテンツのコメントを表します。
Attributes
removed(bool): 要素を削除するかどうかを指定します。 この属性は読み取り専用です。 remove() メソッドを呼び出して、要素を削除できます。 通常、すでに削除されている要素を無視するようにこの属性を設定する必要があります。text(string): 既存のコメントまたは既存のコメントを上書きするコメントを指定します。 この属性は読み書き可能です。
変更方法
コンテンツの変更
before(data, option): 指定した要素 (要素タグ) の前にコンテンツを挿入します。
after(data, option): 指定した要素 (要素タグ) の後にコンテンツを挿入します。
replace(data, option): タグとネストされたタグを含む要素全体を置き換えます。
remove(): 指定された要素を削除します。 要素が削除されると、削除された属性の値がtrueに変わります。
Doctype
定義
このオブジェクトは、DOCTYPEコールバック関数が呼び出されると返されます。 このオブジェクトは、選択したHTMLコンテンツのDOCTYPEを表します。
Attributes
name(string): DOCTYPE名を指定します。 この属性はレディ専用です。publicId (文字列): パブリック識別子を返します。 パブリック識別子が存在しない場合、nullの値が返されます。 この属性は読み取り専用です。systemId (文字列): システム識別子を返します。 システム識別子が存在しない場合、nullの値が返されます。 この属性は読み取り専用です。
Docend
定義
このオブジェクトは、Docendコールバック関数が呼び出されると返されます。 このオブジェクトは、HTMLドキュメントの終わりを表します。
変更方法
append(string, option): HTMLドキュメントの末尾にコンテンツを追加します。