尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

qiankun Agent Skill 实战指南:让 Claude Code、Cursor 自动创建主应用与微应用

qiankun Agent Skill 实战指南:让 Claude Code、Cursor 自动创建主应用与微应用 qiankun Agent Skill 实战指南让 Claude Code、Cursor 自动创建主应用与微应用【免费下载链接】qiankun Blazing fast, simple and complete solution for micro frontends.项目地址: https://gitcode.com/gh_mirrors/qi/qiankunqiankun 以 Agent Skills 格式随主仓库分发了一份面向 coding agent 的官方使用手册qiankunskill。安装后Claude Code、Cursor 等 coding agent 即可按照官方约定用一句自然语言为你创建 React/Vue 主应用与微应用或将现有 Vite 应用一键改造为微应用。本文将以仓库中的 agent-skill.md 为主体结合 skill 内部文件与核心源码完整讲解安装、使用、决策规则与底层实现原理读完即可让 agent 为你搭建一套可独立运行、可被主应用挂载卸载的 qiankun 3.x 应用。skill 是什么一份交给 agent 执行的接入约定qiankun 的 skill 是一份以 Agent Skills中手动搭建的结果完全一致——skill 只是把这份官方约定交给 agent 去执行。也就是说手动照着教程搭、还是让 agent 照着 skill 搭得到的工程结构、端口约定、生命周期导出方式是一样的。skill 本体存放在仓库的 skills/qiankun 目录下包含三个文件文件作用SKILL.mdskill 入口声明名称与描述name: qiankun、任务路由表、通用前置条件、关键事实与创建后校验要求references/create-micro-app.md创建微应用 / 改造现有 Vite 应用的详细指令references/create-main-app.md创建主宿主应用的详细指令SKILL.md 的描述字段明确声明了触发场景当用户想要创建 qiankun 主应用或微应用、把现有 Vite 应用改造成 qiankun 微应用、或用 React/Vue 接入微前端加载时agent 就应加载这份 skill。其元数据面向 qiankun 3.x。安装一条命令把 skill 装进 agent在准备创建项目的目录中执行npx skills add umijs/qiankun命令会从 qiankun 仓库拉取名为qiankun的 skill并安装到当前 agent 的技能目录例如.claude/skills/。仓库始终分发与最新文档同步的版本无需关心 skill 自身的版本号——这意味着你永远拿到的是与官方文档一致的接入约定不会出现手册过时、配置失配的问题。使用用自然语言描述目标即可安装后直接向 agent 描述目标例如用 qiankun 创建一个 React 主应用端口 7099和一个 Vue 微应用端口 7101agent 会按 skill 中的指令完成以下工作使用 create-vite 创建项目React 或 VueTypeScript 或 JavaScript微应用安装qiankunjs/bundler-plugin、注册 Vite 插件并固定端口、改写入口模块以导出bootstrap/mount/update/unmount生命周期并保留独立运行分支主应用安装qiankun及可选的 React/VueMicroApp组件绑定接入加载代码启动两个开发服务器验证微应用既能独立运行、也能被主应用加载和卸载。skill 内部的决策框架agent 依据什么干活要让 agent 产出正确的结果SKILL.md 定义了一套明确的决策规则值得逐条理解这也是你向 agent 下指令时应该提供的信息。任务路由skill 要求 agent 按需只读取相关引用文件而不是一次性读完全部任务读取文件创建微应用或改造现有 Vite 应用create-micro-app.md创建主应用create-main-app.md其他主题迁移、样式隔离、沙箱、调试仓库文档站与examples/目录动手前必须确定的四件事应用类型——主应用host/shell还是微应用sub/micro app应用名——小写字母、数字、连字符。主应用注册的name必须与微应用在经典模式classic-mode回退中使用的名字完全一致框架——React 或 VueTypeScript 或 JavaScript引用模板是 TS 的用 JS 时去掉类型标注即可开发端口——必须固定且每个应用唯一因为主应用会在entry中硬引用它。约定主应用7099微应用7101、7102……包版本与 dist-tag在 qiankun 3.0 正式版发布前核心包的 dist-tag 是rc包dist-tag装到哪里qiankunrc主应用dependenciesqiankunjs/react/qiankunjs/vuerc主应用dependencies可选 UI 绑定qiankunjs/bundler-pluginrc微应用devDependencies几条贯穿始终的关键事实Vite 微应用不需要专门的构建模式。qiankun 3 通过 ESM 沙箱原生加载script typemodule常规vite dev/vite build产物开箱即是 qiankun 可用的JS 沙箱默认开启CSS 隔离按应用通过styleIsolation: true选择开启运行时使用 CSSscope微应用必须保持可独立运行当window.__POWERED_BY_QIANKUN__未定义即未被 qiankun 加载时它要自行渲染自己挂载了就一定要卸载loadMicroApp返回句柄应用离开时必须调用.unmount()MicroApp组件会在组件卸载时自动完成这件事Webpack 微应用使用qiankunjs/bundler-plugin/webpack而非 Vite 插件。创建完成后的强制校验skill 要求任何创建任务完成后都要按所用引用文件末尾的清单验证结果如果 agent 有浏览器工具应由 agent 亲自执行校验而不是把校验丢给用户。创建微应用从脚手架到生命周期导出新建 vs 改造引用文件 create-micro-app.md 区分两种入口新建从第 1 步开始改造现有 Vite 应用直接跳到第 2 步——改造恰好就是第 24 步除此之外什么都不动不改index.html、App组件、构建脚本。步骤 1脚手架pnpm create vite app-name --template react-ts官方 Vite 模板可选react-ts、react、vue-ts、vue。步骤 2安装构建插件pnpm add -D qiankunjs/bundler-pluginrc步骤 3配置 vite.config.ts——注册插件并固定端口import { defineConfig } from vite; import react from vitejs/plugin-react; // vue: vitejs/plugin-vue import { qiankun } from qiankunjs/bundler-plugin/vite; export default defineConfig({ plugins: [react(), qiankun()], server: { port: 7101, strictPort: true, }, });注意导入路径Vite 插件必须从qiankunjs/bundler-plugin/vite导入包根路径导出的是 Webpack 插件详见 bundler-plugin.md 的导出表。这个插件不接收参数为 Vite 提供两项能力见源码 packages/bundler-plugin/src/vite/index.ts为开发服务器和预览服务器配置 CORS 响应头Access-Control-Allow-Origin: *使主应用能够跨源获取 HTML 入口和模块依赖在生产构建中为唯一的入口模块脚本添加 qiankun 所需的entry属性让加载器确定性地识别入口而不是回退到最后一个模块脚本。源码注释还澄清了一个细节开发环境不需要标记 entry——ESM 引擎通过入口模块的生命周期导出解析入口且 Vite 在 dev 转换时会丢弃未知属性。另注意开发环境的 CORS 配置不替代生产配置部署后仍需服务器或 CDN 返回正确的 CORS 与 MIME 响应头。步骤 4改写入口导出生命周期React 入口模板src/main.tsximport React from react; import ReactDOM from react-dom/client; import App from ./App; import ./index.css; declare global { interface Window { __POWERED_BY_QIANKUN__?: boolean; [key: string]: unknown; } } let root: ReactDOM.Root | undefined; function render(props: { container?: Element } {}) { // when loaded by qiankun, resolve #root inside the host-provided container, not the top document const container props.container?.querySelector(#root) ?? document.getElementById(root); if (!container) return; root ReactDOM.createRoot(container); root.render( React.StrictMode App / /React.StrictMode, ); } export async function bootstrap() {} export async function mount(props: { container?: Element }) { render(props); } // the host re-delivers its props here whenever they change — react to them without remounting export async function update(_props: Recordstring, unknown) {} export async function unmount(_props: { container?: Element }) { root?.unmount(); root undefined; } if (window.__POWERED_BY_QIANKUN__) { // classic-mode fallback: expose the lifecycles on window under the REGISTERED app name window[app-name] { bootstrap, mount, update, unmount }; } else { render(); }Vue 入口模板src/main.tsimport { createApp, reactive } from vue; import App from ./App.vue; import ./style.css; declare global { interface Window { __POWERED_BY_QIANKUN__?: boolean; [key: string]: unknown; } } let app: ReturnTypetypeof createApp | undefined; // props the host hands over — seeded on mount, kept current by update const hostProps reactiveRecordstring, unknown({}); function render(props: { container?: Element } {}) { const container props.container?.querySelector(#app) ?? document.getElementById(app); if (!container) return; app createApp(App, { hostProps }); app.mount(container); } export async function bootstrap() {} export async function mount(props: { container?: Element }) { Object.assign(hostProps, props); render(props); } export async function update(props: Recordstring, unknown) { Object.assign(hostProps, props); } export async function unmount(_props: { container?: Element }) { app?.unmount(); app undefined; } if (window.__POWERED_BY_QIANKUN__) { // classic-mode fallback: expose the lifecycles on window under the REGISTERED app name window[app-name] { bootstrap, mount, update, unmount }; } else { render(); }模板中的几个要点props.container属于当前微应用实例渲染时必须在该容器内查询#root/#app而不是用页面级全局选择器__POWERED_BY_QIANKUN__分支用于避免入口模块在 qiankun 调用mount前自行渲染独立运行时立即渲染。该标志由 qiankun 在beforeLoad/beforeMount时置为true、beforeUnmount时删除见 packages/qiankun/src/addons/engineFlag.ts每次mount都要创建完整的应用实例每次unmount都要彻底销毁。重新挂载时模块顶层代码不会再次执行window[app-name]是经典模式Classic 脚本构建如 Webpack 应用下的回退注册方式ESM 模式下原生导出即生命周期约定。模板把两种都覆盖确保主应用无论走 ESM 沙箱还是经典加载都能识别。微应用验证清单在微应用中执行pnpm dev打开http://localhost:7101——必须能独立渲染走入口的非 qiankun 分支如果已有主应用同时运行它确认微应用能挂载进主应用且无控制台报错。创建主应用三种加载方式与实例句柄管理脚手架与安装引用文件 create-main-app.md 假定 shell 使用任意框架下面以 React TS、端口7099为例pnpm create vite main-app-name --template react-ts pnpm add qiankunrc qiankunjs/reactrc # vue shell: qiankunjs/vuerc同样在vite.config.ts中固定端口server: { port: 7099, strictPort: true }。加载方式一MicroApp组件React/Vue shell 推荐挂载即渲染、组件卸载即卸载内置 loading/error 插槽额外的 props 会被透传给微应用变化时通过微应用的update生命周期送达import { MicroApp } from qiankunjs/react; // same component name in qiankunjs/vue export default function SubAppPage() { return MicroApp nameapp-name entry//localhost:7101 autoSetLoading /; }从源码看MicroApp组件packages/ui-bindings/react/src/MicroApp.tsx把挂载与卸载串行化到一条 effect 链上挂载在useEffect中执行卸载在 effect cleanup 中等待挂载完成后调用unmountMicroApp并设置_unmounting标志避免卸载过程中再次触发update。这意味着即使 React StrictMode 下挂载与清理交错也不会留下悬挂的实例。组件还通过useDeepCompare对 props 做深比较仅在变化时才触发updateMicroApp.tsx。加载方式二路由驱动注册框架无关qiankun 在 URL 匹配activeRule时自动挂载/卸载应用。把这段代码放进 shell 入口执行一次import { registerMicroApps, start } from qiankun; registerMicroApps([ { name: app-name, entry: //localhost:7101, container: #micro-app-container, // an element the shell always renders activeRule: /app-name, }, ]); start();加载方式三loadMicroApp完全手动控制import { loadMicroApp } from qiankun; const microApp loadMicroApp({ name, entry, container }, configuration); // ... await microApp.unmount(); // 应用离开时由你负责调用loadMicroApp返回一个 parcel 句柄源码见 packages/qiankun/src/apis/loadMicroApp.ts其内部以name container XPath作为实例标识做了记忆化同一容器再次挂载同名应用时不会重新加载和求值其生命周期loadMicroApp.ts同一容器上挂多个微应用时新实例的mount会先等待前序实例全部卸载完成loadMicroApp.ts。此外使用loadMicroApp时无需配置registerMicroApps也无需显式调用start()loadMicroApp.ts 中若尚未 start 会自动 start。仓库的 examples/main/src/apps.ts 展示了一个真实主应用如何以名称 路由 端口的元数据表驱动多个微应用React、Vue、Webpack、纯 HTML、流式渲染并在部署模式pages下把entry切到同一站点下的子路径。按应用配置每个应用可独立配置loadMicroApp的第三个参数、MicroApp组件的configurationprop、或registerMicroApps的 per-app 字段sandbox默认开启加styleIsolation: true即可用 CSSscope隔离微应用样式。主应用验证清单同时启动两个 dev server打开主应用http://localhost:7099导航到微应用路由——必须挂载进 shell 且无控制台报错离开微应用路由——其 DOM 必须被移除说明 unmount 真正执行了微应用在http://localhost:7101仍能独立渲染。覆盖范围与边界skill 当前版本只覆盖创建环节新建主应用/微应用以及改造现有 Vite 应用。迁移、样式隔离、排障等其他主题不在 skill 指令内请查阅本文档站对应章节接入 Vite 应用完整指南见 prepare-a-vite-app.md含跨域部署、生产环境验证等进阶内容Webpack 应用的 Classic 构建方案见 prepare-a-webpack-app.md生命周期与 props 的完整约定见 lifecycle-and-props.mdHTML 入口约定与 CORS 要求见 html-entry-loading.mdESM 运行行为与兼容性见 esm-sandbox.md。相关内容快速上手教程搭建主应用和微应用接入 Vite 应用qiankunjs/bundler-plugin可运行示例examples/main、examples/react、examples/vue、examples/vue-host【免费下载链接】qiankun Blazing fast, simple and complete solution for micro frontends.项目地址: https://gitcode.com/gh_mirrors/qi/qiankun创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表