feat: modernize examples and scaffold sandbox=true integration#3126
feat: modernize examples and scaffold sandbox=true integration#3126
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
There was a problem hiding this comment.
Pull request overview
This PR modernizes the repo’s qiankun example apps and create-qiankun scaffolding to align on a simplified “single external script[entry] + IIFE” build contract while keeping sandbox mode enabled, and refreshes the example UIs to a consistent modern layout.
Changes:
- Replace legacy/SystemJS-based qiankun HTML transformation with a Rollup
generateBundleplugin that emits a qiankun-compatibledist/index.htmland an IIFE bundle. - Update
create-qiankunpatchers, fixtures, and e2e assertions to match the new build/output contract and remove legacy dependencies (e.g.,@vitejs/plugin-legacy,cheerio). - Refresh example apps (React/Vue/Vite/PureHTML + main) UI/styling and align ports/app naming to improve stability when switching micro-apps under
sandbox: true.
Reviewed changes
Copilot reviewed 52 out of 54 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/create-qiankun/tests/fixtures/vue-ts/vite.config.ts.txt | Updates Vue TS fixture to IIFE + emitted entry HTML plugin contract. |
| packages/create-qiankun/tests/fixtures/vue-ts/qiankunHtml.ts.txt | Removes legacy HTML transform fixture (SystemJS/legacy path). |
| packages/create-qiankun/tests/fixtures/vue-ts/main.ts.txt | Adds Vue idPrefix and lifecycle aliasing for stable global name usage. |
| packages/create-qiankun/tests/fixtures/react-ts/vite.config.ts.txt | Updates React TS fixture to IIFE + emitted entry HTML plugin contract. |
| packages/create-qiankun/tests/fixtures/react-ts/qiankunHtml.ts.txt | Removes legacy HTML transform fixture (SystemJS/legacy path). |
| packages/create-qiankun/tests/fixtures/react-ts/main.tsx.txt | Adds React identifierPrefix and lifecycle aliasing for stable global name usage. |
| packages/create-qiankun/tests/fixtures/main-react-ts/main.tsx.txt | Updates commented example entry port for main-app fixture. |
| packages/create-qiankun/tests/fixtures/main-react-ts/App.tsx.txt | Updates main-app fixture entry port and header copy. |
| packages/create-qiankun/tests/fixtures/main-react-ts/App.css.txt | Refreshes main-app fixture styling to the new design. |
| packages/create-qiankun/tests/e2e.cli.test.ts | Aligns e2e assertions with new HTML contract; drops legacy plugin expectations. |
| packages/create-qiankun/src/shared/versions.ts | Replaces legacy plugin version constants with pinned modern React/Vue/Vite/TS versions. |
| packages/create-qiankun/src/shared/patchers/viteConfig.ts | Generates qiankun-mode IIFE build + emits index.html via generateBundle. |
| packages/create-qiankun/src/shared/patchers/qiankunHtmlPlugin.ts | Removes the legacy cheerio-based index.html transformer writer. |
| packages/create-qiankun/src/shared/patchers/packageJson.ts | Updates sub-app deps to modern React/Vue/Vite/TS and removes legacy deps. |
| packages/create-qiankun/src/shared/patchers/mainApp/packageJson.ts | Pins main-app template React/Vite/TS versions alongside qiankun. |
| packages/create-qiankun/src/shared/patchers/mainApp/entryFile.ts | Updates commented example entry port for generated main app entry file. |
| packages/create-qiankun/src/shared/patchers/mainApp/appStyles.ts | Refreshes generated main-app CSS to the new design. |
| packages/create-qiankun/src/shared/patchers/mainApp/appComponent.ts | Updates generated main-app micro-app entry port and header copy. |
| packages/create-qiankun/src/shared/patchers/index.ts | Stops generating the legacy qiankunHtml plugin file. |
| packages/create-qiankun/src/shared/patchers/entryFile.ts | Adds React/Vue id prefixing and lifecycle aliasing in generated sub-app entry files. |
| examples/vue/vite.config.ts | Switches Vue example to IIFE build + emitted entry HTML plugin in qiankun mode. |
| examples/vue/tsconfig.node.json | Extends node tsconfig includes for config TS files. |
| examples/vue/tsconfig.app.json | Extends app tsconfig includes to cover .d.ts files. |
| examples/vue/src/vite-env.d.ts | Adds Vue SFC module typing for TS. |
| examples/vue/src/style.css | Replaces default Vite styles with minimal base styling aligned to new UI. |
| examples/vue/src/main.ts | Adds idPrefix, mount default props, and exports lifecycle under stable names. |
| examples/vue/src/App.vue | Rebuilds UI with new layout/styling and runtime info display. |
| examples/vue/package.json | Upgrades Vue/Vite/TS toolchain versions and removes legacy deps. |
| examples/vue/config/qiankunHtml.ts | Removes legacy cheerio-based HTML transformer. |
| examples/vite/vite.config.ts | Adds qiankun-mode IIFE build + emitted entry HTML plugin and server headers/port. |
| examples/vite/tsconfig.node.json | Extends node tsconfig includes for config TS files. |
| examples/vite/src/main.tsx | Adds typed lifecycle, safer mount/unmount, and stable global lifecycle names. |
| examples/vite/src/index.css | Replaces default Vite styles with minimal base styling aligned to new UI. |
| examples/vite/src/assets/vite.svg | Adds a bundled Vite logo asset for in-app usage. |
| examples/vite/src/App.tsx | Refreshes UI and switches Vite logo import to a bundled asset. |
| examples/vite/src/App.css | Updates component styling to match the new design system. |
| examples/vite/package.json | Adds qiankun deps/scripts and upgrades React/Vite/TS versions. |
| examples/react/vite.config.ts | Switches React example to qiankun-mode IIFE build + emitted entry HTML plugin. |
| examples/react/tsconfig.node.json | Extends node tsconfig includes for config TS files. |
| examples/react/src/main.tsx | Adds identifierPrefix, mount default props, and stable global lifecycle names. |
| examples/react/src/index.css | Replaces default Vite styles with minimal base styling aligned to new UI. |
| examples/react/src/App.tsx | Refreshes UI layout/styling and runtime info display. |
| examples/react/src/App.css | Updates component styling to match the new design system. |
| examples/react/package.json | Upgrades React/Vite/TS versions and removes legacy deps/plugins. |
| examples/react/config/qiankunHtml.ts | Removes legacy cheerio-based HTML transformer. |
| examples/purehtml/package.json | Updates server port and bumps dev deps (cross-env/http-server). |
| examples/purehtml/index.html | Modernizes PureHTML micro-app UI and updates script entry port. |
| examples/purehtml/entry.js | Removes jQuery dependency; implements vanilla render/counter + unmount cleanup. |
| examples/main/src/styles/index.css | Adds layout resets and new sidebar item styling. |
| examples/main/src/components/Sidebar.tsx | Reworks sidebar menu rendering using items with richer labels and updated copy. |
| examples/main/src/components/MicroAppContainer.tsx | Adds per-app name mapping and forces sandbox: true for micro-app loading. |
| examples/main/src/components/Header.tsx | Simplifies header UI/actions for the refreshed main app design. |
| examples/main/src/components/Dashboard.tsx | Updates dashboard copy/content and adjusts antd v6 styling props usage. |
| examples/main/package.json | Upgrades React/AntD/Zustand/Vite/TS versions for the main example app. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| .purehtml-root { | ||
| font-family: Inter, 'PingFang SC', 'Microsoft YaHei', system-ui, -apple-system, sans-serif; | ||
| } | ||
| .purehtml-root { | ||
| margin: 0; | ||
| min-height: 100vh; | ||
| background: linear-gradient(180deg, #f8fafc 0%, #fef3c7 100%); | ||
| color: #0f172a; | ||
| } |
There was a problem hiding this comment.
The .purehtml-root selector is duplicated in two consecutive blocks; this can be merged into a single rule to reduce redundancy and make future edits less error-prone.
| <Text className="text-xs text-gray-400">Micro-Frontend</Text> | ||
| </div> | ||
| </Space> | ||
| <button onClick={() => setCollapsed(!collapsed)} className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"> |
There was a problem hiding this comment.
The collapse/expand control is a <button> with only an icon and no accessible name. Add an aria-label (and optionally aria-expanded) so assistive tech can understand the action/state.
| <button onClick={() => setCollapsed(!collapsed)} className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"> | |
| <button | |
| onClick={() => setCollapsed(!collapsed)} | |
| className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors" | |
| aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'} | |
| aria-expanded={!collapsed} | |
| > |
| background-color: #f9f9f9; | ||
| } | ||
| color: #0f172a; | ||
| } |
There was a problem hiding this comment.
Same as other micro-app styles: only #root is styled, so the default body margin can show in standalone mode. Add a global reset (e.g., html, body { margin: 0; }) to avoid inconsistent layout.
| } | |
| } | |
| html, | |
| body { | |
| margin: 0; | |
| } |
| type="text" | ||
| icon={<GithubOutlined />} | ||
| className="text-gray-500 hover:text-blue-500" | ||
| onClick={() => window.open('https://github.com/umijs/qiankun', '_blank')} |
There was a problem hiding this comment.
window.open(..., '_blank') without noopener,noreferrer enables reverse-tabnabbing. Use window.open(url, '_blank', 'noopener,noreferrer') (or set opener = null) when opening external links.
| onClick={() => window.open('https://github.com/umijs/qiankun', '_blank')} | |
| onClick={() => window.open('https://github.com/umijs/qiankun', '_blank', 'noopener,noreferrer')} |
| <Button | ||
| type="text" | ||
| icon={<GithubOutlined />} | ||
| className="text-gray-500 hover:text-blue-500" | ||
| onClick={() => window.open('https://github.com/umijs/qiankun', '_blank')} | ||
| /> |
There was a problem hiding this comment.
This icon-only GitHub button has no accessible label. Add an aria-label (and/or title) so screen readers can announce what the control does.
| type="text" | ||
| icon={isFullscreen ? <FullscreenExitOutlined /> : <FullscreenOutlined />} | ||
| className="text-gray-500 hover:text-blue-500" | ||
| onClick={toggleFullscreen} |
There was a problem hiding this comment.
The fullscreen toggle is an icon-only button without an accessible label/state. Add an aria-label (and consider aria-pressed to reflect fullscreen on/off) to improve keyboard/screen reader usability.
| onClick={toggleFullscreen} | |
| onClick={toggleFullscreen} | |
| aria-label={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'} | |
| aria-pressed={isFullscreen} |
examples/react/src/App.tsx
Outdated
| import './App.css' | ||
| import { useState, version } from 'react'; | ||
| import reactLogo from './assets/react.svg'; | ||
| import viteLogo from '/vite.svg'; |
There was a problem hiding this comment.
Importing the Vite logo from /vite.svg will resolve against the host page’s origin when this micro-app is mounted inside qiankun, so the image can break. Prefer bundling the asset (e.g., move it under src/assets and import it) so Vite rewrites/embeds it correctly for micro-frontend runtime.
| import viteLogo from '/vite.svg'; | |
| import viteLogo from './assets/vite.svg'; |
| <a href="https://vite.dev" target="_blank" rel="noreferrer"> | ||
| <img src="/vite.svg" class="logo" alt="Vite logo" /> | ||
| </a> |
There was a problem hiding this comment.
<img src="/vite.svg"> points to the host app’s origin after qiankun mounts this micro-app into the main document, so the logo may not load. Prefer bundling the asset (import it from src/assets / reference it via an import) so Vite can rewrite/embed it for the micro-frontend environment.
| #root { | ||
| margin: 0; | ||
| min-width: 320px; | ||
| font-family: Inter, 'PingFang SC', 'Microsoft YaHei', system-ui, -apple-system, sans-serif; | ||
| text-rendering: optimizeLegibility; | ||
| -webkit-font-smoothing: antialiased; | ||
| -moz-osx-font-smoothing: grayscale; | ||
| } | ||
|
|
||
| a { | ||
| font-weight: 500; | ||
| color: #646cff; | ||
| text-decoration: inherit; | ||
| } | ||
| a:hover { | ||
| color: #535bf2; | ||
| } | ||
|
|
||
| body { | ||
| margin: 0; | ||
| display: flex; | ||
| place-items: center; | ||
| min-width: 320px; | ||
| min-height: 100vh; | ||
| } | ||
|
|
||
| h1 { | ||
| font-size: 3.2em; | ||
| line-height: 1.1; | ||
| } | ||
|
|
||
| button { | ||
| border-radius: 8px; | ||
| border: 1px solid transparent; | ||
| padding: 0.6em 1.2em; | ||
| font-size: 1em; | ||
| font-weight: 500; | ||
| font-family: inherit; | ||
| background-color: #1a1a1a; | ||
| cursor: pointer; | ||
| transition: border-color 0.25s; | ||
| } | ||
| button:hover { | ||
| border-color: #646cff; | ||
| } | ||
| button:focus, | ||
| button:focus-visible { | ||
| outline: 4px auto -webkit-focus-ring-color; | ||
| } | ||
|
|
||
| @media (prefers-color-scheme: light) { | ||
| :root { | ||
| color: #213547; | ||
| background-color: #ffffff; | ||
| } | ||
| a:hover { | ||
| color: #747bff; | ||
| } | ||
| button { | ||
| background-color: #f9f9f9; | ||
| } | ||
| color: #0f172a; | ||
| } |
There was a problem hiding this comment.
These styles only target #root, so in standalone mode the browser default body { margin: 8px; } will still apply and can cause unwanted whitespace around the app. Add a global reset (at least html, body { margin: 0; }) in the base stylesheet.
| #app { | ||
| margin: 0; | ||
| min-width: 320px; | ||
| font-family: Inter, 'PingFang SC', 'Microsoft YaHei', system-ui, -apple-system, sans-serif; | ||
| text-rendering: optimizeLegibility; | ||
| -webkit-font-smoothing: antialiased; | ||
| -moz-osx-font-smoothing: grayscale; | ||
| } | ||
|
|
||
| a { | ||
| font-weight: 500; | ||
| color: #646cff; | ||
| text-decoration: inherit; | ||
| } | ||
| a:hover { | ||
| color: #535bf2; | ||
| } | ||
|
|
||
| body { | ||
| margin: 0; | ||
| display: flex; | ||
| place-items: center; | ||
| min-width: 320px; | ||
| min-height: 100vh; | ||
| } | ||
|
|
||
| h1 { | ||
| font-size: 3.2em; | ||
| line-height: 1.1; | ||
| } | ||
|
|
||
| button { | ||
| border-radius: 8px; | ||
| border: 1px solid transparent; | ||
| padding: 0.6em 1.2em; | ||
| font-size: 1em; | ||
| font-weight: 500; | ||
| font-family: inherit; | ||
| background-color: #1a1a1a; | ||
| cursor: pointer; | ||
| transition: border-color 0.25s; | ||
| } | ||
| button:hover { | ||
| border-color: #646cff; | ||
| } | ||
| button:focus, | ||
| button:focus-visible { | ||
| outline: 4px auto -webkit-focus-ring-color; | ||
| } | ||
|
|
||
| .card { | ||
| padding: 2em; | ||
| } | ||
|
|
||
| #app { | ||
| max-width: 1280px; | ||
| margin: 0 auto; | ||
| padding: 2rem; | ||
| text-align: center; | ||
| } | ||
|
|
||
| @media (prefers-color-scheme: light) { | ||
| :root { | ||
| color: #213547; | ||
| background-color: #ffffff; | ||
| } | ||
| a:hover { | ||
| color: #747bff; | ||
| } | ||
| button { | ||
| background-color: #f9f9f9; | ||
| } | ||
| color: #0f172a; | ||
| } |
There was a problem hiding this comment.
Only #app is styled here, so the default body margin can leak through in standalone mode and create extra whitespace. Consider adding a global reset (at least html, body { margin: 0; }) in this base stylesheet.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…p views Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Summary
script[entry]+ IIFE contract, remove legacy/SystemJS transform paths, and keep sandbox mode enabled.create-qiankunpatchers and e2e fixtures/tests with the new contract, including unique host app names for stable sub-app switching.Verification
pnpm --dir examples/main run buildpnpm --dir examples/react run build && pnpm --dir examples/react run build:qiankunpnpm --dir examples/vue run build && pnpm --dir examples/vue run build:qiankunpnpm --dir examples/vite run build && pnpm --dir examples/vite run build:qiankunpnpm --dir packages/create-qiankun run buildpnpm --dir packages/create-qiankun run test:e2ehttp://localhost:7099verifying all 4 sub-apps load from expected ports and counters increment under sandbox=true.