如何建立一個(gè)函式庫(kù),公開(kāi)可供分散式 .mjs 檔案使用的單一 Vue 元件?
P粉797004644
2023-08-26 23:23:36
<p>我想建立一個(gè)捆綁到單一 .mjs 檔案中的 Vue 元件。另一個(gè) Vue 專(zhuān)案可以透過(guò) HTTP 取得此 .mjs 檔案並使用該元件。透過(guò) npm 安裝可插入元件是不可能的,因?yàn)槠渌麘?yīng)用程式會(huì)嘗試在執(zhí)行時(shí)間根據(jù)配置來(lái)取得它。</p>
<p>可插拔組件需要考慮的事項(xiàng)</p>
<ul>
<li>可能正在使用另一個(gè) UI 框架/庫(kù)中的子元件</li>
<li>可能使用自訂 CSS</li>
<li>可能依賴(lài)其他文件,例如圖片</li>
</ul>
<hr />
<p><strong>複製庫(kù)</strong></p>
<p>我透過(guò) <code>npm create vuetify</code> 建立了一個(gè)新的 Vuetify 專(zhuān)案</p>
<p>我刪除了 src 資料夾中除 vite-env.d.ts 之外的所有內(nèi)容,創(chuàng)建了一個(gè)元件 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>和一個(gè)index.ts文件</p>
<pre class="brush:php;toolbar:false;">import Renderer from "./Renderer.vue";
export { Renderer };</pre>
<p>我在vite.config.ts中加入了庫(kù)模式</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>並擴(kuò)充了 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 會(huì)產(chǎn)生 styles.css 文件,但我必須將樣式註入到 .mjs 檔案中。基於這個(gè)問(wèn)題,我正在使用插件 vite-plugin-css-injected-by-js。</p>
<p>建置時(shí),我獲得了包含自訂 CSS 的所需 .mjs 檔案</p>
<hr />
<p><strong>使用組件</strong></p>
<p>我透過(guò)<code>npm create vue</code>創(chuàng)建了一個(gè)新的Vue專(zhuān)案</p>
<p>出於測(cè)試目的,我將生成的 .mjs 檔案直接複製到新專(zhuān)案的 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>不幸的是,我收到以下警告和錯(cuò)誤</p>
<blockquote>
<p>[Vue warn]:Vue 接收到已成為響應(yīng)式物件的元件。這可能會(huì)導(dǎo)致不必要的效能開(kāi)銷(xiāo),應(yīng)該透過(guò)使用 <code>markRaw</code> 標(biāo)記元件或使用 <code>shallowRef</code> 而不是 <code>ref</code> 來(lái)避免。 </p>
</blockquote>
<blockquote>
<p>[Vue warn]:找不到注入「Symbol(vuetify:defaults)」。 </p>
</blockquote>
<blockquote>
<p>[Vue warn]:執(zhí)行設(shè)定函數(shù)時(shí)出現(xiàn)未處理的錯(cuò)誤</p>
</blockquote>
<blockquote>
<p>[Vue warn]:執(zhí)行調(diào)度程序刷新期間出現(xiàn)未處理的錯(cuò)誤。 </p>
</blockquote>
<blockquote>
<p>未捕獲(承諾中)錯(cuò)誤:[Vuetify] 找不到預(yù)設(shè)實(shí)例</p>
</blockquote>
<p>有人知道我缺少什麼或如何解決它嗎? </p>
Vuetify 不提供隔離元件,需要初始化插件,您需要在主應(yīng)用中執(zhí)行此操作:
app.use(Vuetify)
確保 vuetify
在專(zhuān)案 deps 中不重複,以便程式庫(kù)和主應(yīng)用程式使用相同的副本。
lib應(yīng)該使用vuetify
作為開(kāi)發(fā)依賴(lài),並在Rollup external
中指定它,以防止專(zhuān)案全域的東西與lib捆綁在一起:
external: ["vue", "vuetify"]
點(diǎn)贊 +0
P粉797004644