- Published
Refactoring Old React Project To Wujie
- Authors

- Name
- Xu Zhiyi
Micro-Frontend Evolution: Rebuilding From iframe to Wujie
Background
Core hosts more than ten business modules. In the early days, we used iframes to embed independent subsystems quickly. As the product grew, the iframe approach started showing serious weaknesses:
- Routing and state often fell out of sync; cross-module navigation frequently triggered full-page reloads.
- DOM/CSS tweaks had to be injected manually for each scenario—mobile, dialogs, sidebars—leading to endless hacks.
- Security headers (tfsgv, JSEncrypt) were injected ad hoc in every iframe, making governance difficult.
- Loading, timeout handling, and exception UX were all tangled in one giant component, driving up maintenance cost.
Legacy Implementation: A Powerful but Bloated SubWindow
src/components/functions/subWindow/SubWindow.tsx renders each subsystem via <iframe>:
- Communication: It exposes
window._client/historyPush, manually parses routes, and keeps the host menu in sync—a high-coupling design. - UI Manipulation: Direct DOM scripting inside the iframe hides sidebars, overrides backgrounds, and adjusts
z-index; mobile mode even usesMutationObserver. - Security Injection: On iframe load, scripts rewrite XHR/FETCH to add tfsgv, each page duplicating the logic.
- Exception Handling: Loading states, 10-second timeouts, and modal prompts are all managed inside the component.
- Compatibility Layer: Extra code adapts Angular-era breadcrumbs,
?_timestamp,fcparams, etc.
It works, but the component shoulders every responsibility, making evolution painful.
New Architecture: Wujie-Powered Container
The new implementation in src/components/new/wujie/ embraces a “container component + plugin chain + Redux cooperation” pattern.
1. Lightweight Container (index.tsx)
- Uses
WujieReactto render sub apps, supportingalive(keep-alive) andreload. - Leverages Wujie’s event bus:
sub-route-change: readsfunctionNameMapto auto-fill tab names, i18n text, and detail suffixes.sub-route-replace: updates Reduxtabs/currTabandhistory.pushfor seamless replacements.
- Exposes
props2.jumpso sub apps can trigger host routing via props instead of global variables.
2. Controlled Lifecycle (wujie.tsx)
- Delegates
startApp/destroyApptowujie;window.__WUJIE_QUEUEensures ordered loading for same-name apps. reloadtears down and restarts the sandbox with clean state.- The component renders only a div container—no direct iframe manipulation.
3. Unified Plugin Chain (plugin.ts)
- Pulls in
wujie-polyfillto support Selection, Fullscreen, WindowMessage, etc., inside the sandbox. - Custom plugins inject
jsencrypt.min.js, tfsgv headers, and interceptwindow.open—all defined once, reused everywhere. - CSS plugins inject tweaks (e.g.,
.ant-layout-sider{display:none}) before any child styles load, eliminating imperative DOM hacks.
4. Redux & Event-Driven Coordination
useTabsMenuhandles tab creation/naming; Wujie simply emits events.- Redux becomes the single source of truth for menu/tabs, boosting observability and consistency.
Architecture Comparison
| Aspect | iframe Approach | Wujie Approach |
|---|---|---|
| Route Sync | Global window helpers; frequent full reloads | Event bus + Redux/Router, no refresh |
| DOM/CSS | querySelector + style overrides | Configurable plugin injection |
| Security | Per-iframe scripts, duplicated | Centralized plugin chain |
| Code Structure | One component owns everything | Container/plugin/Redux separation |
| Extensibility | Copy massive template per module | Configure name/url/props only |
| UX | Flashing screens, inconsistent tabs | Smooth switching, aligned tabs |
Migration Strategy & Lessons
- Dual Directory: Legacy code stays in
components/functions; new container lives incomponents/newfor incremental rollout. - functionNameMap Compatibility: Continue using
sessionStorage.functionNameMapto keep menu names consistent during transition. - Event Protocol: Sub apps gradually replace
window.historyPushwithwindow.$wujie.bus.$emit(...). - Plugin Governance: Centralize security and UI patches in plugins for unified upgrades.
Benefits & Next Steps
- Experience: Route transitions feel native; tabs stay synchronized without flashing.
- Velocity: Onboarding new subsystems is far simpler; QA handoffs shrink.
- Governance: Security injections and polyfills are centralized and auditable.
Upcoming work:
- Provide onboarding scaffolds that standardize bus events and lifecycle hooks.
- Move functionNameMap/menu metadata into a backend config service.
- Add instrumentation for bus events and plugin execution to diagnose sub-app issues quickly.
Switching to Wujie is more than replacing iframes—it turns our micro-frontend container into a configurable, observable, and evolvable platform. Hopefully, these lessons help guide future architecture upgrades.