viteでNode向けパッケージをバンドルする方法
Tech
js/ts
状況
tsで書いたコードをnpm package向けにjsにコンパイルしたい
テストは、Vitestを使っている
Viteは基本的にブラウザ向けビルドツール
Viteはデフォルトでブラウザ向けに最適化されている(*1,*2)ため、Node向けパッケージとして利用する場合、いくつかの前提ズレが発生する
- エントリーポイントは
index.html - 依存関係は基本すべてバンドル対象
- Node built-in(fs, pathなど)は警告対象
- ブラウザ互換性優先でモジュールが外部化されることがある
そのためNode向けパッケージとして使う場合は追加設定が必要になる
ViteでNodeライブラリを作る場合
問題と解決手段
- エントリーポイントの設定: libraryモードを使う
- 依存関係の外部化: SSRモードかrollup-plugin-node-externalsプラグインを使う
- .d.tsの生成: unplugin-dtsプラグインを使う
- sourcemapの生成: build.sourcemapをtrueにする
参考: https://github.com/vitejs/vite/issues/8910
vite.config.ts
import { defineConfig } from "vite";
import dts from "unplugin-dts/vite";
export default defineConfig({
plugins: [dts()],
build: {
lib: {
entry: "src/index.ts",
formats: ["es"],
fileName: "index",
},
ssr: true,
sourcemap: true,
},
});Vite+を使うという選択肢
上記からわかるように、Viteはあくまでブラウザ向けのバンドラーなので
Nodeライブラリとしてバンドルする場合は、プラグインやSSRモードなどで無理矢理設定を作るしかないので
一般的には、tscやtsdownの利用が推奨されるが、tscはtsgoへの移行が安定化するまではあまり使いたくなくて
tsdownは、tsdown.config.tsを追加する必要があって、設定ファイルが増えるのはあまり気乗りしない
それを解決するのがVite+である
Vite+は内部でtsdownを利用しているが、その設定はvite.config.tsに書ける
すでにVitestのためにvite.config.tsを用意してあるため、設定ファイルが増えないのは大きな利点である
問題と解決手段
- エントリーポイントの設定: デフォルトでsrc/index.ts
- 依存関係の外部化: deps.skipNodeModulesBundleをtrueにする
- .d.tsの生成: dtsオプションは、デフォルトで有効
- sourcemapの生成: build.sourcemapをtrueにする
vite.config.ts
import { defineConfig } from "vite-plus";
export default defineConfig({
pack: {
deps: {
skipNodeModulesBundle: true,
},
dts: {
sourcemap: true,
},
},
});選択肢の比較
| 問題 | Vite | tsdown | Vite+ |
|---|---|---|---|
| エントリーポイントの設定 | ○ | ○ | ○ |
| 依存関係の外部化 | △ (SSR-mode or 外部plugin) | ○ | ○ |
| .d.ts生成 | △ (外部plugin) | ○ | ○ |
| Source Mapの生成 | ○ | ○ | ○ |
| 設定ファイルの増加 | ○ (vite.config.ts) | × (別config) | ○ (vite.config.ts統合) |
Vite+は内部でtsdownを利用しているので、設定項目などはすべて同じで、設定ファイルを1つにまとめられるかどうかという点だけが異なる
まとめ
Nodeライブラリ用途ではVite単体は設計がブラウザ寄りで扱いづらい
tsdownを使うべきだけど、設定ファイルを増やしたくない
という状況にVite+が最適なツールだと判断した