ジャコ Lab

プログラミング関連のメモ帳的ブログです

Vue3 でコンポーネントを作って npm install で使用できるようにするにはどうしたらいいの?

なんで前回、急に Vue を触ったかというと、
npm install 可能な Vueコンポーネント を作りたかったんですよね。

調べてみると Vite のオプションで ライブラリモード なるものがあるようなので、
こちらを使ってみようと思います。

どうやって npm package 化するの?

以下のライブラリモードに記載のあるビルド設定をすればできるっぽい

この記事でのプロジェクト構成

.
├── hello-vue3-lib  # パッケージとして提供する側のプロジェクト
└── vite-project # 提供されたパッケージを使う側のプロジェクト

こちらは、両方とも前回の記事で扱った ViteVue3 のプロジェクトを作ったものになります。
※プロジェクト名が違うだけで、全く同じものです。

前回の記事

パッケージとして提供する側のプロジェクトを作っていく

# 作業ディレクトリの確認
$ pwd
./hello-vue3-lib

vite.config.ts を変更する

+ import { resolve } from 'path'
  import { defineConfig } from 'vite'

  import vue from '@vitejs/plugin-vue'

  // https://vitejs.dev/config/
  export default defineConfig({
+   build: {
+     lib: {
+       // 複数のエントリーポイントのディクショナリや配列にもできます
+       entry: resolve(__dirname, 'lib/index.ts'),
+       name: 'hello-vue3-lib',
+       // 適切な拡張子が追加されます
+       fileName: 'index',
+     },
+     rollupOptions: {
+       // ライブラリーにバンドルされるべきではない依存関係を
+       // 外部化するようにします
+       external: ['vue'],
+       output: {
+         // 外部化された依存関係のために UMD のビルドで使用する
+         // グローバル変数を提供します
+         globals: {
+           vue: 'Vue',
+         },
+       },
+     },
+   },
    plugins: [vue()],
  })

entry になっている lib/index.ts を作成する

Vite のドキュメントによると export すれば良いらしい
◆ まず export するためのコンポーネントを作成する

lib/components/CountUpButton.vue というファイルを作成して以下を定義します。

<template>
  <button class="count-up-button" type="button" @click="count++">
    count is {{ count }}
  </button>
</template>

<script setup lang="ts">
import { ref } from "vue";

const count = ref(0);
</script>

<style scoped>
.count-up-button {
  color: #888;
  background-color: #fcc;
}
</style>
とりあえず、色の付いたカウントアップできるボタンコンポーネントを作成
◆ lib/index.ts の定義を追加
import CountUpButton from "./components/CountUpButton.vue";
export { CountUpButton };

ここでビルドを実施

$ yarn build
yarn run v1.22.22
$ vue-tsc && vite build
vite v5.2.13 building for production...
✓ 5 modules transformed.
dist/style.css  0.07 kB │ gzip: 0.08 kB
dist/index.js   0.59 kB │ gzip: 0.39 kB
dist/style.css      0.07 kB │ gzip: 0.08 kB
dist/index.umd.cjs  0.70 kB │ gzip: 0.47 kB
✓ built in 787ms
Done in 9.36s.
いい感じに出力されたっぽい!

npm package としての設定を package.json に書く

  {
    "name": "hello-vue3-lib",
    "private": true,
    "version": "0.0.0",
    "type": "module",
+   "files": [
+     "dist"
+   ],
+   "main": "./dist/index.js",
+   "module": "./dist/index.umd.cjs",
+   "exports": {
+     ".": {
+       "import": "./dist/index.js",
+       "require": "./dist/index.umd.cjs"
+     },
+     "./dist/style.css": "./dist/style.css"
+   },
    "scripts": {
      "dev": "vite",
      "build": "vue-tsc && vite build",
      "preview": "vite preview"
    },
    "dependencies": {
      "vue": "^3.4.21"
    },
    "devDependencies": {
      "@vitejs/plugin-vue": "^5.0.4",
      "typescript": "^5.2.2",
      "vite": "^5.2.0",
      "vue-tsc": "^2.0.6"
    }
  }
これで、npm package 化は完成と思われる
npm linkは、自作 package を作るときに便利なコマンドらしいです
publish や git push 等を行わなくても、公開された package のように扱う事ができるようになるみたいです
$ npm link

added 1 package, and audited 3 packages in 1s

found 0 vulnerabilities

提供されたパッケージを使う側のプロジェクトを作っていく

# 作業ディレクトリの確認
$ pwd
./vite-project
先ほどnpm linkでリンク?したものをこのプロジェクトで使えるようにします
$ npm link hello-vue3-lib

added 1 package, and audited 48 packages in 2s

5 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

node_modules を確認する

$ ls -la node_modules | grep hello-vue3-lib
hello-vue3-lib -> ../../hello-vue3-lib
シンボリックリンク貼られてました

src/App.vue でインポートして使ってみる

  <script setup lang="ts">
-   import HelloWorld from './components/HelloWorld.vue'
+   import { CountUpButton } from 'hello-vue3-lib'
+   import 'hello-vue3-lib/dist/style.css'
  </script>

  <template>
    ...  <!-- 省略 -->
-   <HelloWorld msg="Vite + Vue" />
+   <CountUpButton />
  </template>

実行してみる

$ yarn dev

  VITE v5.2.13  ready in 769 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

実行結果
実行結果

ちゃんと色も付いているし、コンポーネントが使えるようになってますね!

1つ問題が発生

型定義エラーの様子
型定義エラーの様子

あぁ。。。TypeScript だからね。。。
Vite ビルド時に.d.tsも生成しなきゃいけないんだ。。。

まとめ

vite.config.ts をいじくることで簡単のパッケージ化できることがわかりました。

そして、dev 実行で動くことが確認できるものの、型定義エラーが出ていることが判明しました。

.d.ts の生成は次回頑張りまする。。。