The core goal of the micro front end is to break up the boulder application into several loosely coupled micro-applications that can be autonomous. Many of the designs of Qiankun are based on this principle, such as HTML Entry, sandbox and inter-application communication. Only in this way can we ensure that microapplications can be developed independently and run independently.
One: the core value of the micro front-end architecture
- Stack independent
- Independent development and deployment
- The incremental upgrade
- Independent run time
Two: get started quickly
We divide it into master apps and micro apps. The previous idea was to generate the basic configuration of both projects directly through vue-CLI scaffolding. But halfway through, vue-CLI is too hard to use the webpack5 module federation (there have been various errors, I think the vue-CLI4.x webpack version is 4.x, which is incompatible with Webpack 5 in some places). Build your own configuration using webpack5.
Webpack configuration
Start with WebPack5 to set up a basic configuration to get the project running.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {VueLoaderPlugin} = require('vue-loader/dist/index');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
mode: 'development'.entry: path.resolve(__dirname, './src/main.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].js'
},
module: {
rules: [{test: /.vue$/,
use: [
'vue-loader'] {},test: /.css$/,
use: [
'style-loader'.'css-loader'] {},test: /.js$/,
exclude: /node_modules/,
loader: 'babel-loader'}},devServer: {
// Change webpack4 contentBase to the following
static: {
directory: path.join(__dirname, './dist')},port: 8080
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './index.html'),
filename: 'index.html'.title: 'qiankun-root-app'
}),
new VueLoaderPlugin(),
new CleanWebpackPlugin()
]
};
Copy the code
Qiankun configuration
Main application:
- The installation
qiankun
Yarn Add Qiankun # or NPM I Qiankun-s
- Register the microapplication in the main application and start it
// main.js
import {registerMicroApps, start} from 'qiankun';
registerMicroApps([
{
// The name of the microapplication
name: 'vue-app'.// Microapplication entry
entry: 'http://localhost:8081/'.// The container node selector for the microapplication
container: '#vue-app'.// Activation rules for microapplications
activeRule: '/vue'}]); start();Copy the code
There should be a route and node matching the activation rule in the main application;
<template>
<div>
<router-link to="/">Home page</router-link>
<router-link to="/vue">Vue applications</router-link>
</div>
<router-view></router-view>
<div id="vue-app"></div>
</template>
Copy the code
Son:
- Export the corresponding lifecycle hooks (
bootstrap
,mount
,unmount
)
// main.js
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
render(props);
}
export async function unmount() {
instance.unmount();
instance._container.innerHTML = ' ';
instance = null;
router = null;
history.destroy();
}
Copy the code
- Configure the packaging tool for microapplications
// webpack.config.js
const packageName = require('./package.json').name;
module.exports = {
output: {
library: `${packageName}`.libraryTarget: 'umd'.// WebPack5 jsonpFunction changed to chunkLoadingGlobal
chunkLoadingGlobal: `webpackJsonp_${packageName}`,}};Copy the code
Three: Common problems
1. The routing
- (1) : Both main and micro applications are best
The history (createWebHistory)
Mode;
Main application:
// router/index.js
import {createRouter, createWebHistory} from 'vue-router';
const Home = () = > import('.. /src/components/Home.vue');
const routes = [
{path: '/'.component: Home}
];
const router = createRouter({
history: createWebHistory('/'),
routes
});
export default router;
Copy the code
Application:
Export routes. Instantiate routes in the entry file.
// main.js
import {createRouter, createWebHistory} from 'vue-router';
import routes from '.. /router/index'
let instance = null;
let router = null;
let history = null;
function render(props = {}) {
const {container} = props;
// Base must be set for histroy routes
history = createWebHistory(window.__POWERED_BY_QIANKUN__ ? '/vue' : '/');
router = createRouter({
history,
routes
});
instance = createApp(App);
instance.use(router);
instance.mount(container ? container.querySelector('#app1') : '#app1');
}
Copy the code
- (2) : cross-domain problems
Subapplications need to be configured to allow cross-domain:
// webpack.config.js
devServer: {
headers: {
'Access-Control-Allow-Origin': The '*',}},Copy the code
2. Reuse common dependency libraries
usewebpack
的 externals
The implementation.
Main application:
// webpack.config.js
externals: {
'vue': 'Vue'.'element-plus': 'ElementPlus'
}
Copy the code
// index.html
<link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css">
<script src="//unpkg.com/vue@next"></script>
<script src="//unpkg.com/element-plus"></script>
Copy the code
Micro application: index. HTML address to add ignore, but add ignore error;
No solution has been found; There seems to be a problem with Vue-Router4;
// webpack.config.js
externals: {
'vue': 'Vue'.'element-plus': 'ElementPlus'
}
Copy the code
// index.html
<link ignore rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css">
<script ignore src="//unpkg.com/vue@next"></script>
<script ignore src="//unpkg.com/element-plus"></script>
Copy the code
// main.js
import ElementPlus from 'element-plus';
instance.use(ElementPlus);
Copy the code
3. Reuse common components and methods
- (1) : Directly used when registering microapplications
props
Attribute passing;
Main application:
// main.js
import HeaderComponent from '.. /src/common/header.vue'
import FooterComponent from '.. /src/common/footer.vue'
window.commonComponents = {
HeaderComponent,
FooterComponent
};
let commonComponents = window.commonComponents || {};
registerMicroApps([
{
...
props: {
data: {
commonComponents
}
}
}
]);
// Shared components must have multiple instances enabled
start({ singular: false })
Copy the code
Application:
// main.js
export async function mount(props) {
window.commonComponents = props.data.commonComponents;
render(props);
}
Copy the code
// Home.vue
components: {
HeaderComponent: window.__POWERED_BY_QIANKUN__ ? window.commonComponents.HeaderComponent : ' '.FooterComponent: window.__POWERED_BY_QIANKUN__ ? window.commonComponents.FooterComponent : ' '
}
Copy the code
- (2) : Use
webpack5
Module federal
Main application: put common components and methods into a separate JS and export them;
// commonExport.js
import HeaderComponent from './src/common/header.vue'
import FooterComponent from './src/common/footer.vue'
import utils from './src/utils/index.js'
export {
HeaderComponent,
FooterComponent,
utils
}
Copy the code
// webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
new ModuleFederationPlugin({
name: 'root_app'.filename: "root_app.js".exposes: {
'./commonExport': './commonExport'}})Copy the code
Application:
// webpack.config.js
plugins: [
new ModuleFederationPlugin({
name: 'vue_app'.filename: "vue_app.js".remotes: {
rootApp: 'root_app@http://localhost:8080/root_app.js'}})]Copy the code
// Home.vue
import {onMounted} from 'vue';
// Use common components and methods
import {HeaderComponent, utils} from 'rootApp/commonExport'
export default {
name: 'Home'.components: {
HeaderComponent
},
setup() {
onMounted(() = >{ utils.commonFn(); }}})Copy the code
4. Microapp loaded resources will be 404
Create a public-path.js microapplication and import it in main.js.
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
Copy the code
import './public-path';
Copy the code
5. How do microapplications operate independently?
// main.js
if (!window.__POWERED_BY_QIANKUN__) {
render()
}
Copy the code
6. 404 is refreshed in the micro-application path
This is usually because you are using browser mode routing, which requires the cooperation of the server. The development environment needs to modify devServer
// webpack.config.js
devServer: {
// Resolve microapplication refresh error 404
proxy: {
'/vue/': {
target: 'http://localhost:8080'.changeOrigin: true.pathRewrite: {
'^/vue': ' '}}},historyApiFallback: true
},
Copy the code