You engage in one step with a micro tip end frame - based single-spa

Original Address

  micro front end of my work soon, a colleague chiefs in the company's attempt to implement, I had the honor to participate. Before the emergence of the concept of front-end micro, micro and fire services have emerged, while the front end is borrowed from micro-micro-architecture services produced, they are very similar, we can compare the understanding.

Micro Services Micro front end
A micro service is generally constituted by a set of interfaces, interface address is URL. When the service receives a request micro interface, you will find the appropriate routing logic, the output response content.

Micro-services have a backend gateway, as a single inlet for receiving all client requests the interface, the interface according to the matching relation with the URL of the service, routed to the corresponding service.
A micro-tip end is composed of a set of pages, the page address are URL. When a request is received front-end micro-page URL, it will be routed to find the appropriate components to render the page content.

Micro will have a front end loader , as a single inlet to receive a URL to access all pages, according to the matching relation with the micro-tip of the page URL, load the corresponding modules independently selected

A table
  on the front line also has a lot of micro discussion, thought the micro front-end is a very complex thing, but later found himself personally involved, not difficult to understand the micro front end, then, I will take you step by step you get with a front-end micro frame.
  Micro front-end implementations there are many, today we are using more fire single-spa approach. If you learn, you can try to reconstruct your company's application with the way the micro front end.

We engage in micro front of the background

First of all we need to know what is the micro front end, if I'm here in accordance with the concept say it again, I believe we are more abstract. I am here to talk about the background we engage in micro front end, everyone will know what the micro front end problems can be solved, and then will understand what is the front-end micro.
  Group 2B where I have a lot of business, but the company later use policy changes, there have been many new lines of business, each business has its own line of custom operational functions required in order to meet these new lines of business operational needs, we have to do is:

  1. The original function of switching operations background to join the line of business
  2. Operational functions will be scattered in other platforms migrated
  3. Develop custom function for each line of business and be able to show based on business lines
  4. For line of business customizable features, we will try to be responsible for each business line, which requires each business line technology stack to be used to develop a unified

Final presentation like this below. image.png              
     Figure it


  follows the traditional design program like this, but so will result in the following problems:

  1. Operators need to reconstruct the original background, the main point is reconstructed authentication and business lines to switch this, of course, some interfaces can also do some back-end processing
  2. The cost of migration to other platform features a little high, because using a different technology stack
  3. More and more operational requirements, the platform will become increasingly large, increasingly high cost of maintenance will iteration is not flexible enough, people collaborate cause conflicts

The advantage of using micro front end

Big saying goes, the world, the long period of division, together for a long time to divide, slightly front-end is a perfect solution for both together is divided, in the above scenario, the micro front-end easy to do. Micro embodiment refers to the front of each module are split out of the system, independently developed, deployed independently and integrate all the functions, but these functions complete decoupling modules, different techniques may even be used between the module stack to realization, the old platform functionality can smooth migration .
image.png                    2

  then it is how to achieve it? Next, we use the Vue + single-spa implement a micro front-end system, you can understand the principle of the micro front end.

The basic principle of front-end micro

Micro front-end system requires a main module and a number of sub-module, the module contains the main entrance of the project file, you need to be registered subprojects, according to the route of the sub rendering match, followed by the need to provide a home, login, menu, authentication, business switching. Subprojects do not need to have an HTML file, you only need to export the resource file, resources include js / css / img / fonts and so on. **
When the user enters the front end of the micro system loader is run first (upper table mentioned in a), will each loader module register, the module after successful registration, when a user enters the module, the micro-tip end loader will render the module will then perform hook function:

  • bootstrap life cycle, will perform again at mount time.

  • mount lifecycle, perform a loader mounted.

  • unmount life cycle, sub-module unload time execution.

                     ![image.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAyMC8zLzI2LzE3MTE3NzZjMDhlNGNjNWE?x-oss-process=image/format,png)<br />
    

image 3

single-spa + Vue + Element implement a micro-end system

According to the above principles and flow chart micro front end, I will be single-spa + Vue + Element were constructed to lead us out of the main projects and subprojects, and then completed a real micro front-end applications. After order to facilitate understanding, the explanation to not join switching line of business, but this feature is important to implement without trouble, the students build their own micro front-end can be added to this logic.

Main project

Entry file main.js

Our main project using Vue + Element's technology stack, main.js and traditional Vue Vue target is to complete the project as initialization, below the first realization of a basic entry file main.js, I believe we are very familiar with .

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import Router from 'vue-router';
import routerMap from './router/index';
import App from './App';
import util from '@/common/js/util';
Vue.use(ElementUI);
Vue.use(Router);

