切換語言為:簡體

用 Unbuild 和 mkdist 打造你的第一個 Vue.js 元件庫

  • 爱糖宝
  • 2024-10-18
  • 2037
  • 0
  • 0

元件庫是一組可重複使用的元件,可以用於多個專案。它可以幫助不同專案和團隊共享資源,這些元件可以是低階通用元件(例如按鈕、輸入框和模態框),也可以是特定業務模組。簡而言之,元件庫是跨專案共享程式碼的有效方法,能夠顯著節省時間。

然而,使用 Vue.js 構建元件庫並不像看起來那樣容易,因為 Vue.js 的單檔案元件 (SFC) 帶來了挑戰。在標準 TypeScript 專案中,通常使用 tsup 或 Vite 將程式碼轉譯為 JavaScript,並進行打包。

關鍵原則: 儘可能以原生方式交付包程式碼,讓使用者工具負責轉譯和最佳化。這是構建庫時應牢記的原則,能極大地簡化流程。

Vue.js SFC 的挑戰:

讓我們以一個使用可組合函式的元件為例:

<script setup>
import { useUser } from '../composables'
const { user } = useUser()
</script>
<template>
 <div v-if="user">
 {{ user.name }}
 </div>
</template>

可組合函式程式碼如下:

import { ref } from 'vue'
export function useUser() {
 const user = ref({ name: 'John Doe' })
 return {
 user
 }
}

這個元件使用了另一個檔案中的可組合函式,這看似簡單,但它帶來了一個顯著的挑戰。

專案的結構如下:

src/
 components/
 User.vue
 composables/
 useUser.ts
 index.ts

index.ts 是庫的入口檔案,內容如下:

import User from './components/User.vue'
export { User }
export { useUser } from './composables/useUser'

package.json 包含一些 exports 配置:

{
 "type": "module",
 "exports": {
 ".": {
 "types": "./dist/index.d.ts",
 "import": "./dist/index.mjs"
 }
 },
 "main": "dist/index.mjs",
 "types": "dist/index.d.ts"
}

類似標準 TypeScript 專案

注意: 包是一個包含所有專案程式碼的單個檔案。它透過減少需要載入的檔案數量來最佳化專案的載入速度。在建立 npm 包時,這個包不會進行轉譯(除了 TypeScript 到 JavaScript)或壓縮。

如果嘗試打包這個專案,dist 資料夾的結構如下:

dist/
 index.cjs

檢查 index.cjs 檔案後,你會發現可組合函式 useUser 被內聯了,但元件卻被完全忽略了。如果打包工具執行成功,可能會出現類似 No loader is configured for ".vue" files 的錯誤。這意味著像 esbuild 或 tsc 這樣的工具不知道如何處理 Vue 檔案,這是正常的,因為 Vue 檔案不是 JavaScript 檔案。

問題很明顯:我們需要一些配置來處理 Vue 檔案。在網上搜索 "vue loader",因為我們使用了 Vue 檔案,需要將它們轉譯為 JavaScript。

搜索結果中最頂端的是 Vue Loader,它是一個 Webpack 載入器。但是,我不打算使用 Webpack,因為 Vite 已經成為行業標準,在這種情況下沒有理由使用 Webpack。

不過,在我們深入之前,讓我們回顧一下我們的口號:儘可能以原生方式交付包程式碼,並遵循 KISS 原則。 使用 Webpack 來轉譯 Vue SFC 檔案似乎違反了這個原則。

忽略 Vue 檔案

爲了不轉譯 .vue 檔案,我們可以指示打包工具忽略它們。這可以使用 UnJS 生態系統中的 unbuild 工具來實現。

Unbuild 是一個簡單但高度可配置的工具,因為它構建在 rollup 之上。

對於我們的小專案,我們可以直接進行嘗試:

npx unbuild

不幸的是,它會因為與之前相同的原因而失敗:

src/components/ShowGitHubUser.vue (1:0): Expression expected (Note that you need plugins to import files that are not JavaScript)

