|
1 | 1 | --- |
2 | 2 | order: 9 |
3 | 3 | toc: content |
4 | | -translated_at: '2024-03-17T08:50:33.783Z' |
| 4 | +translated_at: '2026-08-17T03:38:01.000Z' |
5 | 5 | --- |
6 | 6 |
|
7 | 7 | # Micro Frontends |
8 | 8 |
|
9 | 9 | `@umi/max` has a built-in **Qiankun Micro Frontends** [plugin](https://github.com/umijs/umi/blob/master/packages/plugins/src/qiankun.ts), which can enable the Qiankun micro frontend development mode with one click, helping you easily integrate Qiankun micro applications in your Umi project, and build a production-ready micro frontend architecture system. |
10 | 10 |
|
11 | | -For more information about Qiankun Micro Frontends, please refer to [this page](https://qiankun.umijs.org/zh/guide). |
| 11 | +For more information about Qiankun Micro Frontends, please refer to [this page](https://qiankun.umijs.org/guide). |
12 | 12 |
|
13 | 13 | ## Micro Frontend Example |
14 | 14 |
|
@@ -98,9 +98,9 @@ export const qiankun = { |
98 | 98 |
|
99 | 99 | Child applications need to export necessary lifecycle hooks for the parent application to call at the appropriate time. |
100 | 100 |
|
101 | | -Assuming your child application project is **developed based on Umi** and **the `qiankun` [plugin](https://github.com/umijs/umi/blob/master/packages/plugins/src/qiankun.ts) is introduced**. If not, you can follow [this tutorial](https://qiankun.umijs.org/zh/guide/getting-started#%E5%BE%AE%E5%BA%94%E7%94%A8) to configure. |
| 101 | +Assuming your child application project is **developed based on Umi** and **the `qiankun` [plugin](https://github.com/umijs/umi/blob/master/packages/plugins/src/qiankun.ts) is introduced**. If not, you can follow [this tutorial](https://qiankun.umijs.org/guide/getting-started#sub-application) to configure. |
102 | 102 |
|
103 | | -:::warning{title=Utoopack compatibility} |
| 103 | +:::warning{title="Utoopack compatibility"} |
104 | 104 | If the child application is built with utoopack and the parent application uses qiankun 2, upgrade qiankun in the parent application to `2.10.17-beta.0` or later. Earlier versions do not provide `document.currentScript` correctly while executing entry scripts, which prevents the child application from loading. For more details, see the Utoo blog post [When Turbopack Meets qiankun: Adapting Utoopack for Micro Frontends](https://utoo.land/en/docs/blog/utoopack-qiankun). |
105 | 105 | ::: |
106 | 106 |
|
@@ -471,4 +471,347 @@ export const qiankun = { |
471 | 471 | }; |
472 | 472 | ``` |
473 | 473 |
|
474 | | -The child application can obtain and consume the `props` properties in the lifecycle hooks [configured according to the requirements](# |
| 474 | +The child application can obtain and use the passed `props` in lifecycle hooks by [implementing the corresponding lifecycle hooks](#child-application-configures-lifecycle-hooks) as needed. |
| 475 | + |
| 476 | +## Custom Child Applications |
| 477 | + |
| 478 | +When a loading indicator or error boundary is enabled for a child application, the child application receives an additional `wrapperClassName` CSS class. The rendered structure is as follows: |
| 479 | + |
| 480 | +```tsx |
| 481 | +<div style={{ position: 'relative' }} className={wrapperClassName}> |
| 482 | + <MicroAppLoader loading={loading} /> |
| 483 | + <ErrorBoundary error={e} /> |
| 484 | + <MicroApp className={className} /> |
| 485 | +</div> |
| 486 | +``` |
| 487 | + |
| 488 | +### Child Application Loading Indicator |
| 489 | + |
| 490 | +After this capability is enabled, a loading indicator is displayed automatically while the child application is loading. When the child application finishes mounting and reaches the `MOUNTED` state, the loading state ends and the child application content is displayed. |
| 491 | + |
| 492 | +#### antd-based Loading Indicator |
| 493 | + |
| 494 | +If your project uses antd, pass the `autoSetLoading` property to the child application to enable its loading indicator. The plugin automatically uses antd's [`<Spin />` component](https://ant.design/components/spin) as the loader. |
| 495 | + |
| 496 | +When introducing a child application through routing, configure it as follows: |
| 497 | + |
| 498 | +```ts |
| 499 | +// .umirc.ts |
| 500 | +export default { |
| 501 | + routes: [ |
| 502 | + { |
| 503 | + path: '/app1', |
| 504 | + microApp: 'app1', |
| 505 | + microAppProps: { |
| 506 | + autoSetLoading: true, |
| 507 | + }, |
| 508 | + }, |
| 509 | + ], |
| 510 | +}; |
| 511 | +``` |
| 512 | + |
| 513 | +When introducing a child application through a component, pass `autoSetLoading` directly: |
| 514 | + |
| 515 | +```tsx |
| 516 | +import { MicroApp } from 'umi'; |
| 517 | + |
| 518 | +export default function Page() { |
| 519 | + return <MicroApp name="app1" autoSetLoading />; |
| 520 | +} |
| 521 | +``` |
| 522 | + |
| 523 | +#### Custom Loading Indicator |
| 524 | + |
| 525 | +If your project does not use antd, or if you want to override the default loading style, provide a custom `loader` component for the child application. |
| 526 | + |
| 527 | +Child applications introduced through routing support this option only in runtime configuration: |
| 528 | + |
| 529 | +```tsx |
| 530 | +// .app.tsx |
| 531 | +import CustomLoader from 'src/components/CustomLoader'; |
| 532 | + |
| 533 | +export const qiankun = () => ({ |
| 534 | + routes: [ |
| 535 | + { |
| 536 | + path: '/app1', |
| 537 | + microApp: 'app1', |
| 538 | + microAppProps: { |
| 539 | + loader: (loading) => <CustomLoader loading={loading} />, |
| 540 | + }, |
| 541 | + }, |
| 542 | + ], |
| 543 | +}); |
| 544 | +``` |
| 545 | + |
| 546 | +When introducing a child application through a component, pass `loader` directly: |
| 547 | + |
| 548 | +```tsx |
| 549 | +import CustomLoader from '@/components/CustomLoader'; |
| 550 | +import { MicroApp } from 'umi'; |
| 551 | + |
| 552 | +export default function Page() { |
| 553 | + return ( |
| 554 | + <MicroApp |
| 555 | + name="app1" |
| 556 | + loader={(loading) => <CustomLoader loading={loading} />} |
| 557 | + /> |
| 558 | + ); |
| 559 | +} |
| 560 | +``` |
| 561 | + |
| 562 | +The `loading` parameter is a `boolean`: `true` means that the child application is still loading, and `false` means that loading has finished. |
| 563 | + |
| 564 | +To share one custom loading indicator across multiple child applications, configure `defaultLoader` in the parent application: |
| 565 | + |
| 566 | +```ts |
| 567 | +// .umirc.ts |
| 568 | +qiankun: { |
| 569 | + master: { |
| 570 | + defaultLoader: '@/defaultLoader', |
| 571 | + }, |
| 572 | +}, |
| 573 | +``` |
| 574 | + |
| 575 | +`defaultLoader` is a file path. By convention, place the file in the [src directory](../guides/directory-structure#src-directory). In Umi, `@` represents the `src` directory. |
| 576 | + |
| 577 | +`defaultLoader` has the same implementation as `loader` and receives a `boolean` `loading` parameter. |
| 578 | + |
| 579 | +```tsx |
| 580 | +// defaultLoader.tsx |
| 581 | +import { Spin } from 'antd'; |
| 582 | + |
| 583 | +export default function (loading: boolean) { |
| 584 | + return <Spin spinning={loading} />; |
| 585 | +} |
| 586 | +``` |
| 587 | + |
| 588 | +Note: `loader` takes precedence over `defaultLoader`. |
| 589 | + |
| 590 | +### Child Application Error Handling |
| 591 | + |
| 592 | +After this capability is enabled, error information is displayed automatically when a child application fails to load. |
| 593 | + |
| 594 | +#### antd-based Error Boundary |
| 595 | + |
| 596 | +If your project uses antd, pass the `autoCaptureError` property to the child application to enable error handling. The plugin automatically uses antd's [`<Result />` component](https://ant.design/components/result) as the error boundary. |
| 597 | + |
| 598 | +For example, the displayed language automatically follows the Umi locale configuration: <img src="https://mdn.alipayobjects.com/huamei_zvchwx/afts/img/A*gAAVRrAJJNEAAAAAAAAAAAAADuWEAQ/original"> |
| 599 | + |
| 600 | +When introducing a child application through routing, configure it as follows: |
| 601 | + |
| 602 | +```ts |
| 603 | +// .umirc.ts |
| 604 | +export default { |
| 605 | + routes: [ |
| 606 | + { |
| 607 | + path: '/app1', |
| 608 | + microApp: 'app1', |
| 609 | + microAppProps: { |
| 610 | + autoCaptureError: true, |
| 611 | + }, |
| 612 | + }, |
| 613 | + ], |
| 614 | +}; |
| 615 | +``` |
| 616 | + |
| 617 | +When introducing a child application through a component, pass `autoCaptureError` directly: |
| 618 | + |
| 619 | +```tsx |
| 620 | +import { MicroApp } from 'umi'; |
| 621 | + |
| 622 | +export default function Page() { |
| 623 | + return <MicroApp name="app1" autoCaptureError />; |
| 624 | +} |
| 625 | +``` |
| 626 | + |
| 627 | +#### Custom Error Boundary |
| 628 | + |
| 629 | +If your project does not use antd, or if you want to override the default error boundary style, provide a custom `errorBoundary` component for the child application. |
| 630 | + |
| 631 | +Child applications introduced through routing support this option only in runtime configuration: |
| 632 | + |
| 633 | +```tsx |
| 634 | +// .app.tsx |
| 635 | +import CustomErrorBoundary from '@/components/CustomErrorBoundary'; |
| 636 | + |
| 637 | +export const qiankun = () => ({ |
| 638 | + routes: [ |
| 639 | + { |
| 640 | + path: '/app1', |
| 641 | + microApp: 'app1', |
| 642 | + microAppProps: { |
| 643 | + errorBoundary: (error) => <CustomErrorBoundary error={error} />, |
| 644 | + }, |
| 645 | + }, |
| 646 | + ], |
| 647 | +}); |
| 648 | +``` |
| 649 | + |
| 650 | +When introducing a child application through a component, pass `errorBoundary` directly: |
| 651 | + |
| 652 | +```tsx |
| 653 | +import CustomErrorBoundary from '@/components/CustomErrorBoundary'; |
| 654 | +import { MicroApp } from 'umi'; |
| 655 | + |
| 656 | +export default function Page() { |
| 657 | + return ( |
| 658 | + <MicroApp |
| 659 | + name="app1" |
| 660 | + errorBoundary={(error) => <CustomErrorBoundary error={error} />} |
| 661 | + /> |
| 662 | + ); |
| 663 | +} |
| 664 | +``` |
| 665 | + |
| 666 | +The `error` parameter is an `Error` object. |
| 667 | + |
| 668 | +To share one custom error boundary across multiple child applications, configure `defaultErrorBoundary` in the parent application: |
| 669 | + |
| 670 | +```ts |
| 671 | +// .umirc.ts |
| 672 | +qiankun: { |
| 673 | + master: { |
| 674 | + defaultErrorBoundary: '@/defaultErrorBoundary', |
| 675 | + }, |
| 676 | +}, |
| 677 | +``` |
| 678 | + |
| 679 | +`defaultErrorBoundary` is a file path. By convention, place the file in the [src directory](../guides/directory-structure#src-directory). In Umi, `@` represents the `src` directory. |
| 680 | + |
| 681 | +`defaultErrorBoundary` has the same implementation as `errorBoundary` and receives an `Error` parameter. |
| 682 | + |
| 683 | +```tsx |
| 684 | +// defaultErrorBoundary.tsx |
| 685 | +export default function (error: Error) { |
| 686 | + return <div>{error?.message}</div>; |
| 687 | +} |
| 688 | +``` |
| 689 | + |
| 690 | +Note: `errorBoundary` takes precedence over `defaultErrorBoundary`. |
| 691 | + |
| 692 | +## Environment Variables |
| 693 | + |
| 694 | +If you have configuration that cannot be written explicitly in `.umirc.ts` or `src/app.ts`, store it in an environment variable file. For example, define the parent application's `.env` file as follows: |
| 695 | + |
| 696 | +```plaintext |
| 697 | +INITIAL_QIANKUN_MASTER_OPTIONS="{\"apps\":[{\"name\":\"app1\",\"entry\":\"//localhost:7001\"},{\"name\":\"app2\",\"entry\":\"//localhost:7002\"}]}" |
| 698 | +``` |
| 699 | + |
| 700 | +Internally, the micro frontend plugin runs `JSON.parse(process.env.INITIAL_QIANKUN_MASTER_OPTIONS)` and merges the result with the existing configuration. The environment variable above is equivalent to the following merged configuration: |
| 701 | + |
| 702 | +```ts |
| 703 | +export default { |
| 704 | + qiankun: { |
| 705 | + master: { |
| 706 | + apps: [ |
| 707 | + { |
| 708 | + name: 'app1', |
| 709 | + entry: '//localhost:7001', |
| 710 | + }, |
| 711 | + { |
| 712 | + name: 'app2', |
| 713 | + entry: '//localhost:7002', |
| 714 | + }, |
| 715 | + ], |
| 716 | + // ...other configuration from .umirc.ts |
| 717 | + }, |
| 718 | + }, |
| 719 | +}; |
| 720 | +``` |
| 721 | + |
| 722 | +When the same option exists in both places, such as `apps`, the value in `.umirc.ts` **overrides** the value from the environment variable. |
| 723 | + |
| 724 | +Similarly, a child application can define the following `.env` file: |
| 725 | + |
| 726 | +```plaintext |
| 727 | +INITIAL_QIANKUN_SLAVE_OPTIONS="{\"enable\":false}" |
| 728 | +``` |
| 729 | + |
| 730 | +This is equivalent to the following configuration: |
| 731 | + |
| 732 | +```ts |
| 733 | +export default { |
| 734 | + qiankun: { |
| 735 | + slave: { |
| 736 | + enable: false, |
| 737 | + // ...other configuration from .umirc.ts |
| 738 | + }, |
| 739 | + }, |
| 740 | +}; |
| 741 | +``` |
| 742 | + |
| 743 | +## API |
| 744 | + |
| 745 | +### MasterOptions |
| 746 | + |
| 747 | +| Property | Required | Description | Type | Default | |
| 748 | +| --- | --- | --- | --- | --- | |
| 749 | +| `enable` | No | Enables the Qiankun micro application plugin; set it to `false` to disable the plugin | `boolean` | `undefined` | |
| 750 | +| `apps` | Yes | Micro application configuration | [`App[]`](#app) | `undefined` | |
| 751 | +| `routes` | No | Runtime routes for micro applications | [`Route[]`](#route) | `undefined` | |
| 752 | +| `defaultErrorBoundary` | No | Default error boundary for child applications, specified as a file path | `string` | - | |
| 753 | +| `defaultLoader` | No | Default loading indicator for child applications, specified as a file path | `string` | - | |
| 754 | +| `sandbox` | No | Whether to enable sandbox mode | `boolean \| { strictStyleIsolation: boolean, experimentalStyleIsolation: boolean }` | `true` | |
| 755 | +| `prefetch` | No | Whether to prefetch micro applications | `boolean \| 'all' \| string[] \| (( apps: RegistrableApp[] ) => { criticalAppNames: string[]; minorAppsName: string[] })` | `true` | |
| 756 | + |
| 757 | +For more information about sandboxing and prefetching, see the [Qiankun API documentation](https://qiankun.umijs.org/api/#startopts). |
| 758 | + |
| 759 | +### SlaveOptions |
| 760 | + |
| 761 | +| Property | Required | Description | Type | Default | |
| 762 | +| --- | --- | --- | --- | --- | |
| 763 | +| `enable` | No | Enables the Qiankun micro application plugin; set it to `false` to disable the plugin | `boolean` | `undefined` | |
| 764 | + |
| 765 | +### App |
| 766 | + |
| 767 | +| Property | Required | Description | Type | Default | |
| 768 | +| --- | --- | --- | --- | --- | |
| 769 | +| `name` | Yes | Name of the micro application | `string` | - | |
| 770 | +| `entry` | Yes | HTML address of the micro application | `string` | `{ script: string[], styles: [] }` | |
| 771 | +| `credentials` | No | Whether to include cookies when fetching the micro application; see the [Qiankun FAQ](https://qiankun.umijs.org/faq/) | `boolean` | `false` | |
| 772 | +| `props` | No | Data passed from the parent application to the micro application; see [Communication Between Parent and Child Applications](#communication-between-parent-and-child-applications) | `object` | `{}` | |
| 773 | + |
| 774 | +### Route |
| 775 | + |
| 776 | +| Property | Required | Description | Type | Default | |
| 777 | +| --- | --- | --- | --- | --- | |
| 778 | +| `path` | Yes | Route path | `string` | - | |
| 779 | +| `microApp` | Yes | Name of the associated micro application | `string` | - | |
| 780 | +| `microAppProps` | No | Micro application configuration | [`MicroAppProps`](#microappprops) | `{}` | |
| 781 | + |
| 782 | +### MicroAppProps |
| 783 | + |
| 784 | +| Property | Required | Description | Type | Default | |
| 785 | +| --- | --- | --- | --- | --- | |
| 786 | +| `autoSetLoading` | No | Automatically manages the micro application's loading state | `boolean` | `false` | |
| 787 | +| `loader` | No | Custom loading-state component for the micro application | `(loading) => React.ReactNode` | `undefined` | |
| 788 | +| `autoCaptureError` | No | Automatically captures micro application errors | `boolean` | `false` | |
| 789 | +| `errorBoundary` | No | Custom error boundary component for the micro application | `(error: any) => React.ReactNode` | `undefined` | |
| 790 | +| `className` | No | CSS class for the micro application | `string` | `undefined` | |
| 791 | +| `wrapperClassName` | No | CSS class for the wrapper around the loader, error boundary, and micro application; applies only when a loader or error boundary is enabled | `string` | `undefined` | |
| 792 | + |
| 793 | +## FAQ |
| 794 | + |
| 795 | +### Child Application Lifecycle Hooks Load, but the Page Does Not Render |
| 796 | + |
| 797 | +If the page reports no errors and the child application's root DOM node exists but is empty, the current URL most likely does not match any route in the child application. |
| 798 | + |
| 799 | +For example, suppose the parent application contains this configuration: |
| 800 | + |
| 801 | +```js |
| 802 | +{ |
| 803 | + path: '/app1', |
| 804 | + microApp: 'app1', |
| 805 | +} |
| 806 | +``` |
| 807 | + |
| 808 | +And the child application contains this route: |
| 809 | + |
| 810 | +```js |
| 811 | +{ |
| 812 | + path: '/user', |
| 813 | + component: './User', |
| 814 | +} |
| 815 | +``` |
| 816 | + |
| 817 | +You must visit `/app1/user` to access the child application's user page. |
0 commit comments