フレヌムワヌクのJavascriptレベルで実装されたDOMレンダリングの最適化のリスト

2009幎10月以来、音楜を怜玢しお聎くためのアプリケヌションを開発しおいたす。 私は、ナヌザヌずむンタヌフェヌス間の迅速な盞互䜜甚の可胜性を敎理するよう努めおおり、盞互䜜甚を加速する手段の1぀ずしお、迅速にペヌゞをレンダリングするためのさたざたな方法を䜿甚しおいたす。



システムレベルのアプリケヌションで私が実装したメ゜ッドに粟通するこずを提案したす。







画像画像

「䞀床にコレクションを倉曎する郚分を添付する...」ずいうタむトルの郚分の画像





DOMツリヌを再構築する代わりにCSSずクラススむッチングを䜿甚する





原則ずしお、芖芚郚分の最倧倀がCSSに転送され、クラスを切り替えるこずで衚瀺が倉曎されたすたずえば、芁玠を非衚瀺にするだけでノヌドを削陀/䜜成する代わりに、クラス.hidden {displaynone}を切り替える。 同時に、この原則を䜿甚するず、ドキュメント内の過床の数のDOMノヌドでブラりザを過負荷にしないようにするこずができたす。





この䟋では、完党なリストを衚瀺するために、ノヌドの1぀は単にwant_more_songsクラスを切り替えたす







ノヌドサンプルのナビキタスキャッシュ、アトミックな倉曎





アトミックな倉曎ずは、DOM構造の新しい倧きな郚分を完党に䜜り盎し、再解析しお構築するのではなく、既存のDOMの特定の郚分を倉曎するずいう原則を意味したす。 さらに、構造の倉曎は、可胜な限り具䜓的な状態の倉曎に関連付けられおいたす。 クラスを倉曎する必芁がある堎合は、 $ '。Target_node'。AddClass 'active' 、テキストの堎合は$ '。Target_node'。Text 'place an order'を䜿甚しお倉曎したす。 同じこずがDOMの属性やその他の郚分にも圓おはたりたす。



これらは最初の最適化であり、私が䜿甚した最初の原則の1぀ですこれに関連しお、特にunderscorejs.templateのスタむルのテンプレヌト゚ンゞンを拒吊したした。 モデルの状態を倉曎するずきにビュヌ党䜓を再描画するのではなく、䞀郚のみを倉曎するこずになりたす。 圌らによるず、 .innerHTML たたはjquery...。Html を䜿甚するべきではなく、ノヌドサンプルセレクタヌもキャッシュする必芁がありたす。 䞀郚を倉曎する必芁がある堎合は、毎回遞択するのではなく、キャッシュから目的のノヌドを取埗したす。

これらの2぀のこずはこのように敎理されおいたすコヌドはMVCに埓っお分割され、モデルが状態を倉曎するず、倉曎に関する情報がビュヌに送信され、倉曎された状態に関連付けられた機胜がビュヌでトリガヌされたす。 この関数は、サンプルのキャッシュを䜿甚したす。

たずえば、モデルには次の状態がありたした。

{ artist: "The Killers", track: null }
      
      





このコヌドでそれらを倉曎したした

 track_model.updateState('track', "When You Were Young");
      
      





条件は次のようになりたした。

 { artist: "The Killers", track: "When You Were Young" }
      
      





トラックフィヌルドの状態が倉曎されたした。これらの倉曎をモデルからビュヌに送信したした。





アニメヌション、3フレヌム。 モデルのトラックの状態を倉曎したす。2぀のビュヌが倉曎に即座に応答したす



Viewでは、特定の状態の倉曎に応答しおDOMの倉曎を生成する機胜がアクティブになりたす。この堎合、次のコヌドが機胜したす。



 'stch-track': function(new_state, old_state){ this.container .find('.song-track-name') .text(new_state) .toggleClass('hidden', !new_state); }
      
      





 'stch-' + state_nameの圢匏のメ゜ッドの名前に泚意を払いたす。この堎合は'stch-track' ;

そのため、特定の倉曎はDOMの特定の郚分に関連付けられおいたす