但 unbuild 的潛力遠不止此。

爲了解決這個問題,讓我們嘗試顯而易見的解決方案。在 index.ts 檔案中,移除元件匯出,只匯出 TypeScript 檔案:

export { useUser } from './composables/useUser'

現在,npx unbuild 命令可以正常執行:

➜ npx unbuild
ℹ Automatically detected entries: src/index [esm] [dts]
ℹ Building vue-library
ℹ Cleaning dist directory: ./dist
✔ Build succeeded for vue-library
 dist/index.mjs (total size: 139 B, chunk size: 139 B, exports: useUser)
Σ Total dist size (byte size): 531 B

這是一個好的開始,但我們的元件仍然在 src 資料夾中,無論你如何仔細搜尋,它們都不會出現在 dist 資料夾中。

複製 Vue 檔案

現在 .ts 檔案已經正確處理了,我們可以嘗試使用簡單的 cp 命令將 .vue 檔案複製到 dist 資料夾中。

cp -r src/components/ dist/components/

然後,我們在 package.json 中新增一個 exports 欄位,告訴使用者在哪裏可以找到這些元件:

{
 "type": "module",
 "exports": {
 ".": {
 "types": "./dist/index.d.ts",
 "import": "./dist/index.mjs"
 },
 "./components/*": {
 "import": "./dist/components/*.vue"
 }
 },
 "main": "dist/index.mjs",
 "types": "dist/index.d.ts"
}

看起來很有希望,不是嗎?但事實並非如此。 😔

匯入路徑的困境

在我們的 Vue 元件中,useUser 可組合函式的匯入方式如下:

<script setup>
import { useUser } from '../composables'
</script>

而我們的 dist 資料夾的結構如下:

dist/
 components/
 User.vue
 index.d.mts
 index.d.ts
 index.mjs

你能找出問題所在嗎?👀

元件無法使用,並會產生 Cannot find module '../composables' or its corresponding type declarations 錯誤,因為路徑指向錯誤的位置。我們已經將所有 TypeScript 檔案打包到一個名為 index.mjs 的檔案中,完全丟失了專案的結構。

打包還是不打包?

從這裏,我們有兩個選擇:

  1. 使用 Vite、外掛和複雜的配置來打包 Vue 檔案。

  2. 保留目錄結構,並使用 mkdist 等工具對 TypeScript 檔案進行檔案到檔案的轉譯(無包構建)。

最終的決定取決於你的具體需求,但我相信簡潔是最好的方法。因此,讓我們探索第二個選項。

目標是將 TypeScript 檔案轉換為 JavaScript 檔案,同時保留 src 資料夾在 dist 資料夾中的原始結構,並且忽略 Vue 檔案。

注意: 使用 <script setup> 塊,mkdist 會忽略 Vue 檔案,以便 Vue 編譯器生成執行時 props。否則,它會生成一個 .vue.d.ts 檔案,為 Vue 元件提供型別。

配置 Unbuild

沒錯,我們將配置 unbuild,因為它整合了 mkdist,使其非常易於使用。

首先,在專案的根目錄中建立一個 build.config.ts 檔案。Unbuild 會讀取此配置檔案,瞭解如何處理專案。它假設了一些預設值,並從 package.json 中推斷出許多方面,但我們需要告訴它使用 mkdist。

import { defineBuildConfig } from 'unbuild'
export default defineBuildConfig({
 entries: ['./src/'],
 declaration: true,
})

這是一個非常簡單的配置檔案。我很喜歡它。 entries 鍵告訴 unbuild 從哪個檔案開始轉譯。但是,./src/ 是一個目錄,由末尾的 / 表示。有了這個提示,unbuild 會放棄預設的打包工具 rollup,轉而使用 mkdist。declaration 鍵提示 unbuild 建立 TypeScript 宣告檔案(.d.ts)。

我們也可以移除 package.json 中的 exports 欄位,因為我們不再打包檔案,並恢復 index.ts 檔案中的元件匯出。

