Vite でライブラリを作る

Vite で npm に公開するライブラリを作成する方法を紹介します。今回は React ライブラリを作成する手順を紹介しますが、基本的な手順は Vue.js 及び vanilla JavaScript でライブラリをつくる場合でも同じだと思います。

npm に公開するライブラリを開発する場合は、ライブラリを複数のモジュール形式で利用できるような工夫や、ライブラリに特定の依存関係はバンドルしたくない場合の対応が必要になります。Vite のライブラリモードを活用することで、そのような実装を簡単に行うことができ、なおかつ開発環境でライブラリをインポートしたテスト or デモページを簡単に用意することが可能です。

Vite プロジェクトの作成

まずは、何はともあれ Vite のプロジェクトを作成します。公式ドキュメントに書かれている内容に従って、npm create vite@latest を実行します。今回は React × TypeScript で環境を立ち上げたいので、画面表示に従って framework に react を variant に react-ts を選択します。すると、以下のようにプロジェクトが自動で作成されます。

❯ npm create vite@latest
✔ Project name: … vite-sample
✔ Select a framework: › react
✔ Select a variant: › react-ts

Scaffolding project in /Users/username/path/to/vite-sample...

Done. Now run:

  cd vite-sample
  npm install
  npm run dev

ターミナル上で案内されている通りに作成したプロジェクトに移動し、npm install を行います。その後 npm run dev を実行すると以下のようにスタートページが表示できます。


プロジェクトのルートディレクトリには vite の設定ファイルである vite.config.ts が生成されています。この状態では ↓ のようになっています。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()]
})

ここまでできたら Vite プロジェクトの作成は完了です。

ライブラリモードの設定

Vite にはライブラリを開発するときに便利なライブラリモードという機能があります。この機能を使うことで、ライブラリを複数のモジュール形式で利用できるようにビルドすることができます。build.lib 設定オプションを設定することで使用できます。今回はグローバル変数として公開するライブラリの変数名を SampleLib 、出力されるファイル名をsample-lib としてビルドするように設定してみます。

import { resolve } from 'path'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    lib: {
      entry: resolve(__dirname, 'src/index.ts'), // エントリポイント
      name: 'SampleLib', // グローバル変数として公開するライブラリの変数名
      fileName: 'sample-lib', // 生成するファイルのファイル名を指定します。
      formats: ['es', 'umd'], // 生成するモジュール形式を配列で指定します。デフォルトで['es', 'umd'] なのでこの場合はなくても大丈夫です。
    },
  },
  plugins: [
    react(),
  ],
})

これで、npm run build を実行することで sample-lib.js と sample-lib.umd.cjs というファイルが生成されます。それぞれ ES module 形式と UMD 形式でビルドされたファイルになります。これでライブラリを複数のモジュール形式で利用できるようになりました。

また、React や Vue.js などに依存したライブラリを作成する場合、これらのライブラリはライブラリを使用する側でインストールして利用し、ライブラリにはバンドルしたくないといったことがあります。このような場合には rollupOptions.external 及び rollupOptions.output.globals の設定オプションを利用することで解決することができます。例えば、React のライブラリを作成する場合は vite.config.ts を以下のように記載します。

import { resolve } from 'path'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    lib: {
      entry: resolve(__dirname, 'src/index.ts'),
      name: 'SampleLib',
      fileName: 'sample-lib',
    },
    rollupOptions: {
      external: ['react'], // バンドルしたくない依存関係を指定
      output: {
        globals: {
          react: 'React', // UMDビルド時に、external指定した依存関係をscript タグで読み込まれた場合に使用される変数名を指定
        },
      },
    },
  },
  plugins: [
    react(),
  ],
})

これで、ライブラリに特定の依存関係はバンドルしないようにすることができます。

ライブラリモードについては公式ドキュメントで詳しく説明されています。より詳細な情報を知りたい場合は公式ドキュメントを確認してください。

これで、Vite を活用して JavaSciprt をライブラリとしてビルドすることができるようになりました。

開発環境でライブラリをインポートしたデモページを用意する

ここからは、ライブラリの開発環境でライブラリをインポートしたデモページを作成する方法を解説します。

ライブラリを開発する場合には、ライブラリをインポートしてテストするデモページを用意する必要がありますよね。Vite を活用することでこういったデモページを簡単に用意することができます。

まず、エントリポイントである html ファイルを用意します。デフォルトではプロジェクトルートに index.html が存在しますが、デモページだということをわかりやすくするために examples というディレクトリを作成し、その直下に index.html をでもページとして設置したいと思います。

まず、examples ディレクトリをプロジェクトルートに作成し、その直下に index.html を作成します。index.html の中身は ↓ のようにシンプルです。気をつけるところは script タグに type="module" を指定することです。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Sample Lib Example</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="./src/index.tsx"></script>
  </body>
</html>

次にライブラリをインポートして実行するファイルを用意します。今回は、examples ディレクトリ直下に src/index.tsx ファイルを作成します。

import React from 'react'
import ReactDOM from 'react-dom/client'

import SampleLib from '../../src' // ライブラリのインポート

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <SampleLib />
  </React.StrictMode>
)

これで準備はOKです。 npm run dev コマンドを実行して開発サーバーを起動し、http://localhost:5173/examples/index.html にアクセスするとライブラリのデモができていることが確認できます。

このように Vite を活用することでデモページを簡単に用意することができるようになります。便利ですね。

ライブラリに CSS を含める

JavaScript のライブラリですが、CSS を含めたいという場合があると思います。ただ、Vite のライブラリモードを使用して CSS をビルドするとファイル名が style.css 固定になってしまうという問題があります。github から vite の issue を調べてみるとこの問題に対する issue を見つけましたが、具体的な解決策はまだないようでした。

そこで、CSSに関しては vite をつかってビルドするのではなく、独自でビルドすることで対応します。

自分でビルド環境を立ち上げるにあたって必要なことは scss のビルドと、postcss による autoprefixer の実行です。幸い それぞれ cli で実行できるので npm scripts を使って実行するようにしたいと思います。package.json の scripts を以下のように記述します。

"scripts": {
    "dev": "vite",
    "build": "npm run build:js && npm run build:css",
    "build:js": "tsc && vite build",
    "build:scss": "sass --no-source-map --style=compressed scss/sample-lib.scss:css/sample-lib.css",
    "build:postcss": "postcss css/*.css -r",
    "build:css": "npm run build:scss && npm run build:postcss"
  },

また、autoprefixer を実行するための postcss の設定ファイルを用意します。

const autoprefixer = require('autoprefixer');

module.exports = {
  plugins: [
    autoprefixer(),
  ]
}

また、npm で sasspostcsspostcss-cliautoprefixer をインストールする必要があります。

$ npm i -D sass postcss postcss-cli autoprefixer

これで npm run build:css を実行することで CSS をビルドすることができるようになります。

開発時は vite のエントリポイント である index.html で SCSS ファイルを読み込めば、vite が自動的に SCSS から CSS への変換と PostCSS の適用を行ってくれます。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="../scss/sample-lib.scss">
    <title>Sample Lib Example</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="./src/index.tsx"></script>
  </body>
</html>

まとめ

vite で npm に公開するライブラリを作るための開発環境を準備する手順の説明はこれで終了です。CSS の取り扱いには少し困りましたが、その他の部分は意外と簡単だったのではないでしょうか? Vite は開発モード時にネイティブ ESM を使用して依存関係を解決するため、Webpack と比べビルド時の時間が短く、開発体験が良いです。これを読んでいただいた皆様もこれを機に活用してみてはいかがでしょうか?


Related Posts