什么是微前端?
网上抄的:
微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将单页面前端应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立开发、独立部署。同时,它们也可以在共享组件的同时进行并行开发.
我的理解:
微服务就像是一个操作系统:在其中可以运行多个app。但每个app呢,又可以脱离操作系统独立运行。
为什么选择qiankun.js | qiankun.js优点
大白话:
就目前市面上没有比qiankun.js更好用的了。虽基于 single-spa, 但比它更好用更简单。
qiankun.js官方优点:
简单
任意 js 框架均可使用。微应用接入像使用接入一个 iframe 系统一样简单,但实际不是 iframe。
完备
几乎包含所有构建微前端系统时所需要的基本能力,如 样式隔离、js 沙箱、预加载等。
生产可用
已在蚂蚁内外经受过足够大量的线上系统的考验及打磨,健壮性值得信赖
在vue2项目中落地qiankun.js
在现今项目中落地微前端服务架构,我已经构思和尝试了许久了。
起初因为现有项目使用的是nuxt.js,后为迎合qiankun.js后续项目改用了vue-cli。
最开始接触qiankun.js的时候,看官方文档:一脸懵逼 不知何去何从;偶然间蹭了个公开课后,大概学习了single-spa的原理和搭建qiankun.js项目后,一切变得豁然开朗。所以:任何新的概念、技术,甭管如何高大上和新,使劲啃啃都不难。
实践
主应用(基座)
创建应用
vue create vue-base
// 装vue-router哦
下载qiankun
qiankun.js只在主应用下载,子应用不必下载qiankun.js
npm i qiankun -S
配置main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 导入qiankun.js
import {registerMicroApps,setDefaultMountApp,start} from "qiankun";
Vue.config.productionTip = false
new Vue({
router,
render: h => h( App),
}).$mount('#app');
// 注册子应用
registerMicroApps([
{
name: 'vue app', // 子应用名称
entry: '//localhost:7101', // 子应用入口
container: '#container', // 子应用所在容器
activeRule: '/vue', // 子应用触发规则(路径)
},
]);
// 启动默认应用
setDefaultMountApp('/vue')
// 开启服务
start()
App.vue
<template>
<div id="app">
<a href="/">base</a>
<!-- 子应用 vue app -->
<a href="/vue">vue</a>
<!-- 主应用容器 -->
<router-view></router-view>
<!-- 子应用容器 -->
<div id="container"></div>
</div>
</template>
子应用
创建应用
vue create vue-base
// 装vue-router哦
配置main.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import routes from './router';
Vue.config.productionTip = false;
let router = null;
let instance = null;
function render(props = {}) {
const { container } = props;
router = new VueRouter({
base: '/vue',
mode: 'history',
routes,
});
instance = new Vue({
router,
render: h => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}
// webpack打包公共文件路径
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
// 独立运行
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
// 生命周期
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
console.log('[vue] props from main framework', props);
// storeTest(props);
render(props);
}
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
router = null;
}
router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from './components/Home'
import HelloWorld from "./components/HelloWorld";
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'home',
component: Home,
},
{
path: '/helloword',
name: 'HelloWorld',
component: HelloWorld,
},
{
path: '/about',
name: 'about',
component: () => import(/* webpackChunkName: "about" */ './components/About.vue'),
},
];
export default routes;
vue.config.js
const path = require('path');
const { name } = require('./package');
function resolve(dir) {
return path.join(__dirname, dir);
}
const port = 7101; // dev port
module.exports = {
outputDir: 'dist',
assetsDir: 'static',
filenameHashing: true,
devServer: {
// host: '0.0.0.0',
hot: true,
disableHostCheck: true,
port,
overlay: {
warnings: false,
errors: true,
},
// 跨域
headers: {
'Access-Control-Allow-Origin': '*',
},
},
// 自定义webpack配置
configureWebpack: {
resolve: {
alias: {
'@': resolve('src'),
},
},
output: {
// 把子应用打包成 umd 库格式(必须)
library: `${name}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`,
},
},
};
至此, 完成qiankun.js微服务应用。