Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

モジュールバンドラーが知らぬ間に増えていた

モジュールバンドラーというと

  • Webpack
  • Browserify
  • rollup
  • Require.js

あたりは知名度があると思います(rollupはそうでもないかも知れませんが)。しかし、乱世のJavaScript界隈、気が付けばかなりの数のモジュールバンドラーが乱立していました。今回はそんな中から、JSPM、Fusebox、StealJSを紹介しようと思います。

JSPM

JSPMの最大の特徴は、動的バンドルです。npm run buildしなくても勝手にバンドルしてくれるので直接実行できます!もちろんwatchも不要です!

メリット

  • 手動でバンドルする必要がない(動的にバンドルしてくれる)
  • npmやGitHubのものも読み込める

デメリット

  • パンドラというよりパッケージマネージャ的な側面が大きい
  • グローバルインストールする必要がある
  • SystemJSを使っている関係で、サーバを立ち上げないと実行できない

ここら辺がいけてないなぁと感じました。サーバを立ち上げる方はともかく、バンドルしたいだけなのに、えらくデカいものを使う感じがしてあまり好きになれそうにないです。

グローバルを汚したくなかったので、JSPMはそもそもインストールして試してすらいません。すみません。やはりグローバルにインストールするのがよくないですね。

FuseBox

FuseBoxはなんとJSPMとwebpack、SystemJSのいいとこどりだと公式で謳っていますさっそくJSPMがいらない子に…バンドルも高速です。

メリット

  • グローバルインストール不要
  • Rollupと連携できるのでツリーシェイキングが使える

デメリット

  • JSPMのように動的バンドルをしてくれない
  • node fuseでバンドルするのが違和感がある
  • TypeScriptを強要してくる
  • コンフィグを書くのがめんどくさい

公式が「インストールコマンドはnpm i typescript fuse-box --save-devだよ(暗黒微笑)」と書いてTypeScriptを強要してくる点は大きなマイナスポイントですね。TS使っていませんし。

試しにfuse-boxだけでインストールしてバンドルしてみたところ「Cannot find module 'typescript'」とエラーが出ました。TypeScriptのインストールなしにはバンドルできないようです。JavaScriptで書いているのに、バンドルするためだけにTypeScriptをインストールするというのはなんとも滑稽ですよね?

TypeScript使いにはもってこいかもしれませんね。わかりませんが。

StealJS

英語読めない民なのでホームページを斜め読みしつつ実際に書いてみたところ、StealJSこそがバンドラー界の神だと気が付きました。

メリット

  • グローバルインストールが必要ない
  • 手動でバンドルする必要がない(動的にコンパイルしてくれる)
  • もちろんwatchする必要もない
  • scriptファイルはsteal.jsを読み込むだけでいい
  • 特殊な記法を強要されない(将来ES Modulesにブラウザが対応したとき、steal.jsを外すだけで済む)
  • ES ModulesやAMD、CommonJSをサポートしている
  • 余計なコンフィグをズラズラ書かなくていい

デメリット

  • 動的にバンドルするため、どんな単純なプログラムでもバンドル終わるまで5秒はかかる

Fusebox、JSPM、Rollupのいいとこどりって感じです。あと遅くなければ神なんですけどね…

サンプルコード

プログラムサンプル書くとこんなかんじです。

<!DOCTYPE html>
<html>
  <body>
    <script src="./node_modules/steal/steal.js"></script>
  </body>
</html>

なんと、HTML部分はこれ以上書く必要がありません!これで完結しています。

大まかな動作を解説すると、steal.jsがpackage.jsonのmainに書いたファイルを読み込みに行きます。その後、そのファイルの中のimportやrequireなどを動的に解決していきます。

たとえばindex.js(mainのデフォルト値)に次のようにかいたとします。

import {hoge} from './hoge.js';
alert(hoge);

あとは先ほどのHTMLをブラウザで開いてみてください。きちんと実行されたはずです。そうです、コンパイルする必要すらありません。動的にバンドルしてくれるので、ファイルを更新した後もブラウザをリロードすれば変更が反映されます。

requireだろうとimportだろうと全部解決してくれます。

バンドルが遅い

いろいろ良いところを書きましたが、一つだけ問題があります。それは動的にコンパイルしているため動作が遅れることです。上の例ですらダイアログが表示されるまで5秒程度かかります。それならwatchしてバンドルした方がましですよね。

どれだけ遅いのか実際に作ってみたのでご確認ください。

動的バンドル

バンドル済み

バンドル済みのほうが圧倒的に早いですよね。

終わりに

StealJSがもっと早かったらStealJS一択なんですけどね…現状ではまだwatchコマンドで監視してRollupでバンドルするのが一番っぽいですね。残念。