くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

unjs/unbuildに入門してみた

pnpm workspace+TypeScriptなmonorepoで、
Cloud Functions for Firebaseを開発していたときに、
unjs/unbuildでビルドしてみたときの備忘録(*´ω`*)

少ない設定でビルドができて便利(*´ω`*)

unbuildとは

「A unified JavaScript build system」らしい。
Viteがフロントエンド用のビルドに対し、
unbuildはライブラリなどによさそうな印象

  • 少ない設定でESM/commonjs+型定義を生成できる
  • package.jsonからビルド設定を自動で取得
  • package.jsonの設定やdependenciesの過不足を自動チェック

ビルドする方法は2つあり、rollupとmkdistを使っている

  • rollup: 複数のファイルを1つにまとめる(バンドル)
    • importしてるファイルを1つにまとめてくれる
    • dependenciesに指定されているものはそのまま利用する
    • devDependenciesに指定されてるものはバンドルしてくれる
  • mkdist: バンドルしないシンプルなトランスパイル
    • ディレクトリ構造そのままに、ファイルごとにトランスパイルしてくれる

なので、monorepoの共通プロジェクトも、
rollupを使って、devDependenciesに指定しておけば、
全部バンドルしてくれるので、だいぶ便利に(*´ω`*)

シンプルな使い方

READMEに書かれているのはこんな感じ。

src/index.tsにファイルを用意して、

// src/index.ts
export const log = (...args) => {
  console.log(...args);
};

package.jsonに設定を追加して、

// package.json
{
  "type": "module",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "types": "./dist/index.d.ts",
  "files": ["dist"]
}

コマンドを実行すればOK

$ npx unbuild

すると、こんな感じに作成してくれる。

./dist/
├── index.cjs
├── index.d.cts
├── index.d.mts
├── index.d.ts
└── index.mjs

設定ファイル

build.config.tsを使って細かい設定ができる

import { defineBuildConfig } from "unbuild";

export default defineBuildConfig({
  // ビルドするファイルは、entriesで指定する
  entries: [
    // ファイルを指定すると、rollupでビルド
    "./src/index",
    
    // ディレクトリを指定すると、mkdistでファイルごとのトランスパイル
    {
      builder: "mkdist",
      input: "./src/package/components/",
      outDir: "./dist/components",
    },
  ],

  // 型定義ファイル(.d.ts)を生成する場合は、trueにする
  declaration: true,
  
  // waringのときでもエラーにしない場合は、falseにする
  failOnWarn: false,
});

entries.builderは、特は指定なければ、

  • ファイル(末尾が"/"でなない)場合は、rollup
  • ディレクトリ(末尾が"/")の場合は、mkdist

が利用されるよう

cjsを出力する

build.config.tsを利用する場合、
デフォルトでは.cjsが出力されない。

rollupとmkdirでは設定の仕方が異なる

rollup

import { defineBuildConfig } from "unbuild";

export default defineBuildConfig({
  entries: [
    {
      builder: "rollup"
      input: "./src/index",
      outDir: "./dist",
    },
  ],

  // rollupの場合は、ここで設定
  rollup: {
    emitCJS: true,
  },
});

mkdist

mkdistの場合は、entiresでそれぞれ指定する

import { defineBuildConfig } from "unbuild";

export default defineBuildConfig({
  entries: [
    {
      builder: "mkdist",
      input: "./src/package/components/",
      outDir: "./dist/components",
    },
    {
      builder: "mkdist",
      input: "./src/package/components/",
      outDir: "./dist/components",
      format: "cjs", // commonjs形式を指定
      ext: "cjs", // 拡張子を指定しないと、jsになる
    },
  ],
});

minifyする

なにもしてしないとminifyされないので、
個別に指定する必要がある。

rollup

import { defineBuildConfig } from "unbuild";

export default defineBuildConfig({
  entries: [
    {
      builder: "rollup"
      input: "./src/index",
      outDir: "./dist",
    },
  ],

  // rollupの場合は、ここで設定
  rollup: {
    esbuild: {
      minify: true,
    }
  },
});

mkdist

mkdistの場合は、entiresで指定する

import { defineBuildConfig } from "unbuild";

export default defineBuildConfig({
  entries: [
    {
      builder: "mkdist",
      input: "./src/package/components/",
      outDir: "./dist/components",
      esbuild: {
        minify: true,
      },
    },
  ],
});

特定の文字列を置き換える

一部の文字列や変数などをビルド時に置き換えたい場合

rollup

import { defineBuildConfig } from "unbuild";

export default defineBuildConfig({
  entries: [
    {
      builder: "rollup"
      input: "./src/index",
      outDir: "./dist",
    },
  ],

  // rollupの場合はここ(@rollup/plugin-replaceで置き換え)
  replace: {
    "process.env.FOO": `"bar"`,
  },
  // or 
  rollup: {
    // esbuildのdefineで置き換える
    esbuild: {
      define: {
        "process.env.FOO": `"bar"`,
      }
    }
  },
});

mkdist

mkdistの場合は、entiresで指定する

import { defineBuildConfig } from "unbuild";

export default defineBuildConfig({
  entries: [
    {
      builder: "mkdist",
      input: "./src/package/components/",
      outDir: "./dist/components",
      // esbuildのdefineで置き換える
      esbuild: {
        define: {
          "process.env.FOO": `"bar"`,
        }
      },
    },
  ],
});

以上!! 少ない設定でバンドルあり/なしでビルドできて便利...(*´ω`*)