Qiankun micro front-end

Why not use iframe

The most important feature of iframe is that it provides a browser native hard isolation scheme, no matter the style isolation, JS isolation and other problems can be solved perfectly. However, its biggest problem is that its isolation can not be broken, leading to the application context can not be shared, resulting in the development experience, product experience problems.

The disadvantages of the iframe

  1. The URL is not synchronized. The browser refresh iframe URL status is lost, and the back forward button is unavailable.
  2. The UI is not synchronized and the DOM structure is not shared. Imagine an iframe with a mask layer in the bottom right corner of the screen, and we want it to be centered in the browser and automatically centered when the browser resize
  3. The global context is completely isolated and memory variables are not shared. Iframe internal and external system communication, data synchronization and other requirements, the cookie of the main application should be transparently transmitted to the sub-applications with different root domain names to achieve the effect of free registration.
  4. Slow. Each child application entry is a process of browser context reconstruction and resource reloading.

The micro front-end architecture has the following core values:

  • Technology stack independent main framework does not limit access to the application stack, microapplications have full autonomy

  • Independent development, independent deployment of micro application warehouse independent, the front and back end can be independently developed, after the deployment of the main framework automatically complete synchronization update

  • Incremental upgrade In the face of a variety of complex scenarios, it is usually difficult to upgrade or reconstruct the existing system technology stack completely, and the micro front end is a very good method and strategy to implement the incremental reconstruction

  • Independent run time States are isolated between each microapplication and run time states are not shared

Without further ado, the code in the construction of qiankun micro front end to build a main application of a base

Vue react jquery Angular…

Qiankun Main Application (Base)

1.We used qiankun + VUe2. 0As an example, a master application and a sub-application were created with the routing mode of history mode Vue CREATE Qiankun -mainCopy the code
// 2. In the main application qiankun-mainNPM install Qiankun --saveCopy the code

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'

import { registerMicroApps, start } from 'qiankun' // Add two methods in Qiankun
const apps = [{
    name: 'vueApp'.// The name of the child application
    entry: 'http://172.18.61.27:8083'.// The domain name of the subapplication
    container: '#vue'.// The container that hosts the child application, as defined in app.vue above
    activeRule: '/vue'.// Route of the activated subapplication
}]
registerMicroApps(apps); // Register child applications
start(); / / start qiankun

new Vue({
    router,
    render: h= > h(App)
}).$mount('#app');
Copy the code

src/router/index.js


import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from ".. /views/home/home.vue";
import About from ".. /views/about";

Vue.use(VueRouter)

const routes = [{
        path: '/'.name: 'Home'.// redirect: '/home',
        component: Home,
    },
    {
        path: '/about'.name: 'About'.component: About,
    },

]

const router = new VueRouter({
    routes,
    base: ' '.mode: 'history',})export default router
Copy the code

app.vue

<template>
	<div id="app">
		<div id="nav">
			<router-link to="/">Home</router-link> |
			<router-link to="/about">About</router-link> |
			<router-link to="/vue">VueApp</router-link> <! -- New section -->
		</div>
		<router-view />
		<div id="vue"></div><! -- New section for hosting child applications -->
	</div>
</template>
Copy the code

vue.config.js

module.exports = {
    lintOnSave: false.// Disable ESLint detection
    devServer: {
        port: 8084.// The port must be the same as the child application port configured by the parent application
        headers: {
            Since all internal requests in Qiankun are fetch requests for resources, sub-applications must be allowed to cross domains
            'Access-Control-Allow-Origin': The '*'
        },
        overlay: {
            warning: false.errors: false}},configureWebpack: {
        output: {
            // Resource packaging path
            library: 'vueApp'.libraryTarget: 'umd'}}}Copy the code

Sub-applications (microservices)

vue create qiankun-child
Copy the code

min.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

let instance = null;

function render(props = {}) {
    const { container } = props;
    instance = new Vue({
        router,
        store,
        render: h= > h(App),
    }).$mount(container ? container.querySelector('#app') : '#app');
}
export async function mount(props) {
    render(props);
}

// Determine whether the current operating environment is running independently or in the parent application, configure the global common resource path
if (window.__POWERED_BY_QIANKUN__) {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
__POWERED_BY_QIANKUN__=undefined
if (!window.__POWERED_BY_QIANKUN__) {
    render()
}
// The last three exposed methods are fixed: load render and destroy
export async function bootstrap() {}
// export async function mount(props){
// render();
// } 
export async function unmount() {
    instance.$destroy();
}
export async function update(props) {
    // console.log('update props', props);
}
Copy the code

src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Music from '.. /views/Home.vue'
import '.. /public-path'

Vue.use(VueRouter)

const routes = [{
        path: '/Music'.name: 'Music'.component: Music
    },
    {
        path: '/Dome'.name: 'Dome'.component: () = >
            import ( /* webpackChunkName: "about" */ '.. /views/About.vue')}]const router = new VueRouter({
    mode: 'history'.base: window.__POWERED_BY_QIANKUN__ ? '/vue' : '/',
    routes
})

export default router
Copy the code

app.vue

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/Music">Music</router-link> |
      <router-link to="/Dome">About</router-link> |
      <router-link to="/about">MVVM</router-link>
    </div>
    <router-view/>
  </div>
</template>
Copy the code

vue.cofig.js

module.exports = {
    lintOnSave: false.devServer: {
        port: 8083.headers: {
            "Access-Control-Allow-Origin": "*"}},configureWebpack: {
        output: {
            library: 'vueApp'.libraryTarget: 'umd'}}}Copy the code

Effect of the page

Subpage application

Home page

Nested page