ページ速度の最適化:JavaScript対HTMLを使用してDOMへの書き込み
-
29-10-2019 - |
質問
ページの速度とコードの最適化に関する質問があります。 AJAXコールを通じてほぼ100%入力されているページがあります。私の質問は、ページのHTMLにいくつかの空のdiv、スパンなどをコーディングし、JavaScriptを使用してそれらの要素を入力する方が速いですか?または、これらの要素をJavaScriptに作成して挿入して追加する方が速いですか?大きな違いがあるかどうかはわかりません。したがって、この分野のヘルプ/アドバイスは大歓迎です。
解決
数年前、私はこれについて実験をしました。に割り当てる方がはるかに高速です innerHTML
繰り返し使用するよりも複雑な構造を作成する要素の特性 createElement
appendChild
insertBefore
コールなど。私はそれについて私がした投稿を掘りました(プロトタイプとscript.aculo.usメーリングリストに)。下。
HTMLを解析してレンダリングすることを忘れないでください 早く は ブラウザがすること, 、そして彼らはそれを行うために高度に最適化されています。複雑なHTML構造を持つ文字列をコンテナ要素に割り当てる場合 innerHTML
プロパティ、あなたは作っています 1 JavaScriptレイヤーからブラウザのレンダリングレイヤーへのトリップ。その後、ブラウザの解析およびレンダリングコードが途切れることなく進むことができます。
対照的に、DOM APIを使用して複雑な構造を構築している場合、多くのクロスレイヤーの旅行が起こっているだけでなく(javaScript->ブラウザ - > JavaScript)、ブラウザもDOMで動作する必要があります。内部構造ではなくAPI。
その結果、通常、よく書かれたJavaScriptテンプレートエンジンを見る価値があります(このクライアント側をやりたい場合)。これらは通常、テンプレートを簡単に処理できるフォームに1回「コンパイル」し、特定のデータセットの処理中に、配列のフラグメントとして文字列を構築するなどのトリックを使用します Array#push
, 、そして最終結果を介して取得します Array#join
渡されます ""
セパレーターとして。大きな文字列の場合、それは文字列の連結よりも高速になる可能性がありますが、それが(そして程度まで)かどうか とても 実装依存(FirefoxのSpidermonkey対Chrome's V8 vs. IEのJScript)とは異なります innerHTML
vs. domのもの、それはどのように変化します 多くの より速いです。
これがメーリングリストです 数年前のメッセージは私が話していました(基本的に私が上記のことを言っています。すごい、それは2年前でした)、 これがペーストです それは、それを参照してください JSBINにコピー, 、そして最後に...これがコードです: (コードはそうです いいえ 永遠に美しさと喜びのものになることを目的としています。それは簡単なハックでした...それでも、Yeesh、私は2年後にもう少し良いものをハッキングすると思いたいです。)
これを取り組むものに変換する価値があるかもしれません jsperf. 。今それをする時間はありません、私は恐れています。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<style>
#log {
border-bottom: 1px solid black;
}
#log p {
margin: 0;
padding: 0;
}
</style>
<script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/prototype/1/prototype.js'></script>
<script type='text/javascript'>
document.observe('dom:loaded', function() {
$('btnDOMDirect').observe('click', useDOMDirect);
$('btnPrototypeDOM').observe('click', usePrototypeDOM);
$('btnHTML').observe('click', useHTML);
});
var numRows = 10;
var numCols = 10;
function usePrototypeDOM(evt)
{
var table;
var tbody;
var tr;
var td;
var row;
var col;
var start;
var end;
start = (new Date()).getTime();
table = new Element('table');
tbody = new Element('tbody');
table.appendChild(tbody);
for (row = 0; row < numRows; ++row) {
tr = new Element('tr');
tbody.appendChild(tr);
for (col = 0; col < numCols; ++col) {
td = new Element('td');
td.update('Row ' + row + ', col ' + col);
tr.appendChild(td);
}
}
$('targetTable').update(table);
end = (new Date()).getTime();
log('DOM took ' + (end - start) + 'ms');
}
function useDOMDirect(evt)
{
var table;
var tbody;
var tr;
var td;
var row;
var col;
var start;
var end;
if (Prototype.Browser.IE) {
alert("DOM direct doesn't work on IE because I used table elements. Sorry. The other two work.");
return;
}
start = (new Date()).getTime();
table = document.createElement('table');
tbody = document.createElement('tbody');
table.appendChild(tbody);
for (row = 0; row < numRows; ++row) {
tr = document.createElement('tr');
tbody.appendChild(tr);
for (col = 0; col < numCols; ++col) {
td = document.createElement('td');
td.update('Row ' + row + ', col ' + col);
tr.appendChild(td);
}
}
$('targetTable').update(table);
end = (new Date()).getTime();
log('DOM took ' + (end - start) + 'ms');
}
function useHTML(evt)
{
var html;
var row;
var col;
var start;
var end;
start = (new Date()).getTime();
html = '<table><tbody>';
for (row = 0; row < numRows; ++row) {
html += '<tr>';
for (col = 0; col < numCols; ++col) {
html += '<td>Row ' + row + ', col ' + col + '</td>';
}
html += '</tr>';
}
html += '</tbody></table>';
$('targetTable').update(html);
end = (new Date()).getTime();
log('HTML took ' + (end - start) + 'ms');
}
function log(msg)
{
var l;
var p;
l = $('log');
if (l) {
p = new Element('p');
p.update(msg);
l.appendChild(p);
}
}
</script>
</head>
<body>
<input type='button' id='btnDOMDirect' value='DOM Direct' />
<input type='button' id='btnPrototypeDOM' value='Prototype DOM' />
<input type='button' id='btnHTML' value='HTML' />
<div id='log'></div>
<div id='targetTable'></div>
</body>
</html>
他のヒント
JavaScriptを使用してこれを行うのは常に遅くなります。これは、HTMLに要素を追加するため、ページではなくページのロードの上に実行されるためです。ただし、HTMLに要素を持っていない限り、ページの実際の負荷は(それほど大きくはありませんが)少ないと言うこともできます。
ただし、もう1つのポイントは、JavaScriptがGarbage Collectionでかなり悪いため、DOMコールを大量に作成すると、最終的に処理能力に加算され始めます。
さらに、セマンティックWebサイトの維持に興味がある場合は、タグが必要ですか? JavaScriptなしで優雅に劣化しますか?など。それはあなたがとりたいと思う角度に依存します。
多くの要素を作成する場合、innerhtmlははるかに高速になる可能性がありますが、公式のDOM標準の一部ではありません(広くサポートされていますが)。私の推奨事項は、ページ自体にできるだけ多くのHTMLを含むスケルトンレイアウトを備えたページを提供し、ページの関連部分への参照をつかみ、標準のDOMメソッドで値をプラグインすることです。
これはかなり高速である必要があり、プレゼンテーションとロジックを分離し、将来のサイトの変更または再設計の場合、おそらくより柔軟になります。
変更 innerHTML
DOMメソッドを使用する代わりに。
これによれば W3C Dom vs InnerHtmlのベンチマーク quirksmodeでは、テストされたすべてのブラウザは 多くの HTMLでDOMよりも速い。