2020/06/08 追記
この記事は Snowpack v1 の記事で、かなり古い内容になっています。先日リリースされた Snowpack v2 については、下記の記事がよくまとまっています。
https://qiita.com/kazuma1989/items/30676cb3d2da1c873507
はじめに
Node.js の登場により JavaScript の世界にモジュールの概念が導入されました。そして npm によって多くの JavaScript パッケージが配布されるようになりました。
しかし、Node.js のモジュールシステムは当然ブラウザでは動かず、古の Web ブラウザではモジュールを解決する仕組みがありませんでした。
そのためモダン Web 開発においては、 webpack や Rollup のようなモジュールバンドラを用いて、依存するモジュールを含む単一の JavaScript ファイルを生成するのが一般的です。
Node.js の登場から数年経ち、Google Chrome を始めとするモダンブラウザでは ECMAScript 2015 から導入された ECMAScript Modules (以下 ESModules) というモジュールシステムが実装されて、モジュールバンドラを使うことなくモジュールを使うことができるようになりました。
Fred K. Schott によって開発された Snowpack1 は、ESModules を用いたモジュールバンドラを使わない2モダン Web 開発のためのツールです。
やってくれること
Snowpack の主な役割は依存パッケージのセットアップです。アプリケーション自体のソースコードに手を加えることはありません。
package.json やソースコードから依存するパッケージを抽出し、それぞれのパッケージを単一の JavaScript ファイルとして /web_modules
ディレクトリに配置します。
アプリケーションからは単純に /web_modules
内のパッケージを import するだけです。
やってみる
package.json の存在するディレクトリで下記コマンドを実行すると、 dependencies
のパッケージを /web_modules
ディレクトリにインストールします。
npx snowpack
もしくは -include
オプションを用いて、ソースコードから依存するモジュールを解析することもできます。
npx snowpack --include \"dist/**/*.js\"
インストールしたパッケージはアプリケーションからは相対パスで import することができます。例えば Hyperapp が dependencies
にある場合はこのようになります。
import { h, app } from "/web_modules/hyperapp.js";
また、TypeScript や Babel との連携も容易です。いつも通りトランスパイルしてから、それに対して Snowpack をかけます。
babel src/ -d dist
npx snowpack --include \"dist/**/*.js\" --dest dist/web_modules
詳しくは Hyperapp と Babel を用いたサンプルを作ったので、こちらを参照してください。 package.json の scripts あたりから適当にたどるとわかりやすいと思います。
https://github.com/Monchi/snowpack-hyperapp
モジュールバンドラは時代遅れか
決してそんなことはなく、Snowpack はモジュールバンドラを完全に置き換えるものではありません。
まず、Snowpack は ESModules 前提のツールです。IE のように ESModules が使えないレガシーブラウザをサポートすることができません。
追記: バンドルもできるようになりました
https://qiita.com/yukukotani/items/dfe236d29f97b0986b91#comment-db2dd39b38dcf1600968
また、モジュールバンドラの役割はもはや純粋なモジュールのバンドルだけにとどまりません。例えば webpack では各種 loader を用いて CSS や画像などを import することができますが、これは標準の ESModules の仕様には含まれていないため、ブラウザでは今のところ実現できません。
パフォーマンス面も一長一短です。モジュールバンドラは依存の依存まで含めて重複パッケージをまとめることができますが、Snowpack は依存パッケージごとに単一の JavaScript ファイルを生成するため、それができません。
一方で、Snowpack では依存パッケージごとに Code Splitting されているということでもあります。HTTP/2 や HTTP/3 の並列配信の恩恵を受けることができますし、将来的に Dynamic Import が実装されたら、パッケージを非同期に import してチューニングすることもできるでしょう。
モジュールバンドラを選ぶ理由は多くありますが、Snowpack はゼロロックインをコンセプトとしており、容易にこれまでのモジュールバンドラに戻ることができます。実際、Snowpack 特有の設定などはないですし、ECMAScript の仕様に準拠しています。移行ガイドもあるので、新規プロジェクトを Snowpack で初めてみるのは十分に現実的です。
最後に
Snowpack は極めてシンプルで、多くの機能は持ちません。その分ドキュメントにはその思想や背景が細かく書いてあるので、気になる方は読んでみてください。
まだプロダクションではレガシーブラウザを切れないケースが多いかと思いますが、近未来の Web 開発を感じることができるかと思います。また、Snowpack は Pika エコシステムの一部で、パッケージレジストリや CDN としても発展していくようなので、チェックしとくと面白そうです。
何か間違ったことを書いてしまっていたらコメントで教えてください。