[Micro front end] qiankun + vite + vue3

column:

1. Overall structure

Under the qiankun system, a micro-frontend project includes a main application and multiple sub-applications. Essentially, each project (main application) can be developed and run independently.

1.1 Project structure during development

A total of three projects, one main application, two sub-applications, directory structure:

.
├── app-01
│   ├── README.md
│   ├── index.html
│   ├── package.json
│   ├── pnpm-lock.yaml
│   ├── public
│   ├── src
│   ├── tsconfig.json
│   ├── tsconfig.node.json
│   └── vite.config.ts
├── app-02
│   ├── README.md
│   ├── index.html
│   ├── package.json
│   ├── pnpm-lock.yaml
│   ├── public
│   ├── src
│   ├── tsconfig.json
│   ├── tsconfig.node.json
│   └── vite.config.ts
├── main-app
│   ├── README.md
│   ├── index.html
│   ├── package.json
│   ├── pnpm-lock.yaml
│   ├── public
│   ├── src
│   ├── tsconfig.json
│   ├── tsconfig.node.json
│   └── vite.config.ts
└── readme.md

1.2 Deployment project structure

There are many deployment methods to choose from. The method used here is to deploy the three projects on the same server and the same port. The directory structure is:

.
├── index.html
├── static
│   ├── index-011eeef2.css
│   └── index-0ab867b1.js
├── sub
│   ├── app-01
│   │   ├── index.html
│   │   ├── static
│   │   │   ├── index-0244ff29.js
│   │   │   └── index-83c9dd61.css
│   │   └── vite.svg
│   └── app-02
│       ├── index.html
│       ├── static
│       │   └── index-cb440182.js
│       └── vite.svg
└── vite.svg

2. Development

During development, the listening ports corresponding to the three applications:

application port
main-app 80
app-01 8081
app-02 8082

After the project is started, it can be accessed in the browser:

  • http://localhost:80 The overall operation effect
  • http://localhost:8081 app-01 running alone
  • http://localhost:8082 app-02 running alone

2.1 Main application

主应用Used to register sub-applications and control switching between sub-applications.

A. Register sub-applications

Register the sub-application in the main.ts of the newly created vue3 project:

// 开发模式时,entry的值为子应用的开发演示环境的地址
if ("development" === import.meta.env.MODE) {
    
    
  registerMicroApps([
    {
    
    
      name: "app_01",
      entry: "//localhost:8081/",
      container: "#container",
      activeRule: "/app_01",
    },
    {
    
    
      name: "app_02",
      entry: "//localhost:8082/",
      container: "#container",
      activeRule: "/app_02",
    },
  ]);
} else {
    
    
  // 生产环境时,entry的路径为app在部署时的真实路径
  registerMicroApps([
    {
    
    
      name: "app_01",
      entry: "./sub/app-01",
      container: "#container",
      activeRule: "/app_01",
    },
    {
    
    
      name: "app_02",
      entry: "./sub/app-02",
      container: "#container",
      activeRule: "/app_02",
    },
  ]);
}

setDefaultMountApp("/app_01");

// 启动 qiankun
start();

When registering sub-applications, there are two modes, development mode and deployment mode, and the corresponding entryvalues ​​are different.

B. Sub-application routing

<a @click="toApp('/app_01')">app 01</a>
function toApp(path: string) {
    
    
  history.pushState({
    
    }, "", path);
}

It should be noted that the href of the a tag cannot be used here, and a 404 error will be reported, and history.pushStatethe control route must be used.

Because hrefthe attribute will cause the browser to refresh, the resource cannot be obtained.

2.2 Sub-applications

A. Install dependencies

pnpm add vite-plugin-qiankun

vite.config.js

Configuration file modification

export default defineConfig({
    
    
  // 打包时,这里填充的为绝对路径,对应的是部署路径
  base: "/sub/app-01",
  plugins: [
    vue(),
    qiankun("app-01", {
    
    
      useDevMode: true,
    }),
  ],
});

