preface
Microservices have been widely used in back-end Java development, and their concept has become mature. We have a deep understanding of microservices. The concept of micro front end has been around for many years, and the popularity of applications is far less than that of micro services. Recently, I saw on the Internet that there are some solutions for the micro front-end. Summarize several mainstream micro front-end solutions:
- Base mode: mainly based on route distribution, a base application monitors routes and loads different applications according to routing rules to realize decoupling between applications.
- EMP: webpack 5 module Federation, a decentralized micro front-end scheme, can easily realize resource sharing and communication between applications on the basis of application isolation;
The following is based on single-spa of qiankun.js As an example (i.e. base mode), specifically implement the micro front end (the base and micro application are front-end projects in different folders, not under one folder):
Native environment
- @vue/cli 4.5.13
Building base (main application)
The micro front end based on qiankun.js is mainly composed of main application and several micro applications. First, describe the construction of the base
- Create application
# Create a base project. The project of vue2.x is selected here vue create vue-base cd vue-base #Install routing. By default, the project is created without routing. Install the routing here npm install vue-router --save # Install micro front end Library npm install qiankun --save
- Set the port number (it can not be set, but it cannot conflict with other micro applications), vue.config.js
'use strict' module.exports = { devServer: { port: 8081 // Modify the port number you want here, } }
- Set the default route to history mode (no setting will affect the subsequent route switching), router/index.js
import Vue from 'vue' import Router from 'vue-router' import index from '../components/HelloWorld' Vue.use(Router) let router = new Router({ mode: 'history', routes: [ { path: '/', name: 'home page', component: index } ] }) export default router
- Modify main.js to register micro applications
import Vue from 'vue' import App from './App.vue' import router from './router' import {registerMicroApps,setDefaultMountApp,start} from "qiankun"; Vue.config.productionTip = false new Vue({ router, render: h => h(App), }).$mount('#app') // Register subapplications registerMicroApps([ { name: 'vue app', // Sub application name entry: '//localhost:7101', // Sub application entry container: '#container', // Container of sub application activeRule: '/app-vue', // Sub application trigger rule (path) }, { name: 'bigScreen', // Sub application name entry: '//localhost:8080', // Sub application entry container: '#container', // Container of sub application activeRule: '/bigScreen', // Sub application trigger rule (path) }, ]); // Start default application //setDefaultMountApp('/app-vue') // Open the service. See the official document for configuration items start()
- App.vue add container
<template> <div id="app"> <a href="/app-vue">app-vue</a> <br> <!-- Sub application vue app --> <a href="/bigScreen">bigScreen</a> <!-- Main application container --> <router-view></router-view> <!-- Subapplication container --> <div id="container"></div> </div> </template> <script> export default { name: 'App', components: { } } </script> <style> </style>
Here, the main service is deployed. Note that the two a tags are set later for the test jump to two micro applications
Build micro applications
During the test, two micro applications are vue (one port number is 8080 and the other is 7101). Here, I only take one as an example, and the other process is basically the same.
- Create project
# Create a micro application project. The project of vue2.x is selected here vue create app-vue cd app-vue #Install routing. By default, the project is created without routing. Install the routing here npm install vue-router --save
- Modify vue.config.js, mainly to set the port number, allow cross domain (main application cross domain access to micro application), and set the packaging mode (it must be set)
'use strict' const packageName = require('./package.json').name; module.exports = { devServer: { port: 7101, // Modify the port number you want here, headers: { 'Access-Control-Allow-Origin': '*' // Allow cross domain } }, configureWebpack: { output: { library: `${packageName}-[name]`, libraryTarget: 'umd', // Package micro applications into umd library format jsonpFunction: `webpackJsonp_${packageName}`, }, }, }
- Create public-path.js in src directory
if (window.__POWERED_BY_QIANKUN__) { __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; }
Note that if the project enables Eslint, add the following to eslintConfig in package.json, otherwise the compilation will not pass
"globals": { "__webpack_public_path__": true },
- Create a route and set it to history mode. The base path setting is consistent with the activeRule of the main application. router/index.js
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from "../components/HelloWorld"; Vue.use(Router) let router = new Router({ mode: 'history', base: window.__POWERED_BY_QIANKUN__ ? '/app-vue/' : '/', routes: [ { path: '/', name: 'home page', component: HelloWorld }, ] }) export default router
- Write a few text data in HelloWorld.vue to facilitate comparison
<template> <div class="hello"> <h1>vue-app</h1> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h3 { margin: 40px 0 0; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
- mian.js has changed a little more than the original
import Vue from 'vue' import App from './App.vue' import router from './router' import './public-path' Vue.config.productionTip = false let instance = null; function render(props = {}) { const { container } = props; instance = new Vue({ router, render: (h) => h(App), }).$mount(container ? container.querySelector('#app') : '#app');// Avoid conflicts with primary applications } // Stand alone runtime if (!window.__POWERED_BY_QIANKUN__) { render(); } //There must be the following three life cycles, otherwise the main application cannot be called export async function bootstrap() { console.log('[vue] vue app bootstraped'); } export async function mount(props) { console.log('[vue] props from main framework', props); render(props); } export async function unmount() { instance.$destroy(); instance.$el.innerHTML = ''; instance = null; }
Test use
One main application and two micro applications are started with npm run serve. First access the main application as follows:
Click app Vue
Click bigScreen
The second application style has some problems and needs to be adjusted
summary
- qiankun.js is relatively simple in general, and the effect of use is also good
- However, there are still many problems in the construction process, and what the official website said is not very clear
- Overall, it is somewhat similar to iframe nesting, except that iframe is replaced by div
- There is still a lot to study in the follow-up