Bundler について
作りたいアプリがあったので、試作品をCopilotに頼んで作ってもらったところ、まぁまぁいい感じだったので、細かいところを修正加えていく。
でも、最初に何も指示しなかったせいかhtmlとcssとJavaScriptで作られてしまった。これをTypeScriptにしてもらおうとさらにCopilotに直してもらったのだけど、動かなーい💦
その後バンドルすることで再度動き出したので、今日はBundlerについてその役割や、なぜバンドルをしたら直ったのかを紐解いていく。
問題の原因は?
今回TypeScript化と同時に、もう一つやったことがあって、どうやらそれが動かなくなった原因だったみたい。
何をしたかというと、コードを管理しやすく/読みやすくするために、もともと一つのJavaScriptファイルにたくさんのfunctionが詰め込まれていたものを、複数のモジュールに分割して import / export を使う構成に変更していた。
もちろん複数のモジュールに分割した方が可読性や保守性が向上するので、絶対にそうした方がいいんだけど、今回作っているアプリはVS Code Webviewを使ってVS Code内に表示されるアプリのため、どうやらそこに落とし穴があったらしい。
VS Code Webview
VS Code Webview はVisual Studio Code 拡張機能の一部として、サイドバーなどにカスタムコンテンツをiframeで表示する機能のこと。しかしVS Code Webviewは「通常の <script> タグで読み込んだ JavaScript」を想定しており、ES Module が残ったJavaScriptファイルは解釈できないとのこと。
ES Moduleとはimport / export といった構文でファイル間の依存を記述できる仕組みのこと。
Bundler とは何か
今回の不具合の直接の原因は「TypeScript 化そのもの」ではなく、複数のモジュールに分割して import / export を使う構成にしたことだったので、もしもJavaScriptからTypeScriptに変換した際に、1 ファイルのままでコンパイルしていたらそのまま動いてたかも。
そして、モジュール分割によって import / export 構文付きの JavaScript が生成され、それを VS Code Webview が解釈できずに実行が止まった。
じゃあどうすればいいか?「モジュールを束ねる処理」が必要。
バンドル(束ねる)するためにBundlerを使う。
Bundler(バンドラ)とは、複数の JavaScript/TypeScript モジュールを解析して依存関係を解決し、ブラウザでそのまま実行可能なファイルにまとめ上げてくれるツールのこと。Bundler には webpack・Rollup・Vite・Parcel など多くの選択肢があるが、今回は esbuild を採用。Bundler を導入したことで、import されるすべてのモジュールをWebviewが理解できる形に変換し、最終的に単一ファイルに結合されるので、Webviewでも動くようになるというわけ。
修正方法:
- esbuild を devDependency として追加。
- esbuild.webview.config.mjs を用意し、エントリーポイント (webview.ts) と出力先 (webview.bundle.js) を設定。
npm run bundle:webviewというスクリプトを package.json に追加し、compileやwatchフローに組み込み。- Webview 側の HTML では webview.bundle.js を読み込むよう変更。
本日は以上。