C. Entrance Retrofit

There are two ways to start:

  • start alone
  • Start in the main application

qiankun requires sub-applications to export three interfaces:

  • bootstrap
  • mount
  • unmount
import {
    
    
  renderWithQiankun,
  qiankunWindow,
} from "vite-plugin-qiankun/dist/helper";

import {
    
     App as VueApp, createApp } from "vue";
import router from "./router";
import App from "./App.vue";

let app: VueApp<Element>;
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
    
    
  createApp(App).use(router).mount("#app");
} else {
    
    
  renderWithQiankun({
    
    
    mount(props) {
    
    
      console.log("--app 01 mount");

      app = createApp(App);
      app.use(router);
      app.mount(
        (props.container
          ? props.container.querySelector("#app")
          : document.getElementById("app")) as Element
      );
    },
    bootstrap() {
    
    
      console.log("--app 01 bootstrap");
    },
    update() {
    
    
      console.log("--app 01 update");
    },
    unmount() {
    
    
      console.log("--app 01 unmount");
      app?.unmount();
    },
  });
}

3. Deployment

After the three projects are packaged in sequence, main-appcreate a new sub folder in the packaged output, and move the packaged output of the sub-application to the sub folder. structure:

.
├── index.html
├── static
│   ├── index-011eeef2.css
│   └── index-0ab867b1.js
├── sub
│   ├── app-01
│   │   ├── index.html
│   │   ├── static
│   │   │   ├── index-0244ff29.js
│   │   │   └── index-83c9dd61.css
│   │   └── vite.svg
│   └── app-02
│       ├── index.html
│       ├── static
│       │   └── index-cb440182.js
│       └── vite.svg
└── vite.svg

Start a static web service locally to access the page, for example, use servethe command to start the service:

serve . -p 5500

Access in browser: http://localhost:5500

Four, pits

001. When the main application registers the App, activeRulethere are two modes

hash mode

const getActiveRule = (hash) => (location) => location.hash.startsWith(hash);
registerMicroApps([
  {
    
    
    name: "app-hash",
    entry: "http://localhost:8080",
    container: "#container",
    activeRule: getActiveRule("#/app-hash"),
    // 这里也可以直接写 activeRule: '#/app-hash',但是如果主应用是 history 模式或者主应用部署在非根目录,这样写不会生效。
  },
]);

history mode

registerMicroApps([
  {
    
    
    name: "app",
    entry: "http://localhost:8080",
    container: "#container",
    activeRule: "/app",
  },
]);

002. historyHow to control the switching of sub-applications when the main application is in use

In history mode, the main application will monitor location.pathnamethe changes to switch the loading and unloading of sub-applications.

In the main application, when using a sticky note to switch applications:

<!-- 开发环境时,没有问题 -->
<!-- 部署环境时,会报错:/app_01 404的错误 -->
<a href="/app_01">app 01</a>

The reason for 404, during static deployment: the a tag will trigger the refresh of the browser. After the refresh, the browser initiates a request to the background /app_01, and the background does not have this physical path

Improvement scheme, use history.pushStatethe interface:

<a @click="toApp('/app_01')">app 01</a>
function toApp(path: string) {
    
    
  history.pushState({
    
    }, "", path);
}

The method used history.pushStatewill not trigger the browser's refresh behavior. When the browser pathnamechanges, qiankunit will sense the route change and load the corresponding page.

At this point, if F5the refresh operation is not actively performed, everything is normal. But F5after using it, an error 404 will still be reported. At this time, the background routing needs to cooperate. Take Nginx as an example:

server {
  listen       8080;
  server_name  localhost;

  location / {
    root   html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }

  location /child/vue-history {
    root   html;
    index  index.html index.htm;
    try_files $uri $uri/ /child/vue-history/index.html;
  }
}

6. Source code

Source address: https://github.com/swlws/qiankun-vite-vue3

Guess you like

Origin blog.csdn.net/swl979623074/article/details/129651079