ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

使用 qiankun v3 接入 Vite 微应用:原生 ESM 集成实战指南

使用 qiankun v3 接入 Vite 微应用:原生 ESM 集成实战指南 前端微前端【免费下载链接】qiankun Blazing fast, simple and complete solution for micro frontends.项目地址https://gitcode.com/gh_mirrors/qi/qiankun点击查看免费下载本指南基于 qiankun 的 prepare-a-vite-app.md 编写完整讲解如何将一个现有的 React 或 Vue Vite 应用改造为 qiankun 微应用并通过主应用的loadMicroApp以原生 ESM 方式加载。读完本文你将掌握安装与配置qiankunjs/bundler-plugin/vite插件、在入口模块导出原生 ESM 生命周期、配置跨域部署以及验证开发/生产环境的完整流程并理解其底层实现原理。qiankun v3 以原生 ESM方式加载 Vite 应用这是与经典脚本Classic/Webpack路径截然不同的集成方案无需 UMD 包装、无需 SystemJS 转换、无需把生命周期对象挂到window上。接入过程只有一条路径安装 Vite 插件 → 从入口模块导出微应用生命周期 → 主应用通过loadMicroApp加载。提示如果你是从零创建新应用可以使用 Agent skill 让 coding agent 自动生成整套配置本指南面向的是改造已有的 React 或 Vue 应用的场景。1. 安装并配置插件在 Vite 应用微应用侧中安装构建插件npm install --save-dev qiankunjs/bundler-pluginrc插件支持 Vite 5 及更高版本。注意该包同时提供 Vite 和 Webpack 两个插件但不会自动检测打包器——Vite 插件必须从qiankunjs/bundler-plugin/vite子路径导入包根路径bare import导出的是 Webpack 插件QiankunWebpackPlugin即 Webpack 应用接入指南 所使用的方案。1.1 React 应用的 vite.config.tsimport { qiankun } from qiankunjs/bundler-plugin/vite; import react from vitejs/plugin-react; import { defineConfig } from vite; export default defineConfig({ plugins: [react(), qiankun()], server: { port: 7101, strictPort: true, }, });1.2 Vue 应用的 vite.config.tsimport { qiankun } from qiankunjs/bundler-plugin/vite; import vue from vitejs/plugin-vue; import { defineConfig } from vite; export default defineConfig({ plugins: [vue(), qiankun()], server: { port: 7101, strictPort: true, }, });仓库中的示例项目使用了完全一致的配置模式例如 examples/react/vite.config.ts 中同样是plugins: [react(), qiankun()]并固定端口7100strictPort: true。固定开发端口非常关键主应用通过loadMicroApp直接以 URL 形式引用微应用的 HTML 入口如http://localhost:7101/端口漂移会导致入口不可达。1.3 插件做了什么零参数两项能力qiankun()插件不接受任何参数。从 Vite 插件源码 可以看到它通过config()钩子注入配置通过transformIndexHtml钩子改写构建产物开发/预览服务器返回宽松的 CORS 响应头插件为server和preview都设置了cors: true和Access-Control-Allow-Origin: *头使主应用能够跨源获取 HTML 入口和模块依赖图dev 模式下模块图按需从 Vite dev server 拉取生产构建给唯一入口模块脚本打上entry属性qiankun 的加载器依赖该属性确定性地识别入口脚本而不是回退到最后一个 module 脚本的猜测逻辑。transformIndexHtml的处理逻辑值得注意对应测试见 packages/bundler-plugin/tests/vite-plugin.test.ts开发模式ctx.chunk为空下不修改 HTML——dev 阶段 Vite 的 HTML 变换会丢弃未知属性ESM 引擎依靠入口模块导出的生命周期来解析入口生产构建时先查找与入口 chunk 文件名匹配的script[typemodule][src]匹配时打上entry属性如果已经存在带entry属性的脚本则跳过尊重既有标记匹配失败则回退到最后一个 module 脚本匹配时忽略 URL 中的?查询参数和#哈希。2. 导出原生 ESM 生命周期从index.html直接引用的入口模块即src/main.tsx或src/main.ts中导出bootstrap、mount、unmount三个生命周期函数。核心模式框架实例在mount中创建在props.container内渲染在unmount中销毁。2.1 React 入口src/main.tsximport React from react; import ReactDOM from react-dom/client; import App from ./App; declare global { interface Window { __POWERED_BY_QIANKUN__?: boolean; } } type MountProps { container: HTMLElement }; let root: ReactDOM.Root | undefined; function render(scope: ParentNode) { const node scope.querySelector(#root); if (!node) throw new Error(#root not found); root ReactDOM.createRoot(node); root.render(App /); } export async function bootstrap() {} export async function mount({ container }: MountProps) { render(container); } export async function unmount() { root?.unmount(); root undefined; } if (!window.__POWERED_BY_QIANKUN__) { render(document); }2.2 Vue 入口src/main.tsimport { createApp, type App as VueApp } from vue; import App from ./App.vue; declare global { interface Window { __POWERED_BY_QIANKUN__?: boolean; } } type MountProps { container: HTMLElement }; let app: VueAppElement | undefined; function render(scope: ParentNode) { const node scope.querySelector(#app); if (!node) throw new Error(#app not found); app createApp(App); app.mount(node); } export async function bootstrap() {} export async function mount({ container }: MountProps) { render(container); } export async function unmount() { app?.unmount(); app undefined; } if (!window.__POWERED_BY_QIANKUN__) { render(document); }2.3 生命周期实现的四条关键原则原生 ESM 导出即是生命周期约定。qiankun 的 ESM 引擎直接从入口模块的具名导出中解析bootstrap/mount/unmount也支持默认导出的生命周期对象见 原生 ESM 支持不要再将生命周期对象赋值给windowprops.container属于当前微应用实例。必须在传入的容器内查询#root或#app而不是使用页面级全局选择器如document.getElementById(root)。这是多实例共存与反复挂载/卸载的前提否则多个实例会抢同一个根节点__POWERED_BY_QIANKUN__用于区分运行模式当 qiankun 即将调用mount时入口模块不应自行渲染而应用通过自身开发服务器独立运行时无该标记则立即渲染保证独立开发体验不受影响mount必须创建完整应用unmount必须彻底销毁。ESM 模块的顶层代码在一个应用实例的生命周期内只执行一次——重新挂载时模块作用域状态不会重建因此绝不能把初始化寄托在模块顶层代码上所有需要按次创建的状态都要放进mount。这一点与 生命周期与 props 概念 中阐述的完整契约一致。3. 保持 index.html 为原生模块入口保留 Vite 常规的 HTML 结构单个module 入口且挂载节点的 ID 必须与生命周期代码中的选择器一致div idroot/div script typemodule src/src/main.tsx/script几个关键约束源码中无需手动添加entry属性。生产构建时由 Vite 插件自动给生成的入口脚本加上该属性见第 1.3 节的实现细节每份构建产物必须恰好包含一个带entry属性的脚本——这也是 bundler-plugin 参考文档 中Entry constraints的硬性要求不要事后手工再标记如果应用部署在子路径下或资源通过独立域名/对象存储提供应配置 Vite 的base确保浏览器能访问dist/index.html中生成的资源 URL否则模块脚本和静态资源的相对路径会 404。4. 从主应用加载主应用侧将 Vite 开发服务器地址或生产部署地址配置为loadMicroApp的entry保存返回的实例句柄并在宿主视图销毁前卸载应用import { loadMicroApp } from qiankun; const container document.getElementById(micro-app-slot); if (!container) throw new Error(micro-app-slot not found); const microApp loadMicroApp({ name: account-app, entry: http://localhost:7101/, container, props: { accountId: 42 }, }); await microApp.mountPromise; // 主应用视图销毁时 await microApp.unmount();围绕这段代码需要理解 loadMicroApp API 的几个行为loadMicroApp不需要registerMicroApps也不需要显式调用start()。从 loadMicroApp 源码 可以看到当started尚未置位时它会自动调用start()因为 single-spa 只有在 start 之后才会在pushState/replaceState时派发popstatecontainer必须是真实的HTMLElement而不是 CSS 选择器字符串——v3 中这是类型错误且运行时不可用返回的句柄是一个 single-spa Parcel提供mount()/unmount()/getStatus()以及loadPromise、bootstrapPromise、mountPromise、unmountPromise等 Promise。await microApp.mountPromise用于确认应用已上屏这些 Promise 在加载/挂载失败时会 reject应挂.catch或包在try/await中同一个 name container 组合会复用已加载的模块源码中用name container XPath作为实例 ID 做记忆化重新挂载不会重新执行模块顶层代码因此mount每次都要重建应用、unmount必须完整清理同一容器上先后加载多个实例时下一个实例会等待前一个实例完成卸载源码中的mount包装逻辑会Promise.all等待先前的unmountPromise避免并发冲突。React 和 Vue 主应用也可以改用各自的MicroApp组件集成由组件生命周期代为管理容器、props 更新与卸载——组件底层就是同一个loadMicroApp实例模型。5. 配置跨域部署插件只为 Vite 的开发服务器和预览服务器启用 CORS。生产环境中插件不会替你配置任何东西——真正的服务器或 CDN 必须允许主应用所在源获取以下资源HTML 入口JavaScript 模块以及动态导入import()产生的代码块CSS、图片以及应用引用的其他资源。从主应用页面出发实际测试最终资源 URL、重定向、MIME 类型和 CORS 响应头是否全部正确。特别是模块脚本必须返回正确的 MIME 类型text/javascript与 CORS 头否则浏览器会拒绝执行如果应用请求需要携带 Cookie则不能把Access-Control-Allow-Origin配置为通配符*携带凭据的请求不允许通配符来源。需要同时做三件事服务端指定明确的允许来源如Access-Control-Allow-Origin: https://host.example.com返回支持凭据的响应头Access-Control-Allow-Credentials: true主应用侧配置自定义fetchloadMicroApp的第二个参数AppConfiguration.fetch在请求中注入凭据。关于自定义fetchAppConfiguration 文档 说明它默认是window.fetchqiankun 会在其外层校验响应状态200-399、对失败请求做有限重试、并对请求去重缓存——自定义 fetch 必须保持标准 Fetch API 的响应与流式语义。另外若启用 CSP内容安全策略qiankun 的 ESM 路径要求允许blob:脚本且不需要unsafe-eval具体浏览器约束见 原生 ESM 支持 与 浏览器支持指南。6. 验证开发与生产环境按以下步骤逐项验证确保开发与生产两条链路都可用独立运行微应用单独运行 Vite 应用确认独立分支__POWERED_BY_QIANKUN__不存在时立即渲染正常工作主应用加载运行主应用以http://localhost:7101/为入口调用loadMicroApp确认应用渲染在传入的容器内挂载/卸载往返依次调用await microApp.unmount()和await microApp.mount()确认没有重复的根节点、监听器或残留界面——这能直接检验unmount是否彻底清理检查构建产物在 Vite 应用中执行npm run build检查dist/index.html应当恰好有一个生成的 module 脚本带有entry属性验证 preview执行npm run preview将主应用入口指向预览服务器地址重复第 2、3 步的挂载与卸载检查preview 服务器同样由插件注入了 CORS 头发布前回归在所有受支持的浏览器中使用各主应用的实际源访问生产入口确认应用能够正常加载。由于 qiankun 的 ESM 沙箱依赖浏览器原生能力需要注意 Firefox 默认未启用相关能力此时应改用 Classic/Webpack 交付路径详见 原生 ESM 支持 中的兼容性与诊断章节。一个值得提前知晓的 ESM 特性qiankun 的 Vite 开发集成不提供 Vite 常规的 HMR 连接开发时请以手动刷新页面为主不要依赖热更新保留状态若应用依赖模块顶层注入的 CSS重新挂载后这些样式可能缺失模块顶层代码不会重跑应显式测试重挂载场景。延伸阅读HTML 入口——入口契约与 CORS 边界原生 ESM 支持——ESM 的运行行为、兼容性与浏览器限制qiankunjs/bundler-plugin——插件导出、选项与兼容性参考运行多个微应用实例——重新挂载与清理模式接入 Webpack 应用——Classic 脚本构建方案Vite 方案的对立面loadMicroApp API——实例句柄、参数与行为细节AppConfiguration——sandbox、fetch等按实例配置的完整参考赞分享前端微前端【免费下载链接】qiankun Blazing fast, simple and complete solution for micro frontends.项目地址https://gitcode.com/gh_mirrors/qi/qiankun点击查看免费下载相关推荐vite-plugin-qiankun终极指南快速实现微前端Vite集成vite plugin qiankun终极指南快速实现微前端Vite集成 掌握如何用vite plugin qiankun插件一键配置微前端架构让你的Vitqiankun微应用接入指南3步实现主应用与子应用通信qiankun微应用接入指南3步实现主应用与子应用通信 在现代前端架构中微前端Micro Frontends架构已成为解决大型应用复杂度的有效方案。qi微前端前端框架手写礼簿容易记错记漏这款完全离线的开源电子礼簿让礼金登记毫不费力手写礼簿容易记错记漏这款完全离线的开源电子礼簿让礼金登记毫不费力 每逢红白喜事主家最怕的往往不是操持劳累而是散场后那本密密麻麻、还带着涂改痕迹的手写礼簿前端企业应用上一篇AMD GPU专属优化Ollama-for-amd本地大语言模型部署完整指南下一篇SofGAN交互式Painter工具详解实时绘制与动态风格调整技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表