簡體   English   中英

模板:命名空間自定義元素的名稱以避免沖突

[英]Stencil: Namespacing custom elements’ names to avoid collisions

我們的平台建立在帶有 Web 組件的微前端架構上。 我們正在為其中一些使用 Stencil,這意味着我們在一個網頁中有多個 Stencil 應用程序。 此外,我們還有一個 UI 庫,也是用 Stencil 構建的,我們希望在這些微前端組件中使用它。

我們希望使用 Stencil UI 庫作為 Stencil 微前端組件的構建時依賴項。 但由於標簽名稱沖突,目前這是不可能的:

理論上,兩個微前端可以提供兩個不同版本的 UI 庫。 然而,在運行時,它們會發生沖突,因為它們都試圖用customElements.define注冊它們的 UI 元素。 當然,這不會發生,因為 Stencil 在注冊新名稱之前檢查現有名稱 - 但結果同樣糟糕:第一個加載的組件總是獲勝,如果它是舊版本或具有不同的 API,其他組件會打破。

一個解決方案是在構建或運行時命名空間/前綴標記名稱,但網絡標准中沒有任何內容(尚未)。 雖然 Stencil 中有一個namespace配置選項,但這似乎並不能解決這類問題。

使用純 ES6,我們至少可以執行以下操作(即使用動態標簽名稱注冊自定義元素):

export class InnerComponent extends HTMLElement
{
    static register(prefix) {
        customElements.define(`my-${prefix}-inner-component`, InnerComponent)
    }

    constructor() {
        super()
        this.shadow = this.attachShadow({ mode: "open" })
    }

    connectedCallback() {
        this.shadow.innerHTML = `<span>this is some UI component</span>`
    }
}

而且我確信我們可以在 Webpack 等中使用某種構建時解決方案來實現相同的目標。

但是 Stencil 是否有類似的可能? 或者還有什么辦法可以解決這個問題?

我們面臨着類似的問題。 我們的解決方案是避免捆綁依賴項並將它們部署為單獨的庫。 所以如果 A 和 B 都依賴於 C,那么 A 和 B 都沒有任何 C 組件,並且 C 作為自己的腳本資源包含在前端。

Stencil 提供tagNameTransform配置以支持在運行時重命名標簽名稱。 默認情況下,它的值為 false,確保將其設為 true。

此功能幫助我們在微前端架構中使用模板可重用組件,因為每個消費微前端都可以為標記名賦予自己唯一的名稱,從而解決了在微前端平台中使用多個版本的同一模板可重用組件的問題。

將以下配置添加到您的模板配置文件中 -

config.extras.tagNameTransform: true

並在消費微前端確保使用以下代碼覆蓋標記名 -

import { defineCustomElements } from '@yourcomponent/libraryname/dist/loader';
...
defineCustomElements(window, { transformTagName: tagName => `unique-prefix-${tagName}` });

注意:如果您使用stencil-ds-output-targets為模板組件創建包裝器,則尚未提供對重命名的支持。 同樣的 PR 仍在等待中 -https://github.com/ionic-team/stencil-ds-output-targets/pull/59 在支持該功能之前可能的解決方法 - 嘗試模仿從消費微前端創建包裝器。 例如——

import { JSX } from '@yourcomponent/libraryname';
import { createReactComponent } from '@yourcomponent/libraryname/<react-wrapper>/dist/react-component-lib'; 

const TextBox = createReactComponent('unique-prefix-<tagName>')

// Use this new TextBox component while rendering rather than from stencil wrapper directly
class YourComponent = () => {
    return <TextBox />
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM