Ich denke, fast jeder hat von dem neuen Killer-Feature mit dem Namen Modul 'Federation' gehört. Meiner Meinung nach, können wir mit dieser Funktion entweder bereits geschriebene Open-Source-Module verwenden und sie in einer App zusammenführen, oder sie kann für ein großes Projekt nützlich sein, bei dem verschiedene Teams unabhängige Module erstellen können. Am wichtigsten ist, dass alle Beispiele nur in einem einzigen Ökosystem dargestellt werden (React-Bibliothek).
Nachdem ich diesen Artikel über Mikro-Front-Ends gelesen hatte, beschloss ich, eine Mikro-Front-End-Anwendung mit dem Modul 'Federation' zu schreiben.
Meine erste Absicht war es, React und Svelte zu kombinieren. Aber am Ende hatte ich mit Problemen mit dem Svelte-Loader zu kämpfen und fand nur eine Lösung, um Aliase und Hauptfelder für die Webpack-Konfiguration bereitzustellen. Leider funktionierte diese Lösung in meinem Fall nicht (Github, Stack overflow). Daher habe ich diesen Weg verlassen und mich für Vue entschieden.
Als Entwickler haben Sie grundsätzlich zwei Möglichkeiten:
Der Zugriff über die Window Objekt Eigenschaften kann einfach durch Zugriff auf den Bibliotheksnamen erfolgen. Dieser ist im ModuleFederationPlugin definiert. Zum Beispiel folgendermaßen:
src: modules/vue-module/webpack.config.js
{% c-block language="js" %}
new ModuleFederationPlugin({
name: 'vue',
library: { type: "var", name: "vue" },
exposes: {App: './src/bootstrap'}
...etc
})
{% c-block-end %}
Dann können wir auf das Modul zugreifen.
src: modules/main/public/index.html
{% c-block language="js" %}
window.vue.get('App').then(module => {
const vueInstance = module().default;
vueInstance.$mount('#vue');
});
{% c-block-end %}
Im Grunde genommen haben wir einen asynchronen Import, aus dem wir unsere Vue-Instanz über den Standardexport nehmen und in ein Element im DOM mounten können.
Kommen wir nun zum angenehmen Teil
Zur Montage der Vue-Komponente, die benötigt werden:
Das sieht in etwa so aus: src: modules/main/src/VueContainer.jsx
{% c-block language="js" %}
import React, { useRef, useEffect } from 'react'
import app from 'vue/App';
const container = document.createElement('div');
function VueContainer() {
const ref = useRef();
useEffect(() => {
const currentElement = ref.current;
const vueInstance = app();
if(currentElement) {
currentElement.appendChild(container);
vueInstance.$mount(container);
}
return () => {
vueInstance.$destroy();
container.remove();
}
}, [ref])
return <div ref={ref}></div>
}
{% c-block-end %}
Es funktioniert, aber…
Wir erhalten die Vue-Instanz, aber das Template enthält keine Eigenschaften. Statt einer gerenderten Komponente erhalten wir eine Reihe von Fehlern, bei denen Eigenschaften im Template definiert sind, die Instanz aber nicht über diese verfügt. Nach mehrstündigem Suchen fand ich einen großartigen Artikel über Render-Funktionen in Vue. (Ich möchte darauf hinweisen, dass ich eine Art Neuling in Vue bin. Wenn Sie also bessere Lösungen kennen, lassen Sie es mich bitte wissen). Wir müssen die Standard-Renderfunktion außer Kraft setzen und die Vorlagen, die wir rendern wollen, explizit bereitstellen. Dazu erstellen wir eine Komponente mit der Funktion Vue.component, mit einem inneren Zustand, den wir verwenden werden. Das andere Problem ist das erneute Rendern. Wenn die Vue-Instanz einmal gemountet ist und die React-Komponente nicht gemountet ist, dann wird auch die Vue-Komponente entfernt und nicht neu gerendert. Daher sollte ein erzwungenes erneutes Rendering vorgesehen werden. Ich habe noch keine bessere Lösung gefunden, außer der Erstellung einer Funktion, die eine Vue-Instanz erzeugt - auf jedem Mount einer React-Komponente wird eine neue Instanz erstellt und an den Container gemountet.
In etwa so:
src: modules/vue-module/src/bootstrap.js
{% c-block language="js" %}
const app = () => new Vue({
render: function(h) {
const renderTemplate = this._c || h;
return renderTemplate(App); // <- App.vue
}
});
{% c-block-end %}
Aber dieser Ansatz hat auch seine Schwächen - mit jedem Rendern verlieren die Vue-Komponenten ihren Zustand.
Dies war ein einfaches Sandbox-Beispiel für die Kombination verschiedener Frameworks und Bibliotheken. Ich bin mir nicht sicher, ob dies für Produktionszwecke verwendet werden kann, aber es ist eine coole Funktion, die Spaß macht und mit der man spielen kann, und ich möchte sie in Zukunft noch etwas genauer untersuchen.
Link zum Code-Beispiel
Was steht auf meiner To-Do-Liste?