// 绑定路由
const router = new Router(routerMap);

router.beforeEach((to, from, next) => {
    if (to.fullPath === '/login' || from.fullPath === '/login') {
        next();
    } else {
        // 判断是否登录
        if (!util.login()) {
            login(); // 登录
        } else {
            next();
        }
    }
});

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

Then you need to configure main.js introduced in the sub-modules come in, we will use the loader when registering sub-module configuration file reference as follows:

export default {
    test: {
        id: 1,
        parent: {
            id: 1,
            name: 'test管理'
        },
        name: 'test模块',
        path: 'http://xxx.com/app.js',
        router: '/test'
    },
    demo: {
        id: 2,
        parent: {
            id: 1,
            name: 'demo管理'
        },
        name: 'demo模块',
        path: 'http://xxx.com/app.js',
        router: '/demo'
    }
};

It is then incorporated in and stored, the add main.js:

import appList from './appList'
util.setCache('appList', appList);

Routing Configuration

It should be noted that the configuration on the route, the main project provides home, menu, login, 404 and other public part of the logic and the relevant page of the menu we use Elemnet of NavMenu components, the other is loader logic and page (Portal page). So routing should be like this:

import Home from '@/views/Home';
import Portal from '@/views/Portal'; // 加载器
import Login from '@/views/Login';
import NotFound from '@/views/404';
export default {
		routes: [
  			{
            path: '/',
          	redirect: '/portal',
            component: Home,
            children: [
                {
                    name: 'Portal',
                    path: `/portal*`,    
                    component: Portal, // 加载模块
                }
            ]
        },
        {
            path: '/login',
            component: Login,
            meta: {
                label: '登录',
                hidden: true
            }
        },
        {
            path: '/404',
            component: NotFound,
            meta: {
                label: '404',
                hidden: true
            }
        },
        {
            path: '*',
            redirect: '/404',
            meta: {
                hidden: true
            }
        }
    ]
}

Loader Portal page

404 and we can design their own login page. The next focus is to achieve the highlight Portal page, the page is actually the entrance of each sub-project, the main logic is to achieve loader, followed directly on the code, the code in front of us step by step to understand.

<template>
    <div id="MICRO-APP"></div>
</template>
<script>
/* eslint-disable */
import util from '@/common/js/util';
import { registerApplication, start, getAppNames, getAppStatus, unloadApplication } from 'single-spa';

export default {
    data() {
        return {};
    },
    methods: {
        registry(key, app) {
            // 去重
            if (getAppNames().includes(key)) {
                return;
            }
            // registerApplication 用于注册我们的子项目,第一个参数为项目名称(唯一即可),第二个参数为项目地址,第三个参数为匹配的路由,第四参数为初始化传值。
            registerApplication(
                key,
                () => {
                    const render = () => {
                        // 渲染
                        return window.System.import(app.path).then(res => {
                            if (res) {
                                return res;
                            } else {
                                return render();
                            }
                        });
                    };
                    return render();
                },
                location => {
                    if (location.pathname.indexOf(app.router) !== -1) {
                        return true;
                    } else {
                        return false;
                    }
                }
            );
        },
        // 注册模块
        async registerApp() {
            const appList = util.getCache('appList');
            for (const key in appList) {
                if (appList.hasOwnProperty(key)) {
                    const app = appList[key];
                    this.registry(key, app);
                }
            }
        }
    },
    mounted() {
        start();   //  启动项目
        this.registerApp();// 注册模块
    }
};
</script>
<style lang="less" scoped>
#MICRO-APP {
    position: relative;
    width: 100%;
    height: 100%;
    z-index: 10;
}
</style>

HTML is only a part of portal page id, sub containers as we will be disposed in the sub-module for the root element MICRO-APP.

Life cycle

Before explaining registerApplication, we first sub-module of the lifecycle registered to make a presentation that will help you be a more profound understanding of the principles of the loader and registration process. Note that I said life cycle refers to the life cycle of registered sub-module of the process, rather than the life cycle of this page.
Registered sub-module after download (loaded), initialization (initialized), is mounted (mounted), unloading (unmounted) and unloaded (removed) and other processes. single-spa will provide the hook function for these processes through the "life cycle." These hook functions include:

  • bootstrap: This function will perform the life cycle of a module before the first sub-mount.
  • mount: a sub-module in the registration process, when activityFunction (registerApplication third argument) returns true, and the sub-module is not mounted state, mount lifecycle function is called. When called, the function will be determined according to the currently activated routing URL, create a DOM element, listening DOM events to present content rendering to the user. Over after mounting, any subsequent changes in the sub-route (e.g., hashchangeor popstatethe like) is not triggered again mount, each module requires its own processing.
  • unmount: Whenever applied activityFunction returns false, but the application has been mounting and unmounting of the life cycle will be called. When you uninstall function is called, it will clean up the DOM element is created when mount applications, event monitor, memory, global variables, and news subscriptions.

