Nicholas C. Zakas is a web software engineer who specializes in user interface design and implementation for web applications using JavaScript, Dynamic HTML, CSS, XML, and XSLT. |
WebアプリケーションやWebサイトはますますJavaScriptに依存するようになりつつある。ページレンダリングという観点でみた場合、JavaScriptのサイズはユーザ不満度に与える影響が大きい。ライブラリも含め、利用するJavaScriptのコード量が増えるごとにこの部分は無視できない問題として顕著化してくる。このあたりの高速化テクニックはWebデベロッパが一通り抑えておきたいポイントだ。
このあたりの話がWhat is a non-blocking script? - NCZOnlineにわかりやすくまとめられている。どういった理由で、なぜ問題になるのか、どうすれば回避できるのか、よく誤解されている部分はどれか、などが整理して説明されており参考になる。
説明によれば、まず、JavaScriptは基本的にシングルスレッドで動作するということを抑えておく必要がある。1度に実行できることは1つということだ。さらにレンダリングもこの影響を受ける。JavaScript実行中は基本的にレンダリングできない。これは、JavaScriptが要素を操作することでレンダリングする内容が変わる可能性があるためだ。逆にいえばレンダリング中にJavaScriptを実行することもできない。JavaScriptのコード量が増えれば根本的にレンダリングが停止する時間が生まれることになるわけだ。
典型的にはJavaScriptのコードは次の流れで処理が実施される。この間はページのレンダリングや他のリソースのダウンロードは原則としてブロックされる。
- HTTPコネクションを実施
- JavaScriptコードをダウンロード
- パース
- 実行
JavaScriptコードの並列ダウンロード
もっとも時間がかかるのはHTTPコネクションからダウンロード完了までの間だ。この部分の性能を改善するため、新しいブラウザはJavaScriptファイルを並列でダウンロードする実装を採用している。実行時の順序は本来の順序が保持される。つまり、もっとも時間がかかる部分だけを先にまとめて並列に実施してしまおうというわけだ。これはブラウザ側の改善ということになる。
ノンブロッキングスクリプト - 動的script生成
scriptタグによるレンダリングやほかのリソースダウンロードのブロックを回避する方法はいくつかあるが、What is a non-blocking script?ではscript要素を動的に生成する方法を推奨している。HTMLに最初から静的に記載されているscriptタグはレンダリングや他のリソースのダウンロードをブロックするが、動的に生成されたscript要素はレンダリングやほかのリソースのダウンロードをブロックしない。この方法を採用することでブロック処理のうち1. 2. 3.あたりが回避できることになる。
これで唯一ブロックが残るのがJavaScriptの実行時ということになる。JavaScriptは基本的にシングルスレッドで動作するため、Web Workerスレッドを生成して明示的に別のスレッドで実行しない限りは、JavaScriptの実行でブロックが発生する。しかしWhat is a non-blocking script?では、スクリプトのダウンロードにかかる時間に比べれば、JavaScriptの実行は高速なものだとも言及している。最新のブラウザほどここの実行性能は改善され続けている。
script要素を動的に生成することでダウンロード時におけるブロックは解消し、さらにFirefoxとOperaではscriptが動的に生成された順にスクリプトが実行されるので、実行順序も意図通りに動くことになる。IE、Chrome、Safariでは順序は加味されず、実行できるようになったスクリプトから順次実行される。ブラウザのこのあたりの挙動の違いには注意する必要がある。
ノンブロッキングスクリプト - scriptタグにasync属性を指定
HTML5からは動的にscript要素を生成しなくても、scriptタグにasync属性を指定することで同様の処理を実施されるようになる。今のところリリース版でサポートしているのはFirefox 3.6のみであり、今後の対応が期待される。
ただし動的にscript要素を指定するケースと完全に同じにはならない。FirefoxとOperaはscript要素が生成された順序でスクリプトを実行するが、scriptタグにasyncが指定されていると、IEやChrome、Safariのように生成時の順序を気にせずにスクリプトを実行するようになるという。What is a non-blocking script?では、この動作は明らかにページに埋め込むGoogle Analyticsコードに対処するためのものだろうと指摘している。今のところ、script要素の動的生成とasync属性指定の双方を駆使して、ノンブロッキングスクリプトを実現することになる。