🌐

Denoでブラウザで動くJSファイルをビルドするには

2022/01/16に公開約2,400字

DenoでTypeScriptをブラウザで動くJavaScriptにビルドしたかったため調査した結果です。欲しい機能は以下です。

  • JavaScriptモジュール(ES Modules)形式で出力したい。
  • TypeScriptをJavaScript変換したい。
  • Minifyしたい。
  • 動的インポートで書いたファイルをコード分割したい。
  • Tree Shakingしたい。
  • 設定ファイル無し、コマンド一発でビルドしたい。

Denoのビルドツール

結論を述べるとDenoはまだまだ人口が少なくサードパーティモジュールが充実しておらず、これらの機能を満たすビルドツールがありませんでしたので、作ることにしました。

Denoバンドル

実は私もビルドツールを探し回っているときに知ったのですが、Deno標準のdeno bundleコマンド、およびDeno.emit()APIは、サーバーサイド・フロントエンド両用ではありません。
私はこれらを、サーバーサイドとブラウザの両方で使うためのバンドルツールだと勘違いしていましたこちらの解決済みのISSUEを読むと、開発陣はdeno bundleはあくまでDenoで実行されるスクリプトを一つのファイルにまとめるために作ったというようなことを言っています。
公式マニュアルにはバンドルしたファイルがブラウザでもインポートできることが書かれていますので私は勘違いしてしまったのですが、それはDenoもブラウザも同じES Modulesなのでブラウザ向けのバンドルもできてしまうというだけだったのですね。
ということで、遠い将来は方針変更があるかもしれませんが、少なくともしばらくはDenoにブラウザ向けビルドツールが組み込まれることは無さそうです。
そもそもDenoはNode.jsと同じくサーバーサイドJavaScript実行環境ですので当たり前ですね。

Packup

https://packup.deno.dev/

PackupはParcel風のDeno用バンドルツールです。DenoのサードパーティモジュールはDenoのバージョンアップに追従していけていないものが多く、インストールしても動かないものがあったりするのですが、2022/01/17現在これは動きました。

欲しかった機能のほとんどを満たすのですが、動的インポートができなかったため今回は見送りました。

まだできることが少ないのですが、将来が期待されます。

SWC

https://swc.rs/

SWCはRustで書かれたビルドツールです。最近はとても盛り上がっているように感じます。DenoもRustで書かれており、Denoの型チェックに使っているとのことですが、残念ながらまともに動くサードパーティモジュールがありませんでした。

esbuild

https://esbuild.github.io/

esbuildは公式にDenoでの使い方が書かれています。ちゃんと動きます。
ES Modulesも、TypeScriptも、Minifyも、動的インポートも、Tree Shakingもサポートしています。2022/01/17現在Denoで唯一まともなビルドツールと言えるかと思います。

しかし、残念なことにhttpsから始まるDenoのモジュールをインポートすることができません。また、今のところコマンドがありません。

結局どうしたらいいか

他にもDenoのビルドツールはありますが、動くかどうか確かめるだけでもひと苦労です。

Node.jsのような気軽な感じが全く無い・・・。

現実的な方法はesbuildを使って、Denoのモジュールを使えるようにするプラグインを合わせて使うことです。

私が開発中のライブラリBeako.jsでは、Denoのビルドツールが充実するまで、独自に簡易ビルドツールを設けることにしました。Beako.js専用ではないのでお困りの際はご利用ください。
あくまで、Denoのビルドツールが充実するまでの措置ですので、将来削除する可能性はあります。

deno moduleプラグイン

esbuild_deno_loaderというモジュールを使うと、httpsから始まるDenoのモジュールをインポートしてビルドすることができるようになります。

beako buildコマンド

上記プラグインだけを使ったesbuildをコマンドにしました。

コマンドをインストール

deno install -fA https://deno.land/x/beako_cli@0.2.0/beako.ts

ビルド実行

beako build script.ts --outdir=public

outdirのデフォルトはdistディレクトリです。ひとつのファイルにバンドルするときは--outfile=script.jsのようにします。

これでようやく欲しい機能がすべて揃いました。

Discussion

ログインするとコメントできます