WU / DOCSUNIVERSAL MICROFRONTENDS
EN
WU FRAMEWORK + WU CLI / COMPOSITION

Connected apps.

Build a command in React. Vue receives the event and observes the same state.

RUNTIME4.0.0Versions and distribution ↗
02 / STATE · EVENTS · LIFECYCLECommunication guide ↗
ReactWU · store + eventsVue

The counter and events use real WU APIs. Unmount releases application resources; shared state remains for this session. Copy the commands to run them in your terminal. wu create reference →

From control to code

Source code for the two applications you just used.

Read how the store, events, and subscriptions connect

These snippets are extracted from the linked sources. Both modules register their lifecycle with wu.define and receive mount(container, {wu: scoped}): scoped is that app's facade. COUNTER is docs.lab.counter and LAST_COMMAND, docs.lab.lastCommand.

React: write and reflect the shared value

+1 from React executes these lines in the control handler. The write updates shared data; the event adds an inspector entry.

const next=(scoped.store.get(COUNTER)??0)+1;
scoped.store.set(COUNTER,next);
scoped.emit('docs:lab:counter',{value:next,source:'React'});

React reads once with useState and connects store.on inside useLayoutEffect. Each notification calls setCounter. When the React root unmounts, effect cleanup runs dispose(). alive prevents updating messages from a removed instance; diagnostics counts its listeners.

const [counter,setCounter]=useState(()=>scoped.store.get(COUNTER)??0);

useLayoutEffect(()=>{
  alive.current=true;
  const dispose=scoped.store.on(COUNTER,value=>setCounter(value??0));
  diagnostics.listeners+=1;
  return ()=>{alive.current=false;dispose();diagnostics.listeners-=1;};
},[scoped]);

Publish to the bus saves the command and emits the event. result comes from buildCommand, this app's text generator; draft contains the form.

scoped.store.set(LAST_COMMAND,result.command);
const accepted=scoped.emit('docs:lab:command',{command:result.command,framework:draft.framework,operation:draft.operation});
setStatus(accepted?tr("Comando publicado. Runtime Lab recibe el evento."):tr("El host no concedió permiso para publicar el evento."));

Vue: observe, pause, and read again

Vue creates state with reactive. connectLeaves() registers two store subscriptions and three bus subscriptions; track keeps every unsubscribe function. The callbacks change state.counter and state.lastCommand; receive turns the event envelope into a history row.

const connectLeaves=()=>{
  if(disposers.length)return;
  try {
    const track=dispose=>{disposers.push(dispose);diagnostics.listeners+=1;};
    track(scoped.store.on(COUNTER,value=>{state.counter=value??0;}));
    track(scoped.store.on(LAST_COMMAND,value=>{state.lastCommand=value??'';}));
    for(const name of ['docs:lab:command','docs:lab:counter','docs:lab:lifecycle'])track(scoped.on(name,receive));
    state.counter=scoped.store.get(COUNTER)??0;state.lastCommand=scoped.store.get(LAST_COMMAND)??'';state.connected=true;sync();
  }catch(error){disconnect();throw error;}
};

store.on does not automatically provide the initial value: the reads get on connection also recover changes made during the pause. Store notifications arrive through microtasks; the write is already visible to get.

Pause subscriptions and unmount call disconnect(). This runs the stored unsubscribe functions; sync() copies diagnostic counters into Vue state. Unmounting also removes the DOM listener and runs app.unmount().

disconnect=()=>{
  const pending=disposers;disposers=[];
  for(const dispose of pending){dispose();diagnostics.listeners-=1;diagnostics.cleanups+=1;}
  state.connected=false;sync();
};

Connecting your own interface

Choose your paths and events, keep the initial read, and bind each unsubscribe function to the consumer lifecycle. Declare requests in the manifest and grants in your shell: React manifest, Vue manifest and how to grant permissions. The standalone React hosts and Vue show app registration, initialization, and mounting.

In this demo, React and Vue adapt state to the property model of Lit controls and receive their DOM events wu-command-intent and wu-runtime-intent. You can read the producer controls, the consumer controls and their shared styles, or connect these same WU operations to your controls. The sources preserve the portal project's imports and structure.

Continue with the store rules and wildcard patterns and the event bus contract.

BUILD WU WITH US

Found a bug? Have an idea?

Your experience improves WU. Tell us what went wrong or help support its development.