如何建立一個函式庫,公開可供分散式 .mjs 檔案使用的單一 Vue 元件?
P粉797004644
2023-08-26 23:23:36
<p>我想建立一個捆綁到單一 .mjs 檔案中的 Vue 元件。另一個 Vue 專案可以透過 HTTP 取得此 .mjs 檔案並使用該元件。透過 npm 安裝可插入元件是不可能的,因為其他應用程式會嘗試在執行時間根據配置來取得它。</p>
<p>可插拔組件需要考慮的事項</p>
<ul>
<li>可能正在使用另一個 UI 框架/庫中的子元件</li>
<li>可能使用自訂 CSS</li>
<li>可能依賴其他文件,例如圖片</li>
</ul>
<hr />
<p><strong>複製庫</strong></p>
<p>我透過 <code>npm create vuetify</code> 建立了一個新的 Vuetify 專案</p>
<p>我刪除了 src 資料夾中除 vite-env.d.ts 之外的所有內容,創建了一個元件 Renderer.vue</p>
<pre class="brush:php;toolbar:false;"><script setup lang="ts">
import { VContainer } from "vuetify/components"
defineProps<{ value: unknown }>()
</script>
<template>
<v-container>
<span class="red-text">Value is: {{ JSON.stringify(value, null, 2) }}</span>
</v-container>
</template>
<style>
.red-text { color: red; }
</style></pre>
<p>和一個index.ts文件</p>
<pre class="brush:php;toolbar:false;">import Renderer from "./Renderer.vue";
export { Renderer };</pre>
<p>我在vite.config.ts中加入了庫模式</p>
<pre class="brush:php;toolbar:false;">build: {
lib: {
entry: resolve(__dirname, "./src/index.ts"),
name: "Renderer",
fileName: "renderer",
},
rollupOptions: {
external: ["vue"],
output: {
globals: {
vue: "Vue",
},
},
},
},</pre>
<p>並擴充了 package.json 檔案</p>
<pre class="brush:php;toolbar:false;">"files": ["dist"],
"main": "./dist/renderer.umd.cjs",
"module": "./dist/renderer.js",
"exports": {
".": {
"import": "./dist/renderer.js",
"require": "./dist/renderer.umd.cjs"
}
},</pre>
<p>由於我使用自訂 CSS,Vite 會產生 styles.css 文件,但我必須將樣式註入到 .mjs 檔案中。基於這個問題,我正在使用插件 vite-plugin-css-injected-by-js。</p>
<p>建置時,我獲得了包含自訂 CSS 的所需 .mjs 檔案</p>
<hr />
<p><strong>使用組件</strong></p>
<p>我透過<code>npm create vue</code>創建了一個新的Vue專案</p>
<p>出於測試目的,我將生成的 .mjs 檔案直接複製到新專案的 src 目錄中,並將 App.vue 檔案更改為</p>
<pre class="brush:php;toolbar:false;"><script setup lang="ts">
import { onMounted, type Ref, ref } from "vue";
const ComponentToConsume: Ref = ref(null);
onMounted(async () => {
try {
const { Renderer } = await import("./renderer.mjs"); // fetch the component during runtime
ComponentToConsume.value = Renderer;
} catch (e) {
console.log(e);
} finally {
console.log("done...");
}
});
</script>
<template>
<div>Imported component below:</div>
<div v-if="ComponentToConsume === null">"still loading..."</div>
<component-to-consume v-else :value="123" />
</template></pre>
<p>不幸的是,我收到以下警告和錯誤</p>
<blockquote>
<p>[Vue warn]:Vue 接收到已成為響應式物件的元件。這可能會導致不必要的效能開銷,應該透過使用 <code>markRaw</code> 標記元件或使用 <code>shallowRef</code> 而不是 <code>ref</code> 來避免。 </p>
</blockquote>
<blockquote>
<p>[Vue warn]:找不到注入「Symbol(vuetify:defaults)」。 </p>
</blockquote>
<blockquote>
<p>[Vue warn]:執行設定函數時出現未處理的錯誤</p>
</blockquote>
<blockquote>
<p>[Vue warn]:執行調度程序刷新期間出現未處理的錯誤。 </p>
</blockquote>
<blockquote>
<p>未捕獲(承諾中)錯誤:[Vuetify] 找不到預設實例</p>
</blockquote>
<p>有人知道我缺少什麼或如何解決它嗎? </p>
Vuetify 不提供隔離元件,需要初始化插件,您需要在主應用中執行此操作:
確保
vuetify
在專案 deps 中不重複,以便程式庫和主應用程式使用相同的副本。lib應該使用
vuetify
作為開發依賴,並在Rollupexternal
中指定它,以防止專案全域的東西與lib捆綁在一起: