マスタリング非同期読み込み BPStudy#41

os0x(Shogo Ohta), 2011-01-28

Profile

Theme

非同期読み込み

なぜ非同期読み込みが注目されているのか

非同期処理→イベントドリブン

Node.jsやBigPipe

JavaScriptは他のリソースの処理(読み込み)をブロックする→非同期化で解決

アイドリングストップ

New Twitter

体感的には早く感じない

肝心の本文が最後に表示されるから

でも、非同期読み込みした結果本文が表示される時間と、非同期読み込みなしでページの読み込みが完了するまでの時間を比べたら、ほとんど差はないと推測される

本文が最後に表示される(ように感じる)のはそこの取得に一番時間がかかるから

ページ(外枠)→本文→(返信・Retweet)の順番で、ちゃんと本文は優先されている

非同期読み込みのライブラリ

今のところ、

の2つが主流。RequireJSは後述の問題で非同期に適さない。

LAB.js

ロード処理をJavaScriptで書くことで、非同期読み込みを実現するライブラリ。XHRでjsファイルをテキストとして取得し、後で実行するなど、結構面白い実装。Twitterも使っている。

従来のHTMLに書く方法では使えないので、導入に大幅な修正が必要。

ControlJS

HTML側でscriptタグのtypeをtext/javascriptではなく、text/cjsにすることでJavaScriptとして解釈させず、あとでtext/cjsなスクリプトを評価するという方法を取る。

従来のHTMLベースで良いので導入は楽だが、scriptを2回ロードしてしまう問題がある一度ブラウザにキャッシュさせ、改めて評価する方法を取っているが、リクエストが2回発生していて無駄が大きい印象

RequireJS

読み込みはdocument.createElement('script')してinsertしているだけ。ちゃんと非同期になっている。

ただ、依存がネストすると非同期にならない問題がある。

RequireJSは使えば使うほどファイルが細分化され、しかも非同期読み込みができなくなっていくという問題を抱えている。

test.html

require(['a'],function(a){
  console.log(a,a.say());
});

a.js

define(['b'],function(B){
  var a = new B();
  return a;
});

b.js

define(['c'],function(C){
  function B() {}
  B.prototype.say = function(){
    return C.name;
  };
  return B;
});

c.js

define(function(){
  return {name:'hoge'};
});

RequireJSの読み込み問題の解決策

依存関係は分かっているので、先に読み込んでおけば良い

requireされたら、予めテキストとして読み込んでおいたスクリプトを実行する

デモ

normal require

preload require

最後に

Dynamic Script Execution Order(whatwgのWiki)に、いろんな提案が上がっています。

async=falseとか、"Script Group" elementとか、"text/cache" MIME typeとか、readyState "preloading"とか、