HTML本身不参与微前端路由隔离,真正起作用的是JS运行时协调逻辑和服务器fallback配置;子应用必须由主应用显式传入base path并主动通知路由变更,否则刷新404、跳转失效、菜单高亮错乱等问题必然发生。

HTML 结构本身不参与路由隔离或分发——它只是被加载的静态载体,真正起作用的是运行时 JS 协调逻辑和服务器配置。指望靠改 index.html 或写几个 <iframe> 标签就实现“微前端路由隔离”,90% 的项目会在上线前卡在刷新 404、子应用跳转失效或菜单高亮错乱上。
子应用路由 base 必须由主应用显式传入,不能靠 guess
子应用启动时若把 /app1/user/123 当作 /user/123 解析,就会漏掉前缀,导致内部路由匹配失败。关键不是“能不能跳”,而是“跳完 URL 是什么”以及“主应用是否感知到变化”。
- 主应用挂载前,必须通过
window.__MICRO_APP_BASE_ROUTE__或 props 显式传入 base,例如"/app1" - Vue Router 需配置
base: window.__MICRO_APP_BASE_ROUTE__ || '/';React Router v6+ 必须用<Router basename="{base}">包裹 - 严禁依赖
process.env.PUBLIC_URL或硬编码base,它们在主应用动态加载场景下完全不可控 - 子应用构建输出无需改
publicPath,资源加载路径和路由解析是两回事
Nginx / Express 必须为每个子应用路径做 fallback
用户直接访问 https://host/app1/order/5 时,Nginx 或 Express 默认按静态文件找路径,找不到就返回 404——这不是子应用 bug,是服务端没兜底。
- Nginx 示例:
location /app1 { try_files $uri $uri/ /app1/index.html; } - Express 示例:
app.get('/app1/*', (req, res) => res.sendFile(path.join(__dirname, 'index.html'))); - 注意:每个子应用路径都要单独配一条 fallback,
/app2、/app3同理,不能只配根路径 - 如果子应用部署在独立域名(如
https://cart.example.com),则需主应用反向代理或 CORS 允许,且 fallback 规则要落在主站网关层
iframe src 必须是合法可加载地址,且宽高需显式控制
<iframe src="app.js"> 这种写法在现代浏览器里根本不会加载,只会静默失败或报 net::ERR_FAILED;更常见的是 iframe 被 flex 容器压缩成 0×0,表现为“白屏但已加载”。
立即学习“前端免费学习笔记(深入)”;
- 本地开发务必起 HTTP 服务(如
python3 -m http.server 8000),避免file://协议被拦截 - 生产环境推荐绝对路径:
src="/micro/cart.html",不要用相对路径(当前页面是/admin/user/123时,src="cart.html"会尝试加载/admin/user/cart.html) - 必须显式设置样式:
style="width: 100%; height: 400px; border: none;";响应式场景加aspect-ratio: 16 / 9 - 跨域子应用禁止访问
iframe.contentDocument,所有通信必须走window.postMessage(),且双方都要校验event.origin
Shadow DOM 不隔离 JS 执行环境,仅隔离样式作用域
直接写 shadowRoot.innerHTML = htmlString 会导致内联 <script> 和 <style> 逃逸至全局,污染主应用样式或执行全局副作用(比如 document.body.classList.add('dark'))。
- 必须用
DOMParser解析 HTML 字符串,再逐个提取<style>内容,转为CSSStyleSheet实例后通过shadowRoot.adoptedStyleSheets = [sheet]注入 -
<script src>需拦截并fetch,再在沙箱中重绑定this/window/document后执行 -
attachShadow({ mode: 'closed' })是底线要求,mode: 'open'在生产环境等于开后门 - 第三方库若依赖
shadowRoot(如某些 Web Component polyfill),需提前 patch,否则运行时报错
最常被忽略的一点:路由隔离成败不取决于你用了哪种 HTML 容器,而取决于子应用是否主动通知主应用路由变更。子应用用 history.pushState 或 useNavigate 后,主应用默认收不到任何信号——菜单高亮、权限校验、埋点上报全都会断掉。必须在子应用路由钩子里显式 dispatch micro-app-route-change 自定义事件,主应用监听并同步状态。



















