ARTICLE DETAIL

资讯详情

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

qiankun React 绑定指南:用 `<MicroApp>` 组件在 React 宿主中挂载与管理微应用

qiankun React 绑定指南:用 `<MicroApp>` 组件在 React 宿主中挂载与管理微应用 前端微前端【免费下载链接】qiankun Blazing fast, simple and complete solution for micro frontends.项目地址https://gitcode.com/gh_mirrors/qi/qiankun点击查看免费下载qiankunjs/react是 qiankun 官方提供的 React 生态绑定包它把loadMicroApp封装成一个声明式的MicroApp组件让宿主应用可以在 React 组件树中像使用普通组件一样挂载、更新和卸载微应用并额外提供了用于路由导航的MicroAppLink。读完本文你将掌握这两个组件的全部用法安装、Props 传递、加载态与错误边界、通过 ref 获取运行实例、settings与lifeCycles配置以及它们底层如何与 qiankun 的 Parcel 生命周期协同工作。安装与环境要求npm install qiankunjs/reactrc qiankunrcqiankunjs/react的 peer dependencies 为qiankun^3.0.0-rc.15、react与react-dom均要求16.9.0。从 package.json 可以看到包本身依赖qiankunjs/ui-shared承载 React/Vue 两个绑定共用的挂载、更新、卸载逻辑和lodash用于 props 的深比较同时以 workspace 方式将qiankun作为开发依赖确保绑定与核心运行时版本一致。构建产物同时提供 ESMdist/esm与 CJSdist/cjs入口并声明sideEffects: false便于打包器做 tree-shaking。组件定位声明式挂载而非全局注册MicroApp适合这样的场景宿主本身是 React SPA你希望在某个路由页面、某个面板或弹层中把微应用当作一个普通组件放进去而不是通过registerMicroApps将其注册为跟随 URL 自动激活的全局应用。二者都是官方推荐的挂载方式区别在于registerMicroAppsstart由 URL 驱动激活规则activeRule而MicroApp由宿主组件自身的生命周期驱动。若你需要同时运行多个微应用实例可参考同时运行多个微应用实例。用MicroAppLink做宿主路由导航MicroAppLink是为通过registerMicroApps注册的微应用提供的宿主导航链接宿主完成注册并调用start之后点击链接会经由 single-spa 的navigateToUrl改变 URL由注册的activeRule决定哪些微应用挂载或卸载。链接本身不会加载任何微应用。import { MicroAppLink, type MicroAppLinkProps } from qiankunjs/react; import { useRef } from react; export default function Navigation() { const linkRef useRefHTMLAnchorElement(null); const appLink: MicroAppLinkProps { to: /app1, className: nav-link, activeClassName: is-active, }; return ( nav MicroAppLink {...appLink} ref{linkRef}App one/MicroAppLink MicroAppLink to/app2/settings replaceApp two settings/MicroAppLink /nav ); }Props 一览Prop类型说明tostring必填。目标 URL渲染为链接的href。replaceboolean是否替换当前历史记录条目。默认false导航时新增一条历史记录。classNamestring链接的 CSS 类。activeClassNamestring当当前 URL 匹配目标 URL 前缀时追加的 CSS 类。默认不追加任何类。childrenReactNode链接内容。refRefHTMLAnchorElement指向渲染出的a元素。MicroAppLinkProps从包入口导出。除了组件自身消费的属性外原生a属性target、rel、download、aria-*、data-*、事件处理器等都会被透传到a元素上to提供href。点击拦截规则组件会先调用你传入的onClick随后仅在满足全部条件时才拦截导航事件未被preventDefault()取消是左键点击button 0未按下 Ctrl / Meta / Shift / Alt 修饰键实际生效的target为空或_self省略target时遵循页面base target的设置链接为同源origin 一致的 HTTP(S) 链接且没有download属性。以上任一条件不满足外部链接、下载链接、新标签页、修饰键点击都保留浏览器原生行为。满足条件时若设置replace组件使用history.replaceState并派发popstate通知路由监听器否则走navigateToUrl。这一判定逻辑实现在 shared/link.ts 的navigateMicroAppLink中replaceUrl还做了巧妙的处理先用事件监听器对象探测 single-spa 是否已同步处理本次replaceState若没有收到通知再手动补发popstate避免重复触发路由事件。高亮匹配规则activeClassName的匹配是字符串前缀比较不解析路由参数组件解析目标 URL把pathname search hash与当前 URL 的对应字符串做前缀比较实现见isMicroAppLinkActiveshared/link.ts。因此to/app1同时匹配/app1/settings和/app10to/匹配所有路径to中的查询参数与 hash 参与同样的前缀比较。若需要精确匹配宿主可自行设置className和aria-current。组件通过订阅popstate、hashchange、single-spa:routing-event三个事件见subscribeToMicroAppLinkLocation来保持高亮状态与浏览器导航、single-spa 路由重排同步并在订阅前后各读取一次window.location.href以弥合渲染到监听器安装之间的导航窗口。基本用法MicroApp唯一必填的 props 是name和entry其中entry是微应用 HTML 入口的 URLimport { MicroApp } from qiankunjs/react; export default function Page() { return MicroApp nameapp1 entryhttp://localhost:8000 /; }组件渲染一个容器div把微应用挂载进该容器当组件卸载时微应用随之卸载。⚠️name 和 entry 必填若name或entry缺失组件仅打印the name and entry of MicroApp is needed并什么都不做——不会抛异常。请务必同时传入两者。该日志来自 shared/index.ts 中mountMicroApp的守卫分支。Props 总览与保留字段组件的 Props 类型定义如下见 MicroApp.tsximport { type MicroApp } from qiankun; // 导出组件类型 type Props SharedProps SharedSlotsReact.ReactNode Recordstring, unknown;末尾的Recordstring, unknown是有意为之任何不属于保留 props 的属性都会被原样转发给微应用成为它的 props。这里没有单独的appProps——额外 props 本身就是微应用的 props这与 Vue 版本通过专门的appProps对象传递有所区别详见 Vue 版MicroApp组件。保留 propsProp类型默认值说明name*string—该微应用实例的名称。更改它会卸载当前实例并创建新实例。entry*string—微应用的 HTML 入口 URL。settingsAppConfiguration—透传给loadMicroApp的加载器 / 沙箱配置。lifeCyclesLifeCycles—宿主为该实例提供的生命周期钩子如beforeLoad、beforeMount。autoSetLoadingbooleanfalse渲染内置加载指示器并在应用挂载完成后自动清除。autoCaptureErrorbooleanfalse渲染内置错误边界而非把加载错误向外抛出。wrapperClassNamestring—追加到包装元素上的类。仅在加载器或错误边界激活时生效。classNamestring—追加到挂载容器元素上的类。loader(loading: boolean) ReactNode—自定义加载 UI 的 render-prop 插槽。errorBoundary(error: Error) ReactNode—自定义错误 UI 的 render-prop 插槽。* 必填。ℹ️保留字段不会被转发组件消费的所有属性——name、entry、settings、lifeCycles、autoSetLoading、autoCaptureError、loader、errorBoundary、wrapperClassName、className——会被组件剥除不会到达微应用。这一剥除逻辑在 shared/index.ts 的componentOwnedProps列表与omitSharedProps中实现注释特别说明了为什么要剥除渲染插槽内联loader每次宿主渲染都是新函数若泄漏给微应用会破坏 props 的深比较。向微应用传递 props任何非保留 prop 都会被转发给微应用并送达其bootstrap/mount/update生命周期MicroApp nameapp1 entryhttp://localhost:8000 // 以下都会被转发给微应用作为 props userId{42} themedark onEvent{(e) console.log(e)} /在微应用内部这些值出现在每个生命周期的props上export async function mount(props) { console.log(props.userId, props.theme); }当这些 props 变化时组件用 lodash 的isEqual做深比较见 MicroApp.tsx 的useDeepCompare若发生变化则对运行中的应用调用microApp.update(props)——不会重新挂载。更新只在应用状态为MOUNTED时真正执行。重挂载 vs 原地更新更改name会卸载当前实例并创建新实例。更改其他转发 prop 只尝试原地update。单独更改entry、settings或lifeCycles不会创建新实例。若要彻底重置请更改name或给组件一个新的key。更新机制的实现细节updateMicroAppshared/index.ts并非简单调用microApp.update而是维护了一条串行链首次更新以mountPromise为起点确保更新发生在挂载完成之后——这里只能补上起点不能跳过本次更新否则宿主传入的第一次 props 变更会被吞掉后续更新通过_updatingPromise链式串联保证更新顺序与组件状态变更顺序一致且后一个更新必须等待前一个完成更新前检查app.update存在、状态为MOUNTED且未被标记为_unmounting避免更新与卸载竞态开发环境下若 200ms 内更新过于频繁会输出性能告警并打印本次更新的 props方便排查不必要的重渲染。加载状态内部 loading 标志初始为true在应用的mountPromise落定后无论成功还是失败清除。这一行为与autoSetLoading无关——该标志只用于选择内置指示器若以它为条件才清除 loading会让自定义loader永远旋转。不提供加载插槽时该状态没有任何可渲染的内容。内置 loaderMicroApp nameapp1 entryhttp://localhost:8000 autoSetLoading /内置 loader 只是渲染字面量文本loading...的占位符见 MicroAppLoader.tsx。要获得真正的 UI请传入自己的loader。自定义 loaderMicroApp nameapp1 entryhttp://localhost:8000 loader{(loading) Spinner spinning{loading} /} /自定义loader独立生效且优先于内置指示器因此配合它时autoSetLoading是多余的。wrapperClassName只在加载或错误插槽激活时生效——因为只有那时组件才渲染带定位的包装元素。组件源码MicroApp.tsx先选择loader否则在autoSetLoading开启时回退到内置MicroAppLoader测试 MicroApp.test.tsx 专门验证了不设置autoSetLoading时自定义 loader 也会在挂载完成后结束这一行为。错误处理默认情况下来自加载load、bootstrap、mount 的错误会从异步加载流程中重新抛出。请配置内置或自定义错误 UI以避免产生未处理的 promise rejection。⚠️务必处理异步加载错误既未设置autoCaptureError也未设置errorBoundary时组件会重新抛出异步加载错误。React 的 error boundary 无法捕获 promise 回调中抛出的错误所以必须配置组件自身的错误 UI。组件源码中的setComponentErrorMicroApp.tsx体现了这个设计只有配置了错误边界才把错误写入 state 渲染否则直接向外throw。mountMicroApp同时监听loadPromise、bootstrapPromise和mountPromise三个 promise 的失败shared/index.ts任一失败都会触发错误 UI 并结束加载态。内置错误边界MicroApp nameapp1 entryhttp://localhost:8000 autoCaptureError /内置边界渲染一个只包含error.message的裸div见 ErrorBoundary.tsx。生产环境请传入自己的errorBoundary。自定义错误边界MicroApp nameapp1 entryhttp://localhost:8000 errorBoundary{(error) ErrorPanel message{error.message} /} /加载与错误同时配置MicroApp nameapp1 entryhttp://localhost:8000 autoSetLoading autoCaptureError /测试 MicroApp.test.tsx 验证了加载失败时errorBoundary插槽能正确渲染错误消息、同时加载插槽被清除的行为。更系统的错误处理方案参见处理加载与运行时错误与addErrorHandler/removeErrorHandler。通过 ref 获取运行实例组件是一个forwardRef。转发的 ref 指向运行中的微应用句柄——来自qiankunjs/single-spa的 Parcel即qiankun中的MicroApp类型由qiankunjs/react以MicroAppType重新导出因此你可以读取它的状态、等待它的生命周期 promiseimport { useRef } from react; import { MicroApp } from qiankunjs/react; import { type MicroAppType } from qiankunjs/react; function Page() { const microAppRef useRefMicroAppType(undefined); const logStatus () { console.log(microAppRef.current?.getStatus()); }; return ( button typebutton onClick{logStatus}Check status/button MicroApp nameapp1 entryhttp://localhost:8000 autoSetLoading ref{microAppRef} / / ); }MicroAppType在共享层还扩展了_unmounting、_updatingPromise、_updatingTimestamp三个内部字段shared/index.ts它们是组件协调更新与卸载竞态更新串行化的私有状态。ref 句柄成员句柄是 single-spa 的 Parcel 接口成员类型说明getStatus()() Status当前生命周期状态见下。mount()() Promisenull挂载应用。unmount()() Promisenull卸载应用。update?(props)(props) Promiseunknown推送新 props仅当应用导出了update生命周期时存在。loadPromisePromisenull源码加载完成时 resolve。bootstrapPromisePromisenull应用完成 bootstrap 时 resolve。mountPromisePromisenull应用完成挂载时 resolve。unmountPromisePromisenull应用完成卸载时 resolve。getStatus()返回的状态之一NOT_LOADED、LOADING_SOURCE_CODE、NOT_BOOTSTRAPPED、BOOTSTRAPPING、NOT_MOUNTED、MOUNTING、MOUNTED、UPDATING、UNMOUNTING、UNLOADING、SKIP_BECAUSE_BROKEN、LOAD_ERROR。⚠️让组件管理生命周期ref 用于读取状态和等待 promise不要自己调用它的mount()/unmount()——组件掌管挂载 / 更新 / 卸载并防护并发卸载与重挂载。手动调用这些方法容易破坏内部状态。传递配置settings加载器与沙箱相关的选项都通过settings一个AppConfiguration传入MicroApp nameapp1 entryhttp://localhost:8000 settings{{ sandbox: { styleIsolation: true } }} /settings会被原样交给loadMicroAppshared/index.ts 中与lifeCycles一起作为第二、第三个参数传入——组件不会替你设置任何默认值。注意loadMicroApp的container必须是真实 DOM 元素而非选择器字符串这一点由组件内部的容器div保证测试 MicroApp.test.tsx 断言了组件把自己创建的容器交给了 qiankun。sandbox.styleIsolation实际启用了什么参见样式隔离sandbox本身的含义参见 JS 沙箱。生命周期钩子lifeCycles宿主侧生命周期钩子通过lifeCycles传入只作用于该组件创建的实例。每个钩子可以是单个函数或函数数组MicroApp nameapp1 entryhttp://localhost:8000 lifeCycles{{ beforeMount: async (app) console.log(before mount, app.name), afterMount: async (app) console.log(mounted, app.name), }} /完整的钩子列表与签名参见生命周期钩子。实现上mountMicroApp把lifeCycles原样传给loadMicroApp的第三个参数由 qiankun 在其自身 addons 之上合并——源码注释特别记录了一个历史教训曾用concat(undefined, hook)包装钩子导致产生[undefined, hook]数组qiankun 会把它当作钩子调用导致所有传入lifeCycles的应用挂载即崩溃因此现在保持原样传递shared/index.ts。样式钩子组件始终会附加两个可供 CSS 定位的类元素类名包装元素仅在加载器或错误边界激活时渲染qiankun-micro-app-wrapper挂载容器始终渲染qiankun-micro-app-container.qiankun-micro-app-wrapper { position: relative; /* 内联样式已设置可在此补充布局 */ } .qiankun-micro-app-container { min-height: 240px; }wrapperClassName和className会被前置拼接到这两个类之前见 MicroApp.tsx因此你的类与 qiankun 的钩子类会同时出现在元素上。容器排序的一个隐藏细节组件刻意把挂载容器放在包装元素的第一个子节点位置MicroApp.tsx。原因是qiankun 以容器的 XPath 为键做 parcel 缓存与同容器串行化而 XPath 计数的是同标签兄弟节点之前的元素。若 loader / error 面板条件渲染在容器之前会在两次挂载之间改变该序号把同一个应用静默拆成两个缓存条目。插槽渲染在容器之后还能在不依赖 z-index 的情况下盖在应用内容之上。这一约束被测试 MicroApp.test.tsx 明确守护。底层工作原理挂载以name为键更改name会完整重挂载一个全新应用。组件通过useEffect依赖[name]实现MicroApp.tsx且挂载/卸载经由一条lifecycleRefpromise 链串行化——effect 的 cleanup 可能落在挂载仍在飞行中时React StrictMode 在开发模式下每次挂载都会如此卸载必须先等待那次挂载完成否则会找不到实例而跳过卸载导致实例一直挂载着、后继实例永远等它。测试 MicroApp.test.tsx 分别验证了 StrictMode 下只留下一个存活实例、快速切换name时事件严格按mount:a → unmount:a → mount:b → …串行执行。props 更新由深比较驱动转发 props 经useDeepComparelodashisEqual比较后变化时走microApp.update且更新链与挂载 promise 对齐不会在挂载完成前误发更新。卸载时标记防竞态实例状态为MOUNTED时组件在拆卸前先把microApp._unmounting true使 prop 更新不会与卸载竞争MicroApp.tsx。组件卸载时unmountMicroApp先等待mountPromise再调用unmount()shared/index.ts。相关资源loadMicroApp—— 本组件封装的底层命令式 API。AppConfiguration——settings的数据结构。生命周期钩子 ——lifeCycles的数据结构。Vue 版MicroApp组件 —— Vue 版本注意Vue 通过专门的appProps对象传递应用 props。同时运行多个微应用实例组件源码MicroApp.tsx、MicroAppLink.tsx、共享逻辑 shared/index.ts 与 shared/link.ts。赞分享前端微前端【免费下载链接】qiankun Blazing fast, simple and complete solution for micro frontends.项目地址https://gitcode.com/gh_mirrors/qi/qiankun点击查看免费下载相关推荐EngineerCMS工程师的知识管理利器EngineerCMS工程师的知识管理利器 在数字化时代工程师们面临着海量信息的挑战如何高效地管理、共享和利用这些知识成为了迫切的需求。今天我们要介绍的前端微前端qiankun Vue 绑定实战指南用 qiankunjs/vue 的 MicroApp 组件声明式加载微应用qiankun Vue 绑定实战指南用 qiankunjs/vue 的 MicroApp 组件声明式加载微应用 qiankunjs/vue 是 qiank前端微前端猫抓资源嗅探插件实战指南从捕获到M3U8合并的完整流程猫抓资源嗅探插件实战指南从捕获到M3U8合并的完整流程 猫抓 cat catch 是一款开源的浏览器资源嗅探扩展它实时监听网页发出的网络请求把藏在页面里的前端微前端上一篇深入解析RAPIDS cuDF中的cudf.pandas加速机制下一篇Semi Design 暗色模式深度解析与实践指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表