Skip to content

Configuration ​

Toute la configuration se fait dans le code. Tuvix.js ne lit aucune variable d'environnement ni aucun fichier de configuration.

Options de l'orchestrateur ​

ts
import { createOrchestrator } from 'tuvix.js';

declare function reportError(error: Error, app: string): void;

const orchestrator = createOrchestrator({
  // Built-in router. Omit it when you follow an external router with connectRouter().
  router: {
    mode: 'history', // or 'hash'
    base: '/',
    routes: [{ path: '/dashboard/*', app: 'dashboard' }],
  },

  // Passing eventBus options gives this orchestrator a private bus.
  // Omit it to share getGlobalBus() with every app on the page.
  eventBus: { maxListeners: 50, debug: false },

  // Forwarded to the module loader.
  loader: { timeout: 10000, retries: 2, retryDelay: 1000, globals: {} },

  // 'immediate' | 'idle' | 'hover' | 'none' (default)
  prefetch: { strategy: 'hover' },

  onError: (error, appName) => reportError(error, appName),
  onStatusChange: (appName, status) => console.debug(appName, status),
});
OptionDéfautEffet
routeraucunCrée le routeur intégré. Voir Routage.
eventBusaucun (bus global)Bus privé avec ces options. destroy() détruit un bus privé et laisse le bus global en vie.
loader.timeout10000Millisecondes avant l'abandon d'une tentative de chargement. Plafonne aussi l'attente des feuilles de style en sandbox.
loader.retries2Tentatives supplémentaires après le premier échec.
loader.retryDelay1000Millisecondes entre les tentatives.
loader.globals{}Propriétés écrites sur window avant l'exécution des scripts d'une entrée.
prefetch.strategy'none'Quand récupérer les entrées avant leur montage. Voir le tableau ci-dessous.
onErroraucunAppelé avec (error, appName) quand le chargement, bootstrap, mount, update ou unmount échoue.
onStatusChangeaucunAppelé avec (appName, status) à chaque changement de statut.

Pour partager des dépendances comme React entre les apps, utilisez @tuvix.js/module-federation ou des import maps. L'orchestrateur n'a pas d'option pour cela.

Stratégies de prefetch ​

StratégieQuand les entrées sont récupérées
noneUniquement au montage d'une app.
immediateChaque entrée enregistrée, juste après start().
idleChaque entrée enregistrée, au premier requestIdleCallback après start() (délai de 200 ms là où l'API manque).
hoverQuand le pointeur entre sur un lien de même origine dont le chemin activerait une app, ou quand ce lien reçoit le focus. Chaque app est récupérée une seule fois.

Le prefetch ajoute <link rel="modulepreload"> pour les scripts module et <link rel="prefetch"> pour les scripts classiques et les styles. Il ignore les entrées sous forme de fonction de chargement, car appeler la fonction exécuterait le module.

Enregistrer une micro app ​

ts
import { createOrchestrator } from 'tuvix.js';

const orchestrator = createOrchestrator();

orchestrator.register({
  name: 'dashboard',
  entry: {
    scripts: ['https://cdn.example.com/dashboard/main.js'],
    styles: ['https://cdn.example.com/dashboard/main.css'],
    type: 'module',
  },
  container: '#main',
  activeWhen: '/dashboard/*',
  props: { theme: 'dark' },
  fallback: '<p>Dashboard is unavailable.</p>',
  sandbox: false,
  mountWhenVisible: false,
});
ChampTypeEffet
namestringUnique. Doit correspondre au nom sous lequel le module s'enregistre.
entrystring | EntryConfig | EntryLoaderLa provenance du code. Voir ci-dessous.
containerstring | HTMLElementSélecteur ou élément. Résolu au moment du montage, donc l'élément doit seulement exister à ce moment-là.
activeWhenstring | (path) => booleanMotif de route ou prédicat. Sans lui, l'app suit les routes du routeur qui la nomment, ou vous la montez vous-même.
propsRecord<string, unknown>Props initiales. updateAppProps fusionne avec elles.
fallbackstringHTML écrit dans le conteneur quand le chargement, bootstrap ou mount échoue.
sandboxboolean | { css?: boolean }true rend l'app dans un shadow root. Voir Sandbox.
mountWhenVisiblebooleanMonte l'app dès que le conteneur est visible à 10 %. Les changements de route laissent alors l'app tranquille.

Formes d'entrée ​

ts
import type { Entry } from 'tuvix.js';

// One classic script (UMD or IIFE bundle).
const classic: Entry = 'https://cdn.example.com/legacy/app.js';

// Scripts and styles. `type: 'module'` for ES module bundles such as Vite's `.js` output.
const esm: Entry = {
  scripts: ['https://cdn.example.com/cart/main.js'],
  styles: ['https://cdn.example.com/cart/main.css'],
  type: 'module',
  integrity: { 'https://cdn.example.com/cart/main.js': 'sha384-...' },
};

// A loader function. Your bundler code-splits it; the loader passes an AbortSignal.
const lazy: Entry = () => import('./apps/profile');

Sans type, les URL qui se terminent par .mjs, .mts, .ts, .tsx ou .jsx se chargent comme modules, et tout le reste se charge comme script classique. Un navigateur exécute un script module une seule fois par URL, donc une app type: 'module' que vous déchargez ne peut pas se recharger depuis la même URL. Utilisez une fonction de chargement quand vous devez décharger puis recharger.

À savoir sur l'enregistrement ​

  • register lève une erreur pour un nom en double, une entry manquante ou un container manquant.
  • register après start() prend effet immédiatement : une app gérée par les routes se monte si le chemin courant l'active, et une app mountWhenVisible est observée. Avant start(), register stocke seulement la configuration.
  • Une app de viewport reste montée après être sortie de l'écran. Démontez-la avec unmountApp(name).
  • Une app sans activeWhen ni route du routeur reste dans l'état où vous la laissez. Appelez vous-même mountApp(name) et unmountApp(name).
  • fallback est du HTML brut. Ne le construisez pas à partir d'une saisie utilisateur.

Options du routeur ​

ts
import { createRouter } from 'tuvix.js';

const router = createRouter({
  mode: 'history', // 'hash' reads the path from location.hash
  base: '/app', // stripped before matching, added by push() and replace()
  routes: [
    { path: '/users/:id', app: 'users', meta: { title: 'User' } },
    { path: '/settings/*', app: 'settings' },
  ],
});

router.beforeEach(async ({ to }) => !to.startsWith('/admin'));

Les chemins de route correspondent au chemin entier, donc /settings correspond uniquement à /settings et /settings/, et '/' correspond uniquement à /. Terminez un chemin par /* pour inclure les sous-chemins ; '/*' correspond à tous les chemins.

Options de la sandbox ​

ts
import { createSandbox } from 'tuvix.js';

const sandbox = createSandbox({
  css: true, // shadow root on activate()
  js: true, // proxy window for execScript()
  allowedGlobals: ['gtag'], // extra globals strict mode lets you write
  strict: false, // true: writing any other global throws a TypeError
});

L'orchestrateur applique l'isolation CSS aux apps enregistrées avec sandbox: true. Il n'applique jamais JsSandbox. Voir Sandbox.

Options de l'event bus ​

ts
import { createEventBus } from 'tuvix.js';

const bus = createEventBus({
  maxListeners: 0, // 0 = unlimited; past the limit, `on` still adds the listener and warns once per event
  debug: false, // log every emit and subscription
  logger: console.log,
});