Other life cycle page is not discussed in detail, would like to know more, please refer to the official documentation to build applications

Also note: to call these functions is the life cycle need to be implemented at the entrance of each sub-module files, how do we achieve to tell you when he spoke of the sub-module

registerApplication way

This method is defined as follows:

singleSpa.registerApplication(
  app.key,
  application(app.path), 
  activityFunction(app.router),   
  { access_token: 'asnjknfjkds' }
);
function loadingFunction(path) {
  return import(path);
}
function activityFunction(location,router) {
  return location.pathname.indexOf(router) !== -1;
}

Parameters explanation:

  • The first parameter is a key value, requires a unique
  • The second parameter is a callback function, the function must return promise (or "async function" method). This function is not into the Senate, will be called when the first sub-module is downloaded. Results after Promise resolve must return a sub-modules can be resolved. Common implementation is to use the import loading :() => import ( '/ path / to / application.js'), to be able to independently deploy each application, import are used herein SystemJS
  • The third parameter is a function that returns bool value, window.locationis called as the first parameter value is true (truthy) value, the application will be activated when the function returns, usually, Activity function based on window.locationthe back / path to decide whether the application needs to be activated. When activated, if the sub-module is not mounted, mount the life cycle will be executed.
  • The fourth argument is self-defined parameters, and then we can props ** in all lifecycle functions ** customProps receives this parameter this parameter may be useful, for example, the following scenario:
    • Various applications share a common parameters, such as: access_token
    • Issued initialization information, such as render target
    • Passing a reference to the event bus (EventBus), to facilitate communication between applications

summary

These are explained on the main project, the principle is still a little complicated, but it is not the amount of code to implement, conclude that:

  • mian.js main entrance project file, and the initialization process program login logic, the introduction of sub-module configuration file.
  • Routing Configuration
  • Portal page load to perform registerApplication registration, life cycle a bit complicated, but do not understand does not affect the use of

Subprojects

Can be used on any technology stack subprojects in principle, I am here to share with you an example Vue achieve a sub-module.

single-spa-vue

After the completion of the main project, subproject will achieve is very simple, the main thing here is to use single-spa-vue, singleSpaVue is a method of single-spa combination vue, we use it to achieve the sub-module has been registered the life cycle of logic. Its first parameter is a vue, the second argument is what we usually appOptions incoming vue configuration.

Subprojects entrance mian.js

import Vue from 'vue';
import Router from 'vue-router';
import App from './App';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import routerMap from './router';
import store from './store';
import singleSpaVue from 'single-spa-vue';

Vue.use(ElementUI);
Vue.use(Router);

const router = new Router(routerMap);
const vueLifecycles = singleSpaVue({
    Vue,
    appOptions: {
        router,
        store,
        render: h => h(App),
        el:'#MICRO-APP'     // Portal页面中的子模块容器,子模块会被插入到该元素中
    }
});

export const bootstrap = vueLifecycles.bootstrap;
export const mount = vueLifecycles.mount;
export const unmount = vueLifecycles.unmount;


If you want to do something after life cycle functions can be done to lower

const vueLifecycles = singleSpaVue({...})
export const mount = props => vueLifecycles.mount(props).then(instance => {
  // do what you want with the Vue instance
  ...
})

Routing Configuration

import List from '../views/List.vue';
export default {
    mode: 'history',
    base: '/portal',
    routes: [
        {
            path: '/demo',
            redirect: '/demo/list',
            component: List
        },
        {
            name: 'List',
            path: '/demo/list',
            component: List
        }
    ]
};

Routing configuration is the same as conventional, as long as you can pay attention to base settings

summary

These are explained on subprojects

Finally, I would say here, slightly front-end is a good technology, but should also consider the scene, used under appropriate scene is a good technique.

Resources

reference

https://qiankun.umijs.org/zh/
https://tech.meituan.com/2018/09/06/fe-tiny-spa.html
https://alili.tech/archive/ea599f7c/
https://juejin.im/post/5cadd7835188251b2f3a4bb0#comment
https://juejin.im/post/5d7f702ce51d4561f777e258#heading-10
https://juejin.im/post/5d3925615188257f3850de5a

Published 25 original articles · won praise 3 · Views 4472

Guess you like

Origin blog.csdn.net/zdhui_fly/article/details/105136009