什么是微前端
微前端是一種多個團隊通過獨立發布功能的方式來共同構建現代化 web 應用的技術手段及方法策略。
介紹
qiankun 是一個基於 single-spa 的微前端實現庫,旨在幫助大家能更簡單、無痛的構建一個生產可用微前端架構系統。
qiankun 孵化自螞蟻金融科技基於微前端架構的雲產品統一接入平台,在經過一批線上應用的充分檢驗及打磨后,我們將其微前端內核抽取出來並開源,希望能同時幫助社區有類似需求的系統更方便的構建自己的微前端系統,同時也希望通過社區的幫助將 qiankun 打磨的更加成熟完善
一、配置主應用
1、使用vue cli快速創建應用
2、安裝qiankun
npm i qiankun -S
3、主應用main.js修改如下
import Vue from "vue"; import App from "./App.vue"; import router from "./router"; import store from "./store"; Vue.config.productionTip = false; /** * 中央事件總線EventBus,用於通信。 * 在Vue中可以使用 EventBus 來作為溝通橋梁的概念,就像是所有組件共用相同的事件中心,可以向該中心注冊發送事件或接收事件 */ Vue.prototype.$EventBus = new Vue() import {registerMicroApps,runAfterFirstMounted, setDefaultMountApp, start} from 'qiankun'; import fetch from 'isomorphic-fetch'; let app = null; let count1 = 0; let count = 0; function render({ appContent, loading }) { /*examples for vue*/ if (!app) { app = new Vue({ el: '#app', router, store, data() { return { content: appContent, loading, }; }, render(h) { return h(App, { props: { content: this.content, loading: this.loading, }, }); }, }); } else{ app.content = appContent; app.loading = loading; } } function genActiveRule(routerPrefix) { return location => location.pathname.startsWith(routerPrefix); } render({ loading: true }); const request = url => fetch(url, { referrerPolicy: 'origin-when-cross-origin', }); //注冊子應用 registerMicroApps([ { name: 'child1', entry: '//localhost:7100', render,//普通模式 activeRule: genActiveRule('/child1') }, ], { beforeLoad: [ app => { console.log('before load', app); }, ], beforeMount: [ app => { console.log('before mount', app); }, ], afterMount: [ app => { console.log('after mount', app); }, ], afterUnmount: [ app => { console.log('after unload', app); app.render({appContent: '', loading: false}); }, ], }, { fetch: request, }, ); /** * @description 設置哪個子應用程序在主加載后默認處於活動狀態 * @param defaultAppLink: string 跳轉鏈接 */ setDefaultMountApp('/about'); /** * @description 第一個應用構建完成后執行 * @param 要執行的函數 */ runAfterFirstMounted(() => console.info('first app mounted')); /** * @description 啟動主應用 * @param prefetch 是否在第一次安裝子應用程序后預取子應用程序的資產,默認為 true * @param jsSandbox 是否啟用沙盒,當沙盒啟用時,我們可以保證子應用程序是相互隔離的,默認為 true * @param singular 是否在一個運行時只顯示一個子應用程序,這意味着子應用程序將等待掛載,直到卸載之前,默認為 true * @param fetch 設置一個fetch function,默認為 window.fetch */ start({ prefetch: true, fetch: request });
4、修改App.vue
<template>
<!-- 這里id不能使用默認app,子程序會直接掛在這個節點上,會直接調整到子程序 --> <div id="appmain"> <div id="nav"> <a href="javascript:;" @click="goto('測試','/child1/about1')">Home</a> | <router-link to="/about">About</router-link> </div> <router-view v-if="!ischildApp"/> <div v-html="content" v-show="ischildApp"></div> </div> </template> <script> export default { props: { content: String, }, computed:{ ischildApp:function(){ if(this.$route.path.match('child1')){ return true; }else{ return false; } }, }, methods:{ goto(title, href) { console.log("title",title,"href",href) window.history.pushState({}, title, href); // this.$router.push(op.key) }, } } </script> <style> #appmain { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } #nav { padding: 30px; } #nav a { font-weight: bold; color: #2c3e50; } #nav a.router-link-exact-active { color: #42b983; } </style>
二、配置子應用
1、使用vue cli快速創建應用
2、子應用無需安裝qiankun
3、主應用main.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('#app'); } if (!window.__POWERED_BY_QIANKUN__) { render(); }else { __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; } export async function bootstrap() { console.log('vue app bootstraped'); } export async function mount(props) { console.log('props from main app', props); render(); } export async function unmount() { instance.$destroy(); instance = null; router = null; }
4、vue.config.js修改如下
const path = require('path'); const { name } = require('./package'); function resolve(dir) { return path.join(__dirname, dir); } const port = 7100 module.exports = { lintOnSave: false, 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}`, }, }, }