deno bundle
コマンドは非推奨になった
deno bundle
コマンドはTypeScriptファイルをJavaScriptファイルに変換するコマンドです。
Deno v1.31以降、deno bundle
コマンドは非推奨になりました。
この記事ではdeno bundle
コマンドの代替手段である2つの方法について解説します。
方法1. deno_emitを使う
deno_emitはDeno社が公式に管理・配布しているライブラリです。
こちらのライブラリはRust製バンドラーであるswcをWeb Assembly化してJavaScriptから使えるようにしたものです。
このライブラリ自体は現在もDeno CLIの内部で使用されているため、この先もメンテナンスが継続される可能性が高いです。
使い方は以下のようになります。
import { bundle } from "https://deno.land/x/emit/mod.ts";
const url = new URL(import.meta.resolve("./path/to/file.ts"));
const { code } = await bundle(url);
console.log(code);
// Deno.writeTextFile("./path/to/file.js", code);
また、バンドルせずに1ファイルずつトランスパイルするには、以下のようになります。
import { emit } from "https://deno.land/x/emit/mod.ts";
const url = new URL(import.meta.resolve("./path/to/file.ts"));
const result = await emit(url);
上記の方法だと、下の画像のように依存関係も含めた全てのファイルがトランスパイルされます。
対象のファイルだけトランスパイルしたい時には、emit
関数に対してload
オプションを渡して制御します。
const targetUrl = new URL(import.meta.resolve("./path/to/file.ts"));
const content = await Deno.readTextFile(url);
const targetUrlStr = targetUrl.toString();
const result = await emit(targetUrl, {
load(specifier) {
if (specifier !== targetUrlStr) {
return Promise.resolve({
kind: "module",
specifier,
content: "",
headers: { "content-type": "application/javascript; charset=utf-8" },
});
}
return Promise.resolve({
kind: "module",
specifier,
content,
headers: {
// (http://esm.sh/react など)対象ファイルのURLに拡張子が無い場合は必要に応じて追加↓
// "content-type": "text/typescript; charset=utf-8",
// "content-type": "text/jsx; charset=utf-8",
// "content-type": "text/tsx; charset=utf-8",
},
});
},
});
console.log(result[targetUrlStr]);
方法2:esbuildを使う方法
esbuildを使うこともできます。
esbuildにはDeno向けプラグインが用意されているため、これを利用してDenoのコードをトランスパイルすることができます!
こちらのプラグインはDenoコアチームのlucaさんによって管理されています。
また、Deno公式フレームワークであるFreshの内部でも使用されているため、今後もメンテナンスが継続される可能性が高いです。
コード例は以下のようになります。
import * as esbuild from "https://deno.land/x/esbuild@v0.15.10/wasm.js";
import { denoPlugin } from "https://deno.land/x/esbuild_deno_loader@0.6.0/mod.ts";
const result = await esbuild.build({
plugins: [denoPlugin()],
// 対象ファイル名
entryPoints: ["https://deno.land/std@0.173.0/async/mod.ts"],
outfile: "./test.js",
// バンドルするかどうか。
// trueにすると依存関係も含めて1ファイルにまとまる。
// falseにすると対象ファイルの内容のみがトランスパイルされる。
bundle: true,
format: "esm",
});
if (result.outputFiles) {
for (const { path, contents, text } of result.outputFiles) {
console.log(path);
console.log(contents); // トランスパイル結果(Uint8Arrayのバイナリ形式)
console.log(text); // トランスパイル結果(文字列)
// await Deno.writeFile(path, contents);
}
}
esbuild.stop();
上記はWasm版のesbuildを使用していますが、バイナリ版のesbuildを使う方法もあるので、公式ドキュメントを参考にしてみてください。
バイナリ版はwasm版より高速である一方、バイナリがローカルにDLされるのでディレクトリが汚れる、--allow-run
パーミッションが必要になる、deno deploy非対応などのデメリットがあるため、速度を追い求める場面でなければwasm版で十分だと思われます。
※一つ注意点として、プログラム側からimportするesbuildのバージョンと、プラグイン内で使っているesbuildのバージョンが一致しない場合、エディタで型エラーが発生することがあります。実行するにあたって問題はありませんが、気になる場合は適宜バージョンを調整してみてください。
まとめ
-
deno bundle
はDeno v1.31以降非推奨- おそらく2.0で削除される
- 代替手段は deno_emit か esbuild + esbuild_deno_loader
- deno_emit
- swc使用(Rust製)
- wasm
- deno_deploy対応
- Denoコアチームから配布されている
- esbuild + esbuild_deno_loader
- Go言語製
- wasmとバイナリのどちらを使用するか選べる
- deno_deploy対応
- esbuild_deno_loaderはDenoコアチームメンバーから配布されている
- deno_emit
実質、Rust製バンドラーであるswcとGo言語製バンドラーであるesbuildの2択になっています。
とはいえどちらも充分高速に実行されるため、どちらを選ぶかは本当に好みになります。
筆者はesbuildのAPIの方がイケてるような気がしますが、DenoとswcはどちらもRust製で親和性が高いかなと思ったので、普段はdeno_emitの方を使うことが多いです。