LAB.js
前の斜め読みへのコメントでid:edvakfさんが言及してたjsライブラリ。
- jsと他のコンポーネント(他のjs、css、img、etc.)の並行DL
- ifame要素は?今度調べる
- 複数js間の依存関係維持
- クロスブラウザ
- jQueryライクなメソッドチェーンで書きやすいコード
- 戻り値は$LAVオブジェクト
- 要注意ポイントは「jQueryは1.4以上にしとく」
- 守らないとFxで大変な目に・・・
LABjs
存在は知ってるがよく知らないという状態だったのでこれを機に斜め読み。
以下斜め読んだ内容:home、description、release notes
- LABはLoading And Blockingの略
- MITライセンス
- Getify Solutions(Kyle Simpson)のプロジェクト
- Steve Soudersとのコラボしたことが活かされてる
LABjs & User-Experience
- jsの同時ロード
- フツーは、jsは1個ずつしかロードされない
- jsと他のコンポーネントの同時ロード(ex.js/css/imgの同時ロード)
- フツーは、jsロードは他のコンポーネントのロードをブロックする
- 複数js間の依存関係も維持できる
- フツーは、script要素を書く順番で依存関係を指定(ex.jquery.jsは一番上に)
- ページロード高速化は、ウェブ開発者に課題も出してくる:FUBC問題
- ページコンテンツへjsが実行される前にユーザは画面を操作し始める可能性が出てくる
- FOUC(flash of un-styled content)ならぬFUBC(flash of un-behaviored content)
- (勝手に補足)リンク先をポップアップさせたいアンカーにイベントをセットする前にユーザがクリックしてしまうこと、とか
- LAB.jsはprogressive enhancementにもマッチしてるが、progressiveな部分をユーザに対して、明確にデザインしないといけない
- FUBC問題への対処例
手短なまとめ(/description.php)
- 軽量(minified版が4.5k。gzipすれば2.1kに)
- 狙い
- jsロードと他のコンポーネントのロードを並行させること
- 競合ローダー系jsライブラリと同じ機能
- 差別化
- 複数js間の依存関係も維持できる
-
- 競合jsライブラリが躓いてる、カンタンにできていないところ。
-
- 遅延実行もできる
- 複数js間の依存関係も維持できる
- 複数js間の依存関係を維持する、うまくないやり方
- ロードが終わったらコールバックを監視側に送って実行順番を管理
- コーディング規約として約束ごととしてjsにコメントを書いたりする
- loadイベントをscript要素ごとにセットする
- 「最初に3つjs並列ロードしてから、2つjsをロード&実行」のようなケース
- 上記うまくないやり方では、対応が複雑になる
- 全てのjsのロードの状況を把握して設計しないといけないから。
- そこでLAB.js
- 実行を順番にやるのか順番を問わないのかもカンタンに指定できる
- メソッドチェーンで書きやすい
LAB.jsの使い所(/description.php)
- 圧縮(minify)したり複数js合体(contat)というソリューションへの代案ではない
- 併用できるしすべし。
- httpリクエストを出来るだけ減らすべし、だから
- js1ファイルに固めたときもLab.jsは出番ある?
- 出番あるよ。使えばロード時間速くなる
- jsのロード他のコンポーネントとの並列ロードがLAB.jsでできるから
- CDNなどを使って複数のサーバーにファイルが分散してるサイトが多い
- この場合もLAB.jsはうまくロードしてくれる
- CDNにアップされてるjqueryがロードできないときは別サーバーからロードに切り替えるとか
- この場合もLAB.jsはうまくロードしてくれる
- js合体するだけじゃダメなの?の詳しい話はブログにエントリ書いた。読め。
LABjsを使うべきじゃないケース
- document.write()と併用するなら、LAB.jsは使うべきじゃない
- document.write()は同期的。非同期ロードテクニックであるLAB.jsと間逆
- DOMツリー構築を検知するスクリプトとLAB.jsが不具合に起こすときもLAB.jsは使うべきじゃない
- DomContentLoaded(or代替イベント)発火後にDOMツリー構築を検知するスクリプトをLAB.js経由で読み込んだとき、検知スクリプトがDomContentLoadedを永遠に待ち続ける場合がブラウザによっては起こる。---例えば1.4以前のjQueryとFx3.5の組み合わせの場合。
- jqueryチーム側でバグとして登録され、1.4で解決された({34} jQuery 1.4 Closed Bugs - jQuery - Development)。
- 詳しくはエントリ書いた。読め。
- DomContentLoaded(or代替イベント)発火後にDOMツリー構築を検知するスクリプトをLAB.js経由で読み込んだとき、検知スクリプトがDomContentLoadedを永遠に待ち続ける場合がブラウザによっては起こる。---例えば1.4以前のjQueryとFx3.5の組み合わせの場合。
リリースノート(/releasenotes.php)
- 1.0.2rc1
- IEバグ対策
- head要素へのscript要素挿入方法をappendChildからinsertBeforeに変更
- ノードリスト更新周りでのバグも直した。
- script[rel]廃止
- プリロードされるscript要素へrel属性使うの止めた
- プリロードされるscript要素のmimetype変更
- 「text/htm」から「script/cache」へ
- バグ・障害fix色々
- IEバグ対策
- 1.0.1
- パッチ
- wait()使わずにscript()使ったときに、メソッドチェーンが最後まで辿られないバグ直した
- 1.0
- 正式リリース。minifyして4.5k、gzipすれば2.1k
- 1.0rc5
- ファイルサイズ最適化
- XHRの監視方法変更
- setInterval()からoneadystatechangeへ
- 1.0rc4
- Fx3.6以前限定(?)のハックを追加
- Andrea Giammarchiのテクニック(195 Chars To Help Lazy Loading)を使った
- Fx3.6以前限定(?)のハックを追加
- Andrea Giammarchiのハックについて
- Fx3.5以下で仕様どおりdocument.readyStateが得られる
- jQuery1.3.2以降はこのパッチによってLAB.js経由でのロードに対応。
- document.readyState
- HTML5のスペックにも入った
- IEでは昔から実装済
- Fxは3.6でバグ修正された(document.readystate="complete"のサポート)
- 1.0rc3
- fLABjsをLAB.jsに組み込み
- fLABjsはfileスキーム(file://)に対応
- バグfix、ファイルサイズ最適化を色々と
- fLABjsをLAB.jsに組み込み
- 1.0rc2
- ブラウザ検知方法を変えた
- パフォーマンスアップ
- 1.0rc1
- プリロード機能でAPI追加
- 0.9
- ファイルサイズ軽量化、2.1kに
- ランタイム実行の効率アップ
以下斜め読んだ内容:documentation
テスト結果(/documentation.php)
- Win
- IE6-7
- Fx1.5〜3.6rc1
- Chrome4
- Opera9.6、10
- Safari4
- 略
- Mac
- Safari3.2.4
- Netscape9
- Fx1.5〜3.5
- Opera9.6、10
- 略
- Linux
- Fx1.5, 2, 3.5
- Opera9.5,9.6,10
- Netscape9
非対応ブラウザ
書き方例。これが
こうなる
上記コード解説
- js4ファイル同時にロードされる(これがデフォルト)
- 1番上(framework.js)と2番目(plugin.framework.js)・3番目(myplugin.framework.js)は依存関係あるが、plugin.framework.jsとmyplugin.framework.jsは依存関係無し
- 4番目(init.js)は上3つと依存関係にある
- 上記コードでは4つのjsの依存関係を維持したまま、framework.jsが最初に実行、次にplugin.framework.jsとmyplugin.framework.jsが実行、最後にinit.jsが実行される
$LAB.script()について補足
- scipt()に複数jsファイルのロードも指定できる。配列使う
- script()にsrc/type属性を指定してロードもできる。オブジェクトリテラル使う
$LAB.script({ src: "script1.js", type: "text/javascript" } $LAB.script("script1.js", "script2.js", "script3.js")
LAB.jsとインラインスクリプトを組み合わせる
- script()でロードされたライブラリ/プラグイン用の初期化コードを書く場所
- LAB.jsとLAB.jsを利用しているscript要素の下にロードしたライブラリ/プラグイン用のコード書いたscript要素を置いても、undefinedになる
- $LABの最初のメソッドチェーンが実行されたら、メソッドチェーンの最後まで実行されるのを待たずに、直下のscript要素に書かれたコードが実行されてしまう
- 依存関係維持するなら、Lab.jsのメソッドチェーンの中に初期化コードのが安全。
- wait()メソッド使うが、初期化コードをfunctionでラップしてから、()に入れて式としてwait()に渡す
LAB.js導入のコツ
- 既存のhtml内のjsをロードしてるscript要素を1つずつ、script()メソッドに置き換える
- インラインのスクリプトは「.wait(function(){ ... })」にラップしておきかえる
LAB.jsの特別な機能
- ブラウザ検知
- オブジェクト検知(ex.if(ActiveXObject))では対応できないとき用
//opera用。if(is_opera)・・と使う is_opera = window.opera && Object.toString.call(window.opera) == "[object Opera]" //gecko用。geckoのみtrueが返る。if(is_gecko)・・と使う is_gecko = (function(o) { o[o] = o+""; return o[o] != o+""; })(new String("__count__"))
LABjs API
- メソッドは4つ
- $LAB.setGlobalDefaults()
- $LAB.setOptions()
- $LAB.script()
- $LAB.wait()
- ブログ巡回してて見かけた.block()は廃止されたらしい(LAB.src.jsの337行目あたり)
global.$LAB.block = global.$LAB.wait; // alias "block" to "wait" -- "block" is now deprecated
.setGlobalDefaults()と.setOptions()
- デフォルトの設定を変えたいときに使う
- 引数はオブジェクトリテラルの形式で渡す
- .setGlobalDefaults()と.setOptions()の違い
- .setGlobalDefaults()はチェーンできない。ページ全体の設定になる
- .setOptions()はチェーンできるが、メソッドチェーンの最初でコールするのが必須
.setGlobalDefaults()と.setOptions()で設定できる項目
- 以下の項目を指定するとデフォルト設定を変えれる
- AlwaysPreserveOrder
- デフォルトはfalse
- script()でロードしたjsの実行順番を指定したいときに。
- オン(true)にすると、メソッドチェーンでつないだ順番に実行される
- あとでかく
- UsePreloading
- デフォルトはtrue
- プリロード(≠実行)をするかどうか
- オン(true)のときは、LAB.jsが実装してる並行DLのテクニックが最大限利用される
- オフにすると、メソッドチェーンに追加したステップごとに順番にロード&実行される。
- UseLocalXHR
- デフォルトはtrue
- オン(true)のときはXHR使ってローカルのファイルをロードする。
- キャッシュを読みに行くのとほぼ同義(たいていのブラウザでは)
- Fx/Operaではこのテクニックは使えないので無視される
- UseCachePreload
- デフォルトはtrue
- LAB.jsにおいて「text/html caching」と呼ばれるテクニックを利用するかどうかを判定
- 「text/html caching」
- 遅延実行のためにjsをtext/htmlとしてロードするときあり
- 問題は、mime typeが正しくないので、実行できないというケースが発生する
- この問題を回避するために、LAB.jsではロード時はtext/htmlを指定し、メソッドチェーンが、ロードしたjsを利用するステップに到達したときに、再度script要素をオンザフライで生成し、正しいmmeme type(text/javascript)を指定して、実行できるようにしてる。
- AllowDuplicates
- デフォルトはtrue
- あとでかく
- AppendTo
- オンザフライで生成したscript要素の挿入位置きめる。
- デフォルトはhead
- bodyかheadかを選べる
- BasePath
- デフォルトは""(指定なし)
- あとでかく
.script()と.wait()
あとでかく