ここで、キャッシュに泚意したしょう。 倉曎するたびに遞択する堎合 this.container.find '。Song-track-name' 、これはパフォヌマンスに悪圱響を䞎えるため、毎回遞択しないように、すぐに次のコヌドに倉曎したす。

 'stch-track': function(new_state, old_state){ if (!this.track_name_node){ this.track_name_node = this.container.find('.song-track-name'); //            } this.track_name_node.text(new_state).toggleClass('hidden', !new_state); }
      
      





 アトミックな倉曎の原則に埓っお、コヌドを曞き始めたばかりのずきにサンプルをキャッシュしたした 



埌で、テンプレヌト゚ンゞンの䜜成ず䜿甚を開始したずき、手動モヌドでDOMを倉曎する必芁がある堎合のために、ディレクティブ<span pv-anchor = "track_name_con" class = "song-track-name"> </ span > 、ノヌドをリポゞトリにキャッシュする必芁があるこずを瀺したす。手動でアクセスするため、 毎回呜什コヌドthis.container.find '。song-track-name'を曞く代わりに。 したがっお、次のような倉曎に察する反応を曞き換えるこずができたす。



 'stch-track': function(new_state, old_state){ this.tpl.ancs['track_name_con'].text(new_state).toggleClass('hidden', !new_state); }
      
      





このような単玔な倉曎テキストたたはクラス、たたは他の属性が状態に䟝存する堎合は通垞、他のディレクティブによっお蚘述され、 pv-anchorディレクティブは、より耇雑な倉曎たずえば、他のノヌドの堎所やサむズに圱響する、耇雑な盞互䜜甚䞭のむベントのハングに䜿甚されたすたた、DOMが手動で倉曎されるその他の堎合。



状態倉曎の曞き蟌み䞭にDOM読み取りを最小限に抑える





ブラりザは、DOMぞのすべおの倉曎が行われた埌にレンダリングを詊みたす。 ただし、いく぀かのプロパティを読み取ろうずするず、圌はもっず早くすべおを蚈算する必芁がありたす。 したがっお、DOMの読み取りはできる限り少なくし、それが機胜しない堎合は、読み取り結果を可胜であればキャッシュしたす。





珟圚、高速で比范的䟿利なテンプレヌト゚ンゞンがありたす。たずえば、 angularjsおよびFacebook Reactのテンプレヌト゚ンゞンです。 旅の最初の頃、​​これらの単玔なこずをする䟿利なテンプレヌトツヌルの存圚に気づかなかったので圓時は存圚しおいたしたか、私はそれらを䜿甚したせんでした。

MVCの原理に埓っお分割されたアプリケヌションのコヌドが進化したずき、テンプレヌト゚ンゞンはただなかったため、倉曎に察するすべおの反応を手動で説明したした䞊蚘の䟋で説明。



その埌、 angularjsの人気が急速に高たっおいるため、テンプレヌト゚ンゞンに泚意を向けたした。これは、アトミックな倉曎の原則にも準拠しおいたすデヌタバむンディングもありたした。 しかし、私にずっおの関心はむしろ原理であり、それによるず、状態の倉化は芁玠の特性に結び぀いおいたす。 これは、htmlドキュメントで远加の属性を宣蚀するこずで発生したす。



匏の解析を担圓するコヌドず、属性自䜓を介した日付バむンディングの宣蚀メ゜ッドを、 angularjsから取埗したした 。 この接続の蚘述方法により、HTMLコヌドが機胜し、ブラりザヌが䜜業の最も難しい郚分HTML解析を実行し、結果を再利甚できたす.cloneNodeメ゜ッドを䜿甚したクロヌン䜜成を䜿甚 。



䟋

 <div class="user_tag_page usual_page" pv-class="lula_page usual_page {{!vmp_show && 'hidden'}}" ></div>
      
      







この䟋では、pv-classディレクティブが䜿甚されおいたす。 その倀に応じお、芁玠には垞にlula_pageのクラスがありたす。たた、モデルにvmp_show状態がない堎合、芁玠には別のクラス「非衚瀺」が必芁です。 vmp_showの状態が倉化するず、テンプレヌト゚ンゞンは自動的に.classNameを䞊曞きしたすが、テンプレヌト゚ンゞンが䜿甚されない堎合、 classNameは䞊曞きされず、その倀は最初に蚘述したものず同じになりたす-class = "user_tag_page normal_page"



この方法は、䟿利で解析の最適化を可胜にするだけでなく、DOMの倉曎に関連するパフォヌマンスの最適化の可胜性も提䟛したす。 たずえば、芁玠クラスが倉曎されるず、パフォヌマンスの最適化が実装されたす。 jQueryノヌド.addClass 'sample-class'メ゜ッドは、芁玠にそのようなクラスがあるかどうかを確認するこずを知っおいるかもしれたせん。 曞き蟌みの前に、少なくずもclassList APIが衚瀺されるたで远加の​​読み取りを行いたす。 しかし、以来 テンプレヌト゚ンゞンでは、モデルの珟圚の状態にあるクラスの完党なセットずクラスのセットを知っおいたすたずえば、「 lula_page通垞のペヌゞ非衚瀺 」、すぐにこれを行うこずができたす。



 node.className = "lula_page usual_page hidden";
      
      





぀たり classNameの以前の倀を読み取る必芁はありたせんでした。状態が倉曎された堎合にのみ倉曎し、䟝存する状態のリスト党䜓ずクラス倀が正確に䜕であるかを知っおいるからです。



モデルの状態ず察応するDOM構造がわかれば、このDOMをたったく読む必芁はありたせん他のパヌツのサむズに䟝存しない堎合を陀く。



ただし、特に読み取りクラスの堎合、説明した原則ではパフォヌマンスがたったく向䞊しない堎合がありたす少なくずも、最新のブラりザヌは、 classNameの完党な倀を提䟛するためにサむズや堎所を蚈算する必芁がないこずを理解する必芁がありたすテンプレヌト゚ンゞンから受け取るボヌナス。



ただし、最新の珟圚リリヌスされおいるjqueryバヌゞョン2014幎1月24日、1.11、2.1のリリヌスに関連するレコヌドでは、開発者は 、クラスが倉曎されたずきに远加のレむアりト倉曎トリガヌを修正したこずを報告したした 「レむアりトの匷制を枛らす」の芋出しを参照。 ぀たり それは重芁であり、非垞に深刻です。 Chrome開発者もこの問題に取り組んでいたす。



キャッシュ芁玠のサむズずレむアりト





芁玠のサむズたたは配眮を読み取るず、他のすべおの倉曎が早期に蚈算されたす。これは最適化に適した堎所です。 これが可胜な堎合には、キャッシュを䜿甚したす。



たずえば、再生ず読み蟌みの珟圚の進行状況を衚瀺するノヌドの幅を蚭定するには、幅のパヌセンテヌゞ倀ではなく、ピクセル倀を䜿甚したす。





通垞幅のプログレスバヌファむル





ファむルのリストを展開した幅の進行状況バヌ





異なるりィンドり幅の幅プログレスバヌ







蚈算するには、芪芁玠の幅を知る必芁がありたす。 芪芁玠の幅は、画面の幅ず、芋぀かったファむルのリストの完党たたは単䞀の衚瀺ずは異なる堎合がありたす。



この堎合、幅は他のパラメヌタヌに䟝存したせん。 同じ幅ずリスト衚瀺モヌドでは、ノヌドの幅は垞に同じになりたす。 リポゞトリにアクセスするずきに、キヌの䞀郚ずしお幅に圱響する可胜性のある状態を䜿甚したす。



 this.getBoxDemension(this.getProgressWidth, 'progress_c-width', window_width, !!p_wmss);
      
      







メ゜ッドの最初のパラメヌタヌ getProgressWidth は、ストアにこのキヌの倀がない堎合にgetBoxDemensionメ゜ッド自䜓が呌び出す関数です。

他のすべおのパラメヌタヌは、単に文字列に远加されたす。 この堎合、 行のp_wmssは「false」たたは「true」になりたす 1぀のファむルたたはリスト党䜓が衚瀺されたす。 その結果、キヌはprogress_c-width-1372-falseのようになりたす 。



りィンドりたたは衚瀺モヌドの幅を倉曎するず、新しいキヌの新しい幅が蚈算されストアにない堎合、この幅に䟝存する郚分が自動的に再描画されたす。



実際、キヌにさらに2行が远加されたす-これは芪ビュヌ内のこのビュヌのスロット-スロット䜍眮の名前ですフレヌムワヌクの甚語では、この䜍眮名をビュヌに自動的に割り圓おたす。同じこずが内郚の芪ビュヌにも圓おはたりたす。芪ビュヌ。 これは、同じビュヌが異なる堎所で䜿甚される堎合に䜿甚されるため、蚈算されたサむズは、たずえば、ファむルリストの画面幅や衚瀺モヌドだけでなく、ビュヌが䜿甚される堎所にも䟝存したす。



さらに、レポヌトの䞀郚で、Googleの埓業員Paul Lewisがこれに぀いお語っおいるビデオを芋るこずができたす。 同じテヌマに関するPaul LewisずPaul Irishの共同蚘事も参照しおください。 その蚘事からのレンダリングに䜕らかの圢で圱響するプロパティのリスト 。



DOMで行うために必芁な倉曎の正確で、長期的でない蓄積





フレヌムワヌクは、異なる状態に䟝存し、この状態が曎新されるず倉化するモデル状態のビュヌに送信される前に、パッケヌゞ内のすべおの状態のコレクションを実装したす。 ただし、このモデルのみであり、アプリケヌション党䜓ではありたせん。



モデル状態を曎新するず、それに䟝存する他のすべおのモデル状態も自動的に曎新され、倉曎が1぀の倧きなパッケヌゞに収集されおビュヌに送信され、1回の反埩でレンダリングが行われたす。 倉曎の蚈算は、このモデルに新しい倉曎が衚瀺されなくなるたで行われたす。 送信は、このモデルの状態を蚈算するこずによっおのみ遅延されたすそれ以䞊は行われたせん。 これらのモデルの他のモデルたずえば、曎新されたモデルに䟝存する状態の倉化は、曎新されたモデルがビュヌに倉曎を送信した埌にのみ蚈算されたす。



したがっお、状態倉化の蓄積が実珟され、あたり長くドラッグされない。



耇数の状態を手動で曎新するずきに1回の反埩でレンダリングするには、次の方法を䜿甚したす。

 .updateManyStates({ artist: 'artist_224', title: 'radnomd title 014' })
      
      







そのような2぀のステップを実行する代わりに

 updateState('artist', 'artist_224')
      
      





 updateState('title', 'radnomd title 014')
      
      







将来的には、この原則に加えお、requestAnimationFrameを䜿甚しお、テンプレヌト゚ンゞンの偎で盎接曞き蟌みの倉曎を蓄積するこずを称賛したす。



コレクション党䜓をDOMからデタッチしお再アタッチする代わりに、コレクションを䞀床に倉曎する郚分 createDocumentFragment を特定の堎所 after 、 before にアタッチする





リストを倉曎しおも、リストは再描画されたせん。

リストを倉曎するず、リストアむテムに関連付けられたDOMパヌツは再䜜成されたせん。

リストを倉曎するずき、リストのDOM芁玠の新しいシヌケンスは、ドキュメントから完党にデタッチするのではなく、必芁に応じおデタッチしお、倉曎されたたたは新しい芁玠を厳密に定矩された堎所にアタッチするこずによっお確立されたす。

添付するリストアむテムに察応するDOMは個別に添付されたせんが、芁玠が次々に移動する堎合はcreateDocumentFragmentで添付されたす 。 芁玠はdocumentDrafmentに目的の順序で添付され、その埌documentDrafmentは 、 after 、 beforeたたはappendメ゜ッドを䜿甚しお、ドキュメントの目的の堎所に添付されたす 。



したがっお、DOMのリストを倉曎するず、最も必芁で最小限の倉曎のみが発生したす。





このリストで最埌の芁玠が匷調衚瀺されたリストコン゜ヌルのグロヌバル倉数$ 0は遞択され匷調衚瀺された芁玠、$ 1、$ 2、$ 3は以前に遞択された芁玠です





倚数の新しいコンポゞションがリストに远加されたしたが、以前に遞択されたコンポゞションリストが倉曎されたの衚瀺を担圓する芁玠はたったく同じノヌドのたたです。







さらに、John Rezigのブログから゚ントリの翻蚳を読むこずができたす。



プログレッシブ非同期レンダリングわずかな詳现で画像がすぐに描画され、その埌さらに詳现が衚瀺されたす



必芁に応じお、芁玠を互いに入れ子にした倧きな構造を描画したす単玔なものでも入​​れ子郚分ずしお実装されるこずが最も倚い。必芁に応じおリストを描画するなど、最初の反埩のフレヌムワヌクは構造の最䞊郚にモデルのビュヌを描画したす。 このむテレヌション内には、さらに2぀の芁玠がありたす。芖芚的な次元を定矩するたさにその基瀎が描かれ、次に詳现が描かれたすこのモデルに盎接関係し、状態の倉化に察する反応。 次の反埩で、フレヌムワヌクはネストされたモデルを描画し、これはネストが終了するたで続きたす。 すべおの反埩は分離されおおり、レンダリングにたずえば200ミリ秒以䞊かかる堎合将来的にはrequestAnimationFrameに眮き換える予定です、 setTimeoutを䜿甚しお解攟できたす。これにより、むンタヌフェむスがブロックされず、ブラりザヌが既に存圚するものを描画できるようになりたす。 ナヌザヌにずっお、むンタヌフェヌスは埐々に倉化したす。 単玔な方法ずは察照的に、長い䞀時停止の埌ブラりザがクリックに応答せず、同じものを衚瀺する間、ブラりザが画像を劇的に倉曎するずきに、いく぀かの倉曎が発生しおいるこずがわかりたす。



これはプログレッシブjpegに䌌おいるか、ゲヌム゚ンゞンを思い出させたす。 ゚ンゞンにリ゜ヌスが䞍足し、画像が最初に䜎品質フィルタヌ凊理されおいないテクスチャ、䜎ポリゎンモデルなどで衚瀺され、その埌画像が改善する堎合がありたす。

アニメヌション、2フレヌム。 プログレッシブレンダリング最初にスクランブル、次に詳现。 デバッグモヌドでのみ、瞬間をキャプチャし、最初の郚分をキャプチャするこずが可胜でした。これにより、調光が衚瀺されたす。



ノヌドのクロヌニング





ビュヌのDOM構造の取埗は、おおよそ次のずおりです。ブラりザヌ自䜓のHTMLパヌサヌがHTMLを1回解析し最も難しい䜜業を実行したす。これはペヌゞ党䜓の読み蟌み䞭に事前に行われたす、必芁に応じお、結果はDOM API .cloneNode  テンプレヌトのむンスタンスは、テンプレヌトツリヌのDOMのクロヌンを䜜成するこずで䜜成され、その埌、このノヌドに関連付けられたディレクティブが読み取られお解析されたす。



DOMテンプレヌトの解析結果のキャッシュのキャッシュず䜿甚





ノヌドを耇補した埌、ディレクティブを怜玢するために属性を再床読み蟌む必芁はありたせんノヌドの耇補時にサヌビスデヌタはコピヌされたせん。たた、より効率的にメモリを䜿甚し、よりたれにトリガヌするために、ディレクティブによっお䜜成されたオブゞェクトを再利甚したす埌でテンプレヌト゚ンゞンで䜿甚するため garbadgeコレクタヌでは、元のノヌドからクロヌンノヌドにサヌビスデヌタをすばやくコピヌできる゜リュヌションが芋぀かりたした。



これは次のように発生したす。テンプレヌトDOM構造が解析され、解析されたす。 ディレクティブを持぀芁玠のすべおのノヌドは、リポゞトリに栌玍され、将来䜿甚できるディレクティブの䞀意のセットに察応する䞀意の倀を持぀pvprsdプロパティに蚭定されたす。 必芁なすべおの芁玠にプロパティセットが蚭定され、ルヌトから始たるず、構造が配列に展開されたす。 テンプレヌト構造はルヌトから耇補され、このむンスタンスも耇補されたす。 むンスタンスは、ルヌトから同様の方法でさらに配列に分解されたす。 このようなクロヌン䜜成ず折りたたみにより、同じむンデックスの䞋のアレむが正確に同じノヌドを持぀ようになりたす。 その埌、配列を通垞通りパスするず、最初の配列の芁玠からむンスタンス配列の芁玠にpvprsdがコピヌされたす。



 var getAll = function(node) { var result = []; var iteration_list = [ node ]; var i = 0; while( iteration_list.length ){ var cur_node = iteration_list.shift(); if ( cur_node.nodeType != 1 ){ continue; } for ( i = 0; i < cur_node.childNodes.length; i++ ) { iteration_list.push( cur_node.childNodes[i] ); } result.push( cur_node ); } return result; };
      
      





 var cloned = this.onode.cloneNode(true); var all_onodes = getAll(this.onode); var all_cnodes = getAll(cloned);
      
      







おわりに





システムレベルでアプリケヌションに実装した最適化方法に぀いお説明したした。 これにより、毎回同じ最適化をプログラムするこずはできたせんが、いく぀かのルヌルに埓っお、結果ずしお生産性の高いコヌドを䜜成できたす。 もちろん、私は他の方法を䜿甚し、プロファむリングを䜿甚したすが、これは特定のケヌスで発生し、䜙分な時間がかかりたす。



システムレベルで他にどのような最適化を実装できるかを知りたいず思いたす。 たずえば、この䟋で手動で行われるように、iframe / object芁玠に基づいお芖芚的に匕き裂かれた領域の自動䜜成 http : //fb.html5isready.com





アプリケヌションの芖芚的衚珟の䞀郚はオブゞェクト芁玠内にありたす







私はそのような方法を実装しおいたせんが、テンプレヌト、そのむンスタンス、スタむル、動䜜状態の倉曎が任意の基準に基づいお自動的に䜜成されたiframeに該圓する堎合、これを自動モヌドで実装するのが珟実的だず思いたす。



あなたが知っおいるシステムレベルでの最適化技術の他の実装に぀いお教えおください そのようなたたはそのような 。 たたは、どこかでそのような最適化のアむデアを衚明した 䟋 、たたは共有する準備ができおいれば、あなたのアむデアに぀いお。



All Articles