讓我們重新執行 npx unbuild 命令,見證奇蹟。

➜ npx unbuild
ℹ Building vue-library
ℹ Cleaning dist directory: ./dist
✔ Build succeeded for vue-library
 dist (total size: 600 B)
 └─ dist/index.d.ts (108 B)
 └─ dist/index.mjs (112 B)
 └─ dist/composables/useUser.d.ts (79 B)
 └─ dist/composables/useUser.mjs (124 B)
 └─ dist/components/User.vue (177 B)
Σ Total dist size (byte size): 600 B

現在,dist 資料夾的結構如下:

dist/
 components/
 User.vue
 composables/
 useUser.d.ts
 useUser.mjs
 index.d.ts
 index.mjs

這與 src 資料夾的結構一致,User.vue 元件現在可以在 dist 資料夾中使用。相對匯入路徑仍然有效,元件可以在任何 Vue 專案中使用。🥳

本地開發

許多教程到此為止,建議你已經準備好將包釋出到 npm 了。但是,如果你看不到工作成果,如果你不能在構建過程中進行測試,如何才能建立一個複雜的庫呢?

基本上,你無法做到。

讓我們看看如何在本地專案中使用該庫,爲了簡單起見,我們將使用同一個倉庫。

我將展示使用 pnpm workspace 的最簡單方法。

首先,在專案的根目錄中建立一個 pnpm-workspace.yaml 檔案:

packages:
 - .
 - playground

然後,在 playground 資料夾中建立一個新的 Vite 專案:

npx create-vite playground --template vue-ts

因為我們使用的是 pnpm workspace,所以要從專案的根目錄安裝依賴項:

pnpm install

注意: 此步驟不是必需的。你可以建立一個新的 Vite 專案並在其中安裝依賴項。Pnpm 透過在根目錄中安裝所有工作區的依賴項來簡化這個過程。一個簡單的 pnpm install 命令會安裝所有工作區的依賴項。

現在,我們可以在一個 "真實" 專案中使用這個 playground 庫來測試我們的庫。

例如,開啟 src/App.vue 檔案,匯入 User 元件:

<script setup>
import { User } from '../../src'
</script>
<template>
 <User />
</template>

然後執行專案:

cd playground && pnpm dev

你將在瀏覽器中看到 User 元件顯示出來。🎉  如此簡單,卻又如此強大。我幾乎在構建的每個庫中都使用這種方法,它非常有效。

釋出到 npm

這一部分很簡單,只要你理解了工作流程。

首先,給你的庫命名。在本例中,我將使用 @barbapapazes/vue-library

接下來,在 npm 上建立一個帳戶,並使用 npm login 命令登入。

然後,安裝 changelogen 來生成變更日誌,按照語義化版本控制和提交規範更新版本號,並預先填寫 GitHub 版本釋出資訊。

pnpm i -D changeloggen

接下來,在 package.json 中新增兩個指令碼:

{
 "scripts": {
 "prepack": "unbuild",
 "release": "changelogen --release && npm publish --access public && git push --follow-tags"
 }
}

prepack 指令碼在將包釋出到 npm 之前執行 unbuild 命令。release 指令碼生成變更日誌,將包釋出到 npm,並將標籤推送到 GitHub。

注意: 你的專案應該在 GitHub 上才能使用 --release 選項。如果沒有,請省略它,並在倉庫中手動建立釋出。

現在,使用以下命令將包釋出到 npm:

npm run release

就這樣!你已經將你的第一個 Vue.js 元件庫釋出到 npm 了。🚀

準備就緒

今天就到這裏。我們已經涵蓋了許多主題:

  • 如何使用 TypeScript 構建 Vue.js 元件庫。

  • 如何在 TypeScript 專案中管理 Vue 檔案。

  • 如何使用 unbuild 來轉譯 TypeScript 檔案,而不打包 Vue 檔案。

  • 如何使用 mkdist 來保留專案結構。

  • 如何使用 pnpm workspace 在本地專案中測試庫。

  • 如何將庫釋出到 npm。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.