Slide 1

Slide 1 text

browserify ことはじめ ~ その仕組みと活用~ 東京Node 学園 11 時限目 Ryo Murayama 2014/2/26 0

Slide 2

Slide 2 text

About me Ryo Murayama ( ) ユニバ株式会社 JavaScript, Ruby, Java ... @hitsujiwool http://uniba.jp

Slide 3

Slide 3 text

Outline browserify の概要と使い方 browserify の実装 さまざまなプラグイン (transform) まとめと展望

Slide 4

Slide 4 text

See also browserify‑playground github.com/hitsujiwool/browserify‑playground

Slide 5

Slide 5 text

Usage

Slide 6

Slide 6 text

browserify? CommonJS スタイルのコー ドをブラウザの実行コー ドに変換 するツー ル 初コミットは2010 年9 月 現在はバー ジョン3.30.2 substack (James Halliday) 作

Slide 7

Slide 7 text

Becoming a trend? GitHub Google Trend

Slide 8

Slide 8 text

Basic usage CLI b r o w s e r i f y s r c / m a i n . j s > p u b l i c / j a v a s c r i p t s / b u n d l e . j s programmable v a r b r o w s e r i f y = r e q u i r e ( ' b r o w s e r i f y ' ) ; v a r f s = r e q u i r e ( ' f s ' ) ; v a r b = b r o w s e r i f y ( ) ; b . a d d ( ' s r c / m a i n . j s ' ) . b u n d l e ( ) . p i p e ( f s . c r e a t e W r i t e S t r e a m ( ' p u b l i c / j a v a s c r i p t s / b u n d l e . j s ' ) ) ;

Slide 9

Slide 9 text

With your own modules / / s r c / p e r s o n a l . j s v a r f o o = r e q u i r e ( ' . / f o o ' ) ; f o o ( ) ; / / s r c / f o o . j s v a r b a r = r e q u i r e ( ' . / b a r ' ) ; m o d u l e . e x p o r t s = f u n c t i o n ( ) { c o n s o l e . l o g ( ' t h i s i s f o o ' ) ; b a r ( ) ; } ; / / s r c / b a r . j s m o d u l e . e x p o r t s = f u n c t i o n ( ) { c o n s o l e . l o g ( ' t h i s i s b a r ' ) ; } ;

Slide 10

Slide 10 text

With built‑in modules / / s r c / b u i l t _ i n . j s v a r E v e n t E m i t t e r = r e q u i r e ( ' e v e n t s ' ) . E v e n t E m i t t e r ; v a r e m i t t e r = n e w E v e n t E m i t t e r ( ) ; e m i t t e r . o n ( ' f o o ' , f u n c t i o n ( m e s s a g e ) { c o n s o l e . l o g ( m e s s a g e ) ; } ) ; e m i t t e r . e m i t ( ' f o o ' , ' s o m e m e s s a g e ' ) ; Node の組み込みモジュー ルも大半が使える 使えない場合はr e q u i r e ( ) が空のオブジェクトを返す 詳細は や を参照 Readme ソー スコー ド

Slide 11

Slide 11 text

With npm modules / / s r c / n p m . j s v a r r e q u e s t = r e q u i r e ( ' s u p e r a g e n t ' ) ; r e q u e s t . g e t ( ' h t t p : / / l o c a l h o s t : 3 0 0 0 ' , f u n c t i o n ( r e s ) { c o n s o l e . l o g ( r e s . s t a t u s ) ; } ) ;

Slide 12

Slide 12 text

Optional Parameters ‑r ‑‑require: 外部からのr e q u i r e ( ) を可能に b r o w s e r i f y - r . / s r c / e x p o r t e d . j s : e x p o r t e d ‑‑noparse: 依存関係の探索を省略 b r o w s e r i f y s r c / m a i n . j s - - n o p a r s e s r c / s o m e _ i n d e p e n d e n t _ m o d u l e . j s ‑t ‑‑transform: 出力コー ドの変換( 重要!) b r o w s e r i f y s r c / m a i n . j s - t d e a m d i f y 他にもたくさんあります

Slide 13

Slide 13 text

With task runners grunt‑browserify gulp‑browserify

Slide 14

Slide 14 text

browserify vs RequireJS CommonJS vs AMD preprocessing vs client driven (async) サー バサイドの資産を活用 ひと言で表すと"Node.js Oriented"

Slide 15

Slide 15 text

Architecture

Slide 16

Slide 16 text

Overall process

Slide 17

Slide 17 text

Overall process 1. transform によるコー ドの変換処理 (transform) 2. 依存関係の探索 (detective) 3. モジュー ルのパス解決 (browser‑resolve) 4. ブラウザで実行可能なコー ドの生成 (browser‑pack) 1~3 を再帰的に実行して依存ツリー を探索した後、4 で最終 的なコー ドを生成

Slide 18

Slide 18 text

module‑deps エントリポイントのファイルを受け取って、 ReadableWritable Stream を返す関数 ユー ザが指定したtransform を順々 にpipe して実行 detective (esprima) を使って生成したAST から依存モジュ ー ルを解析 browser‑resolve でモジュー ルのパスを解決 出力として流れるデー タは、 依存関係を構造化したJSON

Slide 19

Slide 19 text

