single-spa-html 是 single-spa 生态中用于挂载纯静态 html 片段的轻量级适配器,不支持 js 执行、css 隔离或完整生命周期管理,仅负责将 html 字符串插入指定容器,适合无交互的内容页;它不能直接当子应用用,必须包装成符合 single-spa 契约的 bootstrap/mount/unmount 导出形式才能被正确加载。

single-spa-html 是什么,能不能直接当子应用用?
single-spa-html 不是一个独立的“子应用模板”,而是 single-spa 生态中一个轻量级的、用于挂载纯静态 HTML 片段的微前端适配器。它不处理 JS 执行、CSS 隔离或生命周期管理,只负责把一段 HTML 字符串插入指定容器——所以它适合做「内容页」「营销页」这类无交互或仅含内联脚本的场景,但不适合 React/Vue 等框架应用。
常见误用现象:single-spa-html 加载后页面空白,或控制台报 Application 'xxx' died in status LOADING_SOURCE_CODE: Cannot find module——这通常是因为你把它当成了框架子应用的替代品,而没配真正的 application 生命周期函数。
- 它只导出一个
htmlApplication工厂函数,接收{ template, mountParcel }等参数 - 必须手动确保 HTML 中的相对路径(如
<img src="./logo.png">)在主应用上下文中可访问,否则 404 - 不支持
import-map自动解析,JS 脚本需内联或通过<script src></script>显式加载,且无沙箱隔离
怎么写一个能被 single-spa 正确加载的 html 子应用?
核心是提供符合 single-spa 应用契约的生命周期函数(bootstrap、mount、unmount),再把 single-spa-html 的能力包装进去。不能直接导出 HTML 字符串。
示例结构(src/app.js):
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
import { htmlApplication } from 'single-spa-html';
const app = htmlApplication({
template: () => fetch('/static/welcome.html').then(r => r.text()),
// 注意:template 必须是函数,支持异步,single-spa 会调用它
mountParcel: true, // 启用 parcel 挂载(可选,仅当你需要嵌套 parcel 时)
});
export const bootstrap = app.bootstrap;
export const mount = app.mount;
export const unmount = app.unmount;
-
template返回 Promise或 string,不能是硬编码字符串(否则热更新/CDN 场景失效) - 如果 HTML 内含
<script></script>,它们会在mount阶段执行,但不会被卸载(unmount不清理 script 标签),容易重复执行 - 推荐把 JS 逻辑抽成独立模块,用
import()动态加载并在mount中调用,避免污染全局作用域
如何解决 HTML 子应用样式冲突和 JS 全局污染?
single-spa-html 本身不做任何 CSS 或 JS 隔离,这是它和框架子应用最本质的区别。所有样式和变量都运行在主应用全局上下文中。
实际能做的补救措施有限,但必须做:
- HTML 中所有 class 名加唯一前缀,比如用
my-welcome-xxx替代header,避免撞上主应用的.header - 禁用内联
<style></style>,改用外部 CSS 并配置主应用的style-loader或shadow DOM(需自行封装 mount 函数) - JS 脚本里避免写
window.xxx = ...或document.addEventListener('click', ...),改用闭包 + 局部变量 + 事件委托到子应用容器节点 - 如果必须用第三方库(如 moment),检查是否已由主应用提供;否则需确保版本一致,否则
moment.locale可能被覆盖
为什么 local dev 时 HTML 加载 404,但构建后正常?
因为开发服务器(如 Webpack Dev Server 或 Vite)默认不代理 /static/ 这类路径。你写的 fetch('/static/welcome.html') 在 dev 模式下请求的是 http://localhost:8080/static/welcome.html,但该路径没被服务配置转发。
- Vite 用户:在
vite.config.ts中加server.proxy['/static'] = { target: 'http://localhost:3000', changeOrigin: true }(指向你的静态资源服务) - Webpack 用户:在
devServer.proxy中配置同理,注意路径重写规则 - 更简单但不推荐的做法:把 HTML 放进
public/目录,用fetch('/welcome.html')直接读取(此时依赖 public 目录静态托管) - 构建后正常,是因为 Nginx/Apache 等生产服务器已配置了静态资源路由,而本地开发缺失对应环节
这个细节最容易被忽略——它不报 JS 错,只静默失败,导致你以为是 single-spa-html 问题,其实只是路径没通。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










