Types

MFEConfig & MFELoadedComponent

Configurazione di caricamento dinamico (URL ESM, scope, environment) e wrapper runtime del componente caricato.

MFEConfig

Configurazione che la shell passa a MFELoader.loadRemote() per caricare dinamicamente un microfrontend.

interface MFEConfig {
  /** Nome identificativo (deve matchare manifest.name) */
  name: string

  /** URL entry point ESM del microfrontend */
  url: string

  /** Scope identificativo del MFE (deve matchare vite.config) */
  scope: string

  /** Percorso modulo esposto (es: "./module") */
  module: string

  /** Abilita/disabilita il microfrontend */
  enabled?: boolean

  /** Ambiente di deployment (per override URL) */
  environment?: 'development' | 'staging' | 'production'
}

Campi

CampoTipoRequiredDescrizione
namestringDeve corrispondere a manifest.name. Usato come chiave cache nel loader
urlstringURL assoluto del bundle ESM (es. https://mfes.example.com/crm/index.js). Protocolli ammessi: http:, https:
scopestringScope esposto dal bundle (ridondante con Module Federation, conservato per compatibilità)
modulestringPath del modulo esposto (tipicamente ./module o ./index)
enabledbooleanFlag per disabilitare il MFE senza rimuoverlo dalla config
environment'development' | 'staging' | 'production'Aiuta a determinare quale URL usare in config multi-ambiente

Esempio

import type { MFEConfig } from '@pzeta/mfe-contracts'
import { MFELoader } from '@pzeta/mfe-contracts/loader'

const configs: MFEConfig[] = [
  {
    name: 'crm-module',
    url: 'https://mfes.example.com/crm/index.js',
    scope: 'crm',
    module: './module',
    enabled: true,
    environment: 'production',
  },
  {
    name: 'hr-module',
    url: 'https://mfes.example.com/hr/index.js',
    scope: 'hr',
    module: './module',
    enabled: false, // temporaneamente disabilitato
  },
]

const loader = new MFELoader()
const modules = await Promise.all(
  configs.filter((c) => c.enabled !== false).map((c) => loader.loadRemote(c)),
)

Sicurezza URL

Il MFELoader._validateUrl() rifiuta automaticamente:

  • Bloccati: data:, javascript:, blob:, vbscript:
  • Non consentiti: qualsiasi protocollo diverso da http: / https:
// Throw: "Protocollo 'file:' non consentito..."
await loader.loadRemote({ name: 'x', url: 'file:///etc/passwd', /* ... */ })

// Throw: "URL non valido per caricamento MFE..."
await loader.loadRemote({ name: 'x', url: 'not-a-url', /* ... */ })

CSS sibling auto-loading

Il loader cerca automaticamente uno stylesheet sibling con la stessa URL ma estensione .css:

URL bundle: https://mfes.example.com/crm/index.js
URL CSS:    https://mfes.example.com/crm/index.css  (cercato via HEAD)
  • Se la HEAD ritorna 200: viene iniettato <link rel="stylesheet" data-mfe="<name>">
  • Se ritorna 404: silenzioso (CSS opzionale)
  • Se ritorna altro errore o network error: throw

MFELoadedComponent

Wrapper runtime che combina un componente Vue caricato dinamicamente con la sua metadata dal manifest.

import type { Component } from 'vue'

interface MFELoadedComponent {
  /** Nome componente */
  name: string

  /** Componente Vue */
  component: Component

  /** Metadata dal manifest */
  metadata: MFEComponent
}

Quando usarlo

Caso d'uso tipico: catalogo di widget esposti dal MFE che la shell vuole montare dinamicamente in una dashboard o in una galleria.

// MFE espone un loader runtime
export async function getLoadedComponent(name: string): Promise<MFELoadedComponent | null> {
  const metadata = manifest.components?.find((c) => c.name === name)
  if (!metadata) return null

  const component = (await import(`./components/${name}.vue`)).default
  return { name, component, metadata }
}
<!-- Shell: rendering dinamico -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { MFELoadedComponent } from '@pzeta/mfe-contracts'

const loaded = ref<MFELoadedComponent | null>(null)

onMounted(async () => {
  loaded.value = await mfe.getLoadedComponent('KpiTile')
})
</script>

<template>
  <component :is="loaded?.component" v-if="loaded" v-bind="props" />
</template>

Tipi correlati