LoginSignup
11
1

More than 1 year has passed since last update.

`deno bundle`が非推奨になったので代替手段(swc、esbuild)

Last updated at Posted at 2023-03-07

deno bundleコマンドは非推奨になった

deno bundleコマンドはTypeScriptファイルをJavaScriptファイルに変換するコマンドです。

Deno v1.31以降、deno bundleコマンドは非推奨になりました

非推奨になった理由としては、こちらこちらのissueで解説されています。

要約すると、

  • deno bundleは元々サーバーサイド向けで、依存関係を1ファイルにまとめるだけの単純なバンドラーだった
  • フロントエンド向けのバンドラーとして使うにはminifyやtree shaking、プラグインシステム、npm互換性、top-level-await対応などの多くの機能が足りない
  • deno bundleにそのような機能を実装するよりも、既存のesbuildやswcなどの優れたツールを使うことをおすすめする

という事でした。

この記事では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);

上記の方法だと、下の画像のように依存関係も含めた全てのファイルがトランスパイルされます。

image.png

対象のファイルだけトランスパイルしたい時には、emit関数に対してloadオプションを渡して制御します。

1ファイルだけトランスパイルする方法
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_emitesbuild + esbuild_deno_loader
    • deno_emit
      • swc使用(Rust製)
      • wasm
      • deno_deploy対応
      • Denoコアチームから配布されている
    • esbuild + esbuild_deno_loader
      • Go言語製
      • wasmとバイナリのどちらを使用するか選べる
      • deno_deploy対応
      • esbuild_deno_loaderはDenoコアチームメンバーから配布されている

実質、Rust製バンドラーであるswcとGo言語製バンドラーであるesbuildの2択になっています。
とはいえどちらも充分高速に実行されるため、どちらを選ぶかは本当に好みになります。

筆者はesbuildのAPIの方がイケてるような気がしますが、DenoとswcはどちらもRust製で親和性が高いかなと思ったので、普段はdeno_emitの方を使うことが多いです。

11
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
1