browser‑pack [ { " i d " : " a 1 b 5 a f 7 8 " , " s o u r c e " : " c o n s o l e . l o g ( r e q u i r e ( ' . / f o o ' ) ( 5 ) ) " , " d e p s " : { " . / f o o " : " b 8 f 6 9 f a 5 " } , " e n t r y " : t r u e } , { " i d " : " b 8 f 6 9 f a 5 " , " s o u r c e " : " m o d u l e . e x p o r t s = f u n c t i o n ( n ) { r e t u r n n * 1 1 1 } " , " d e p s " : { } } ] ReadableWritable Stream を返す関数 module‑deps の出力を受け取り、 実行コー ドを生成する qiita.com/hitsujiwool/items/b013577d361bfdef18a6

Slide 20

Slide 20 text

Plugins

Slide 21

Slide 21 text

transform module 実行コー ドの「 変換」 を司るモジュー ル m o d u l e . e x p o r t s = f u n c t i o n ( f i l e ) { r e t u r n t h r o u g h ( ) ; } b r o w s e r i f y s r c / m a i n . j s - t d e a m d i f y ファイルパスを受けとり、ReadableWritable Stream を返 す関数 ユー ザがbrowserify の実行時に指定する AST から依存関係を解析する手前に通過する

Slide 22

Slide 22 text

Why transforms imporant? 多様なフロントエンドの生態系 「 普通の」JavaScript AMD altJS (TypeScript, JSX, HaXe, CoffeeScript) テンプレー トエンジン (handlebars, mustache, underscore) パッケー ジマネー ジャ (bower, component) プリプロセッサとしてのtransform

Slide 23

Slide 23 text

With naive Style (deglobalify) / / p u b l i c / j a v a s c r i p t s / l e a k . j s w i n d o w . f o o = f u n c t i o n ( ) { c o n s o l e . l o g ( ' t h i s i s f o o ' ) ; } ; w i n d o w . b a z = f u n c t i o n ( ) { c o n s o l e . l o g ( ' t h i s i s b a r ' ) ; } ; ( f u n c t i o n ( e x p o r t s ) { e x p o r t s . b a r = f u n c t i o n ( ) { c o n s o l e . l o g ( ' t h i s i s b a z ' ) ; } ; } ) ( w i n d o w ) ; w i n d o w をe x p o r t に置きかえる( 結構強引) deglobalify

Slide 24

Slide 24 text

With naive style (exposify) / / p u b l i c / j a v a s c r i p t s / l e a k . j s w i n d o w . f o o = f u n c t i o n ( ) { c o n s o l e . l o g ( ' t h i s i s f o o ' ) ; } ; w i n d o w . b a z = f u n c t i o n ( ) { c o n s o l e . l o g ( ' t h i s i s b a r ' ) ; } ; ( f u n c t i o n ( e x p o r t s ) { e x p o r t s . b a r = f u n c t i o n ( ) { c o n s o l e . l o g ( ' t h i s i s b a z ' ) ; } ; } ) ( w i n d o w ) ; グロー バルリー クが解消されるわけではない exposify

Slide 25

Slide 25 text

With AMD (deamdify) / / s r c / d e a m d i f y . j s v a r f o o = r e q u i r e ( ' . / a m d _ f o o ' ) ; f o o ( ) ; / / s r c / a m d _ f o o . j s d e f i n e ( f u n c t i o n ( ) { r e t u r n f u n c t i o n ( ) { c o n s o l e . l o g ( ' t h i s i s f o o ' ) ; } ; } ) ; AMD スタイルのモジュー ルを透過的にr e q u i r e ( ) deamdify

Slide 26

Slide 26 text

With CoffeeScript (coffeeify) / / s r c / c o f f e e i f y . j s v a r f o o = r e q u i r e ( ' . / c o f f e e _ f o o . c o f f e e ' ) ; f o o ( ) ; / / s r c / c o f f e e _ f o o . c o f f e e m o d u l e . e x p o r t s = - > ( c o n s o l e . l o g ' t h i s i s f o o ' ) coffeeify

Slide 27

Slide 27 text

With handlebars (hbsfy) / / s r c / h b s f y . j s v a r t e m p l a t e = r e q u i r e ( ' . / t e m p l a t e . h b s ' ) ; c o n s o l e . l o g ( t e m p l a t e ( { a n i m a l : ' s h e e p ' } ) ) ; / / s r c / t e m p l a t e . h b s I a m a { { a n i m a l } } テンプレー トをコンパイルして関数化 hbsfy

Slide 28

Slide 28 text

With bower (debowerify) / / s r c / d e b o w e r i f y . j s v a r m o m e n t = r e q u i r e ( ' m o m e n t ' ) ; c o n s o l e . l o g ( m o m e n t ( ) . f o r m a t ( ) ) ; bower 由来のモジュー ルを透過的にrequire() できる debowerify

Slide 29

Slide 29 text

And more ... ES6 をES5 にコンパイル fs.readFileSync() のインライン展開 less のコンパイル es6ify brfs lessify などなど 詳しくは を参照 list of transforms

Slide 30

Slide 30 text

Conclusion & Discussion

Slide 31

Slide 31 text

Conclusion browserify は Node ライクのモジュー ルシステム サー バサイドJS の資産を活用できる Stream との親和性が高い transform による柔軟な前処理

Slide 32

Slide 32 text

Too much scope? なんでもかんでも任せすぎなのでは? browserify は「 汎用的な」 プリプロセッサ? Node で直接動くコー ドしかbrowserify しないのも手? タスクランナー との使い分け gulp‑coffee/coffeeify grunt‑contrib‑handlebars/hbsfy

Slide 33

Slide 33 text

Further topics ビルドの速度計測、 キャッシュや並列化 ライブラリ配布の際のベストプラクティスとは? クライアント/ サー バでコー ドの共有 (cf. ) dnode

Slide 34

Slide 34 text

ありがとうございました