XTend Dokumentation
Dunkelmodus aktivieren

XTend Developer Center

Build with XTend today

ESM-Registry

Die XTend ESM-Registry ist der öffentliche JavaScript-first-Einstieg für Browser-, Bundler- und SSR-Apps. Importiere benannte Helfer aus @ccslabs/xtend oder aus dem gleichwertigen Subpath @ccslabs/xtend/registry. Der Import bootet weder den Classic-Loader noch registriert er Komponenten oder schreibt ins DOM.

Installation und Import

npm install @ccslabs/xtend
import {
  readyXTend,
  schedule,
  render,
  createApp,
  createStore,
  disposeXTend
} from '@ccslabs/xtend';

const host = await readyXTend();
const app = createApp();
const store = createStore();

const cancel = schedule(() => {
  render(document.querySelector('#app'), {
    type: 'element',
    tag: 'p',
    children: [{ type: 'text', text: 'Hello XTend' }]
  });
}, { endpointName: 'app.initial-render', scope: 'app' });

// cancel();       // ausstehende Arbeit abbrechen
// disposeXTend(); // Registry-Singletons freigeben

Der Root verwendet standardmäßig den vollständigen RMT-Orchestrierungskernel. readyXTend() bootet Core, Runtime, Performance-/Scheduler-Bridge und Fabric genau einmal. Der Import selbst bleibt side-effect-free. Synchrone Aliase vor erfolgreicher Readiness werfen XTEND_NOT_READY; ein Bootfehler bleibt als XTEND_KERNEL_BOOT_FAILED stabil. getXTendHost() und getXTendSnapshot() liefern den Host beziehungsweise dessen Diagnostik, Backpressure-, Scheduling- und Performance-Snapshot.

Für den bisherigen kleinen Pfad konfiguriert eine App vor der ersten Nutzung explizit configureXTend({ orchestration: 'lightweight' }). Dieser Modus benötigt kein readyXTend() und lädt Kernel und Fabric nicht.

TypeScript

Die Registry bietet opt-in Generics für App und Store sowie geprüfte Descriptor-Typen. Ohne Generic bleibt der permissive, JavaScript-kompatible Vertrag erhalten.

import { createApp, createStore, render, type XTendDescriptor } from '@ccslabs/xtend';

interface AppState {
  count: number;
  status: 'ready' | 'busy';
}

const app = createApp<AppState>({ initialState: { count: 0, status: 'ready' } });
const store = createStore<AppState>({
  states: [{ id: 'count', type: 'number', initial: 0 }]
});
const view: XTendDescriptor = { type: 'text', text: String(store.getState('count')) };
render(document.querySelector('#app')!, view);

Öffentliche Aliase

AliasFachmodul-API
createAppcreateRmtAppRuntime
createStorecreateRmtStateSelectorRuntime
createEffectscreateRmtActionEffectRuntime
createRoutercreateRmtEventRoutingRuntime
createAnimatorcreateRmtAnimationEngineRuntime
createValidatorcreateRmtFormValidationRuntime
createTransitionscreateRmtSurfaceTransitionRuntime
createResourcescreateRmtSurfaceResourceGraphRuntime

Die langen Factory-Namen bleiben ebenfalls exportiert. Nutze sie, wenn explizite Instanzen die Absicht klarer ausdrücken als Registry-Defaults. createFabric() und der Alias createXtendFabric sind asynchron, weil die vorhandene Fabric-UMD-Runtime erst bei Bedarf geladen wird.

const fabric = await createFabric({ reporters: [] });

Lifecycle-Hosts konfigurieren

Rufe configureXTend() vor dem ersten Scheduling- oder Rendering-Alias auf, wenn die App eigene Hosts oder Instanzen benötigt. Eine Konfiguration nach der Singleton-Erzeugung wirft einen Fehler; rufe vor einer Neukonfiguration disposeXTend() auf.

import { configureXTend, readyXTend, renderNode, disposeXTend } from '@ccslabs/xtend';

configureXTend({
  windowTarget: iframe.contentWindow,
  documentTarget: iframe.contentDocument
});
await readyXTend();

const node = renderNode({ type: 'text', text: 'Isolierter Host' });
disposeXTend();

SSR

Node löst den Paket-Root zu xtend.ssr.mjs auf. Die Modulevaluierung benötigt weder window noch document. State-, App-, Effect- und andere DOM-neutrale Factories funktionieren direkt. Rendering benötigt ein injiziertes documentTarget oder einen Renderer; andernfalls wirft XTend einen eindeutigen Konfigurationsfehler. Loader-Helfer sind browser-only.

Mit moduleResolution: &quot;NodeNext&quot; wählt TypeScript xtend.ssr.d.ts. Ein reines Serverprojekt kann daher lib: [&quot;ES2022&quot;] verwenden, ohne DOM-Deklarationen zu installieren oder zu aktivieren.

import { configureXTend, readyXTend, createApp, render } from '@ccslabs/xtend';

configureXTend({ documentTarget: serverDocument });
await readyXTend();
const app = createApp();
const result = render(serverRoot, descriptor);

Komponenten und Classic-Loader

boot(), loadComponent() und hydrate() laden xtend-loader.js lazy im Browser. Damit kann ein ESM-Host Registry-Dienste bewusst mit manifestbasierten Web Components kombinieren.

import { boot, loadComponent, hydrate } from '@ccslabs/xtend';

await boot({ manifestUrl: '/components/manifest.json' });
await loadComponent('x-button');
await hydrate(document.querySelector('#dynamic-region'));

Für einen buildlosen HTML-Host nutzt du weiterhin XTend Classic und bindest xtend-loader.js direkt ein. Package-Consumer können ihn explizit über @ccslabs/xtend/loader importieren. Der Paket-Root bedeutet nicht mehr „Classic laden“.

Vertrag prüfen

npm run test:esm-registry
npm run test:esm-registry-types
npm run demo:ts:typecheck
npm run demo:ts:build
node scripts/run_xtend_tests.js type-exports-loader --json
npm pack --dry-run --json

Die ausführbare ESM-App-Demo nutzt eine Import Map. Die TypeScript-App-Demo nutzt Vite, strikte State-Generics und geprüfte Descriptoren gegen den echten Paket-Root.

Nächste Schritte

(c) 2026 - CCS Networks | Powered by XRouter PHP Extension