讓前端走進微時代,微微一弄很哇塞!

2021-01-08 EAWorld


●●●


微前端這個詞這兩年很頻繁的出現在大家的視野中,主要是把微服務的概念引入到了前端,讓前端的多個模塊或者應用解耦,做到讓前端的子模塊獨立倉儲,獨立運行,獨立部署。


下面是微前端的概念圖。


為什麼需要微前端?


1.項目前端是單體應用即負責貌美如花還要賺錢養家,而後端使用微服務只需要負責分家家然後給前端送朵花花。前端單體承擔了所有的接口。


2.系統模塊增多,前端單體應用變得肥胖,開發效率低下,構建速度變慢。前端心想:哼,老娘就使勁的吃,瀏覽器也別想看見我,卡死你。


3.公司人員擴大,需要多個前端團隊獨立開發,獨立部署,如果都在一個倉儲中開發會帶來一系列問題,例如:老子辛苦一天寫的代碼,第二天讓別人弄沒了。


4.解決遺留系統問題,新模塊需要使用最新的框架和技術,舊系統還繼續使用。


5.單體前端帶來的測試問題。前端小姐姐分模塊測試,這時正遇到構建發布,多人運動戛然而止。


6.編不下去了。。。。。。


微前端技術選型之路


目前關注度和成熟度最高的應該就是 single-spa,但是國內也有很多團隊都有自己的微前端框架,像螞蟻金服的qiankun,phodal 的 mooa,阿里飛冰的icestark,這些都是比較出名的微前端解決方案。但是這些框架都有一定的局限性,像mooa是針對Angular 打造的主從結構的微前端框架,icestark是最近才出的方案,而qiankun官網的開發文檔就僅僅的幾十行。本文將對qiankun進行幾個方面講解。


聊一聊qiankun


沒錯,qiankun正是光天化日,朗朗乾坤的乾坤。qiankun是一個開放式微前端架構,支持當前三大主流前端框架甚至jq等其他項目無縫接入。


qiankun是基於路由配置,適用於 route-based 場景,通過將微應用關聯到一些 url 規則的方式,實現當瀏覽器 url 發生變化時,自動加載相應的微應用的功能。


qiankun在Vue項目中的使用


1、微前端構建


構建主應用


1、使用vue腳手架初始化項目或者原有Vue項目


2、npm install qiankun --save下載qiankun微前端方案依賴


3、改造主項目,很簡單,在src創建一個qiankun文件夾,創建init.js文件,文件內容:


import {

registerMicroApps, // 註冊子應用方法

setDefaultMountApp, // 設默認啟用的子應用

runAfterFirstMounted, // 有個子應用加載完畢回調

start, // 啟動qiankun

addGlobalUncaughtErrorHandler, // 添加全局未捕獲異常處理器

} from "qiankun";

function genActiveRule(routerPrefix) {//路由監聽

return location => location.pathname.startsWith(routerPrefix);

}

export default function startQiankun() {

const apps = [//子應用配置

{

name: 'admin',

entry: "//localhost:9528",

container:'#admin',//將子應用節點掛載到父應用定義id=admin的div上

activeRule: genActiveRule('/admin'),//路由前綴

props: {mag:」我是主應用」} //父應用給子應用傳參

}

]

//註冊子應用

registerMicroApps(apps, {

beforeLoad: [//子應用加載生命周期,下同

app => {

console.log("before load", app);

}

],

beforeMount: [

app => {

console.log("before mount", app);

}

],

afterUnmount: [

app => {

console.log("after unload", app);

}

]

})

// 設置默認子應用

// setDefaultMountApp('/admin');

// 第一個子應用加載完畢回調

runAfterFirstMounted((app) => {

console.log(app)

});

// 啟動微服務

start({

prefetch: 'all'//預加載子應用靜態資源

});

// 設置全局未捕獲一場處理器

addGlobalUncaughtErrorHandler(event => console.log(event));

}


4、在App.vue中加入<div id="admin"></div>即可


<template>

<div :class="classObj">

<div v-if="device === 'mobile' && sidebar.opened" @click="handleClickOutside"></div>

<sidebar v-if="!isFullModel"></sidebar>

<div :style="isFullModel?'margin-left:0px;':''">

<navbar></navbar>

<tags-view v-if="!isFullModel"></tags-view>

<div id="admin" :style="`height:calc(100vh - ${isFullModel ? 54: 84}px);`"></div>//子應用盒子

</div>

</div>

</template>


5、最後將init.js在main.js引入


import startQiankun from './qiankun/init/index'

let app = null

async function render({ appContent, loading } = {}) {

if (!app) {

await ReadConfig(Vue)//加載配置文件

app = new Vue({

router,

store,

i18n,

render: h => h(App),

}).$mount('#app')

} else {

// app.content = appContent;

// app.loading = loading;

console.log(loading, appContent)

}

}

render()

startQiankun()


構建子應用


1、使用vue腳手架初始化項目


2、在main.js中加入:


let router = null;

let instance = null;

if (window.__POWERED_BY_QIANKUN__) {

//處理資源

__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;

}

//下面的 /admin 與主應用 registerMicroApps 中的 activeRule 欄位對應

function render(props = {}) {

const {container} = props

router = new VueRouter({

base: window.__POWERED_BY_QIANKUN__ ? '/admin' : '/',

mode: 'history',

routes,

});

const create = async () => {

// await ReadConfig(Vue)

instance = new Vue({

router,

render: h => h(App),

}).$mount(container ? container.querySelector('#app') : '#app');

}

create()

}

if (!window.__POWERED_BY_QIANKUN__) {//判斷是否在qiankun環境下

render();

}

// 導出子應用生命周期 掛載前

export async function bootstrap(props) {

console.log('[vue] vue app bootstraped');

}

export async function mount(props) {// 導出子應用生命周期 掛載前 掛載後

render(props);

}// 導出子應用生命周期 掛載前 卸載後

export async function unmount() {

instance.$destroy();

instance = null;

router = null;

}


3、創建vue.config.js文件,需要做一些打包配置。


const path = require('path');

const packageName = require('./package').name;

function resolve(dir) {

return path.join(__dirname, dir);

}

const dev = process.env.NODE_ENV === 'development'

const port = 9528; // dev port

module.exports = {

publicPath: dev ? `//localhost:${port}` : '/',

outputDir: 'dist',

assetsDir: 'static',

filenameHashing: true,

devServer: {

hot: true,

historyApiFallback: true,

port,

overlay: {

warnings: false,

errors: true,

},

headers: {

'Access-Control-Allow-Origin': '*',

},

},

// 自定義webpack配置

configureWebpack: {

resolve: {

alias: {

'@': resolve('src'),

},

},

output: {// 把子應用打包成 umd 庫格式

library: `${packageName}-[name]`,

libraryTarget: 'umd',

jsonpFunction: `webpackJsonp_${packageName}`,

globalObject: 'this',

},

},

};


2、微前端解決的問題


自此,一個父子前端微應用搭建成功,當然這只是簡單的vue實現,真正複雜的是一個項目中每個模塊使用不同的前端框架。效果如下:


我們可以看到A模塊、B模塊和C模塊三個微應用分別運行在Vue、React和Angular的環境中,而主應用主要提供了NavBar和SideBar的界面。中心是微應用中組件顯示的界面。


我們從圖中可以看出將前端微服務化後解決了什麼問題:


1、當A模塊需要維護時,只需要動A模塊的代碼,維護完成之後對A項目進行構建發布,由於體積很小,構建發布就很快。


2、當A項目構建發布時,其他應用運行正常,避免了之前單體應用構建發布導致整個前端項目無法訪問。


3、主應用可以捕捉到子應用的運行狀態,如果子應用出現異常或者掛掉,可以對用戶進行友好提示。例如當A模塊掛掉後,用戶點擊其功能一將提示「功能正在維護中」。


4、由於子應用運行的環境不同,項目可以加入各種各樣的技術棧,解決了前端人員因為技術棧不同無法聚合的問題。


5、每個子項目擁有獨自的倉儲,代碼易維護,並且可以用到別的項目中,這樣一來,每個微前端又可以作為一個微應用提供服務。


3、微前端開發中需要解決的問題


父子應用通信


父向子通信(Shared 通信方案)


Shared 通信方案的原理就是,主應用基於 Vuex維護一個狀態池,通過 shared 實例暴露一些方法給子應用使用。同時,子應用需要單獨維護一份 shared 實例,在獨立運行時使用自身的 shared 實例,在嵌入主應用時使用主應用的 shared 實例,這樣就可以保證在使用和表現上的一致性。


1、在主應用中創建shared.js,可以將需要給子應用傳的數據通過getter和setter的方式設置。


import store from "../../store";

class Shared {

//獲取 Token

getToken() {

const state = store.state;

return state.user.token || "";

}

setToken(token) {

// 將 token 的值記錄在 store 中

store.commit('SET_TOKEN',token);

}

}

const shared = new Shared();

export default shared;

2、在init.js註冊的子應用中,將shared傳遞過去


const apps = [

{

name: 'admin',

entry: "//localhost:9528",

container:'#admin',

activeRule: genActiveRule('/admin'),

props: {

shared,//將數據以類的方式傳遞

}

}

]

3、當主應用登錄成功之後可以通過調用shared.setToken(token)設置token,然後主應用通過自身路由跳轉到主頁this.$router.push({ path: '/' })。


4、現在,我們來處理子應用需要做的工作。我們希望子應用有獨立運行的能力,所以子應用也應該實現 shared,以便在獨立運行時可以擁有兼容處理能力。代碼實現如下:


class Shared {

//獲取 Token

getToken() {

// 子應用獨立運行時,在 localStorage 中獲取 token

return sessionStorage.getItem("token") || "";

}

setToken(token) {

// 子應用獨立運行時,在 localStorage 中設置 token

sessionStorage.setItem("token", token);

}

}

class SharedModule {//通過SharedModule 來維護shared

static shared = new Shared();

static overloadShared(shared) {

SharedModule.shared = shared;

}

static getShared() {

return SharedModule.shared;

}

}

export default SharedModule;


5、接下來我們只需要在子應用的入口文件接受父應用傳來的shared,然後設置到SharedModule 中。


export async function bootstrap(props) {

const {shared = SharedModule.getShared() } = props;

SharedModule.overloadShared(shared);

}


6、然後子應用就可以在組件中通過SharedModule獲取shared然後得到token,最後發起網絡請求。


mounted () {

const shared = SharedModule.getShared();

const token = shared.getToken();

let resp =await this.dispatch(AppController.findById, {id: this.currentApp.appId})//封裝之後的網絡請求

...

}


子向父通信(emit通信)


emit通信的原理是子應用通過觸發父應用傳遞的函數來改變父應用vuex中維護的狀態,進而達到子應用想父應用的通信。這裡以子應用向父應用發送token失效,讓父應用跳轉至登錄頁的場景。


1、父應用定製提供子應用觸發token註銷的函數


import store from "../../store";

import { removeToken } from '@/utils/auth'

function logout(childThis) {

removeToken()

childThis

.$confirm('登錄信息已過期!', '提示', {

confirmButtonText: '重新登錄',

type: 'warning',

center: true,

showClose: false,

showCancelButton: false,

closeOnClickModal: false,

})

.then(() => {

store.dispatch('FedLogOut')

})

}

export {

logout

}



2、將父應用定製的函數傳遞至子應用


const apps = [

{

name: 'admin',

entry: "//localhost:9528",

container:'#admin',

activeRule: genActiveRule('/admin'),

props: {

shared,

emitFnc: childEmit,//將上述的函數傳遞子應用

}

}

]


3、子應用獲取並註冊到子應用的全局變量中


export async function bootstrap(props) {

const {emitFnc , shared = SharedModule.getShared() } = props;

SharedModule.overloadShared(shared);

Object.keys(emitFnc || {}).forEach(i => {

Vue.prototype[`$${i}`] = emitFnc[i]

});

}


4、子應用通過在組件中調用this.$logout(this)即可完成通信。


公共資源共享


項目中存在大量的公共資源,例如公共方法,公共組件,公共UI。在開發的時候不可能每個項目都複製一遍,這樣既降低了開發效率,同時項目的體積增大,構建速度變慢。所以對於微前端項目,我們需要定製一套合適的方案將公共資源抽離出來,子應用可以在運行期動態獲取到資源並加以使用,就像maven的頂級pom,將公共的jar抽離了出來。


1、這裡以公共組件為例,將定義好的公共組件放置主應用的文件夾中並導出,創建一個js文件專門作為公共組件。


import InputEditor from './input-editor/src' //自定義公共組件

import ClipButton from './clip-button/src' //自定義公共組件

const components = [InputEditor,ClipButton];

const install = function (Vue) {

components.forEach(component => {

Vue.component(component.name, component);

});

};

if (typeof window !== "undefined" && window.Vue) {

install(window.Vue);

}

export default {

install,

};


2、同樣的,將此文件作為參數傳遞至子應用。


const apps = [

{

name: 'admin',

entry: "//localhost:9528",

container:'#admin',

activeRule: genActiveRule('/admin'),

props: {

shared,

emitFnc: childEmit,

components: Components//公共組件

}

}

]


3、子應用接收到參數後,將組件註冊到自身的項目中


export async function bootstrap(props) {

const {emitFnc ,components, shared = SharedModule.getShared() } = props;

SharedModule.overloadShared(shared);

Vue.use(components) //註冊組件

Object.keys(emitFnc || {}).forEach(i => {

Vue.prototype[`$${i}`] = emitFnc[i]

});

}


4、子應用可以在任何組件中使用父應用傳遞的組件。需要注意的是,使用公共組件的名稱要和註冊組件的名稱保持一致,其他公共js類似。


通過父子間通信,我們大致可以了解到項目中如何實現鑑權,因為前端鑑權是一個難點,在微前端中鑑權方案有很多種,有興趣的小夥伴可以嘗試著去實現自身項目中的鑑權方案。


總結


qiankun,意為統一。通過 qiankun 這種技術手段,讓你能很方便的將一個巨石應用改造成一個基於微前端架構的系統,並且不再需要去關注各種過程中的技術細節,做到真正的開箱即用和生產可用。


關於作者:卜壯,普元前端開發工程師,負責Mobile 8.0項目管理平臺前端部分。熟悉ReactNative,目前正在學習Vue,大前端技術探求者。

關於EAWorld:微服務,DevOps,數據治理,移動架構原創技術分享。

相關焦點

  • 上微前端後,我司的祖傳代碼有救了
    愛奇藝號也開發了一套微前端架構,成功在開發環境中將代碼熱更新的速度提升了 90% 以上。為了解微前端在實踐中的更多真實收益,近日,我們採訪了愛奇藝資深前端工程師楊昊一,他在 QCon+ 案例研習社分享了題為《愛奇藝號微前端從零到一架構實踐》的演講。前端圈子永遠不乏新概念。幾年前提起微前端,還會有一大把的人問這是什麼意思,驚訝於前端和微服務竟然能產生聯繫。
  • 抖音微微就是秋天裡每片落葉是什麼歌 微微歌詞
    下面一起來看看《微微》的歌詞吧。下面一起來看看《微微》的歌詞吧。 微微就是彩虹裡每滴雨點 微微她很渺小卻從不疲倦 微微就是我們 微~~~~~微 多少次跌跌撞撞才學會堅強 多少次在迷茫之中尋找方向 多少次跌倒之後再站起來面對再勇敢去闖啊 微微晨光點亮這喧囂世界 微微溫暖融化昨夜的冰雪 就像是每一秒都稱為歲月 微微從不停歇
  • 微微就是秋天裡每片落葉微微就是彩虹裡每滴雨點是什麼歌哪裡能聽
    那麼,抖音微微就是秋天裡每片落葉微微就是彩虹裡每滴雨點是什麼歌?抖音微微就是秋天裡每片落葉微微就是彩虹裡每滴雨點是什麼歌:  這首歌曲的歌名叫做《微微》,是由傅如喬演唱的一首歌曲。  該歌曲最開始出現在節目《青春有你2》中,是練習生傅如喬的初印象表演曲目,非常好聽,很溫柔的一首歌曲。該歌曲受到很多歌迷朋友的喜歡。
  • 前端架構是什麼?它又有什麼準則呢?
    什麼是前端架構?架構就是用一定技術、管理手段貫聯開發、業務、項目之間內在聯繫的方案;所謂前端架構只是加了個定性詞兒——前端限定了架構範圍,其他並無差異架構的準則經過多年的架構經驗總結出七大準則1. 適度設計(第一準則)a) 架構設計應以滿足一定周期內的需求為目標。
  • EV集團與中芯寧波攜手,實現砷化鎵射頻前端模組晶圓級微系統異質集成
    >  SEMICON CHINA,2019 年 3 月 20 日——晶圓鍵合和光刻設備的領先供應商EV集團(EVG)今日宣布,與總部位於中國寧波的特種工藝半導體製造公司中芯集成電路(寧波)有限公司(以下簡稱「中芯寧波」)合作,開發業界首個砷化鎵射頻前端模組晶圓級微系統異質集成工藝技術平臺。
  • 配色很哇塞蓋婭傳說 國風服飾秀場
    配色很哇塞蓋婭傳說 國風服飾秀場 2020-11-19 14:58
  • 《微微一笑很傾城》肖奈微微相遇,卻不知遊戲中早已認識!
    楊洋被譽為新時代四大流量小生,而楊洋主演的《微微一笑很傾城》也是一部非常火的作品,這部劇的作者也是《何以笙簫默》顧漫的作品,故事是以網路遊戲為基礎,男主人公肖奈和女主人貝微微在遊戲裡認識,在現實中相遇、相知、相愛的,當然這也是一部很溫馨的愛情小說。
  • 前端成像或將開啟「視覺2.0時代」
    雖然算法足夠優秀,但產品落地卻困難重重,原因是忽略了前端成像的重要作用。 「計算機視覺的前端成像技術,背後是至少100億數量級的龐大需求!」朱繼志認為,要徹底解決這一難題,關鍵在於做好AI視覺產品的前端成像。要克服AI機器在複雜光線下的圖像識別,就要首先解決圖像的獲取和前端處理。目前,業內主流的解決方案有3種。第一種就是我們所熟知的雷射雷達,在光線不好的情況下,通過主動發射雷射並利用光線反射來獲取物體的圖像和三維信息。
  • 微微一笑很傾城歌曲大全 微微一笑很傾城原聲碟發布
    8月25日,電視劇《微微一笑很傾城》原聲音樂正式公布。繼先行曲目曝光後,電視劇《微微一笑很傾城》影視原聲大碟今日正式發布,整張大碟共包括9首曲目,分別是:片頭曲《一笑傾城》、片尾曲《微微一笑很傾城》、插曲《下一秒》、推廣曲《一笑傾城
  • 點評|半導體市場缺貨原因複雜;射頻前端模組化已成趨勢,佔領模組...
    集微點評:半導體市場缺貨原因複雜,市場傳聞會持續一年甚至兩年,預見未來總是很難,短期內肯定很難解決。從PAMiD看射頻前端模塊化的演進與未來隨著射頻前端模塊技術的逐步成熟,當前集成多模多頻的PA、RF開關及濾波器的模組化程度相對較高的PAMiD(集成雙工器的功放模塊)在5G時代的需求不斷增長,但研發實力和供應鏈整合能力的差異,對國內射頻前端廠商而言,仍是掣肘。
  • 慧智微李陽:5G大連接時代需要化繁為簡,與時俱進的智能射頻前端
    集微網消息(文/Oliver),10月29日,第十五屆「中國芯」集成電路產業促進大會的5G通信晶片論壇上,慧智微創始人兼CEO李陽以《可重構射頻前端 助力5G大連接時代》為主題,剖析了5G浪潮下國產射頻前端的發展機遇與挑戰。「4G改變生活,5G改變社會。以往通信技術的進步是不斷優化人與人的連接,但5G是面向物與物的連接,實現萬物互聯。」
  • 男生「微燙」髮型個性魅力,造型不誇張,比一般的髮型帥多了
    男孩子長相不是問題,剪一款好看的髮型,就能提升自己的顏值。而「微燙」髮型就是一種不錯的選擇!很多男生都喜歡捯飭頭髮,但是大多數都是按照自己原來的發質來弄,再怎麼捯飭也不會有太大的突破。所以,如果能夠稍微燙一下頭髮,那麼就可以擁有更多帥氣的造型了。下面這3款「微燙」髮型個性魅力,造型不誇張,剪起來比一般的髮型帥多了。
  • 曾經的迷茫,WEB前端是做什麼的?
    web前端開發如果你經歷過痛苦的IE6時代,如果你現在還在做網頁開發,也許這一切不用解釋但在這個前端培訓機構多如牛毛,一批批培訓人員從培訓機構輸出的時代,幾乎大多數人不太清楚web前端這個名詞的起源。他們僅知道的是,從事這個行業會有很好的發展前途,會拿到不錯的薪水,至少很多的招聘機構是這麼寫的,也有不少的公司求賢若渴,給出的薪水很高。也許大家都知道,web前端是做網頁設計的。
  • Web前端是做什麼的?
    Web前端開發工程師是一個相對較新的行業,在國內外真正開始受到關注不到5年。Web前端的發展是從網頁製作演變而來的,其名稱具有明顯的時代特徵。網際網路的演化過程中,網頁製作是Web1.0時代的產物,當網站的主要內容是靜態的時候,用戶使用網站的行為多數也只是瀏覽。
  • 原創微視頻 | 聽總書記講新時代學雷鋒
    (央視新聞客戶端)2019年學雷鋒日到來之際,一段微視頻帶你回顧總書記對「雷鋒精神」時代意義的闡釋。  2018年9月28日,習近平在遼寧省考察期間,來到撫順市雷鋒紀念館。撫順是雷鋒的第二故鄉,是雷鋒精神的發祥地。總書記在參觀紀念館時說,「雷鋒是一個時代的楷模。
  • 人民日報:「微時代」的偏激與極化
    原標題:「微時代」的偏激與極化(深聚焦·關注「微時代」的社會心態(三)) 另一方面,「微時代」的匿名表達和碎片化書寫,也成為情緒極化的助推器。   「微時代」的成熟期還遠沒有到來。隨著技術平臺的不斷革新,越來越多的人加入進來,利用全新的媒介形態表達立場,甚至進行觀點的對抗和博弈。但如何在滿足個體自由表達的同時,引導「微而不惡」,仍是「微時代」的重大課題。   日漸嚴重的偏激與極化現象,就是亟待解決的問題之一。
  • 從微前端到微後端,不可思議的前端架構思考
    背景微服務的概念已經過去了好久,微前端也已經實踐了一段時間,在去年不同的分享會上都有聽到各家公司關於微前端的實踐,總體來說,微前端是因為前端架構的不斷演進
  • 楊洋唱響青春歌單 《微微一笑很傾城》暖心上線
    》片尾曲、插曲《微微一笑很傾城》音頻、MV雙雙發布,這也是楊洋首度為電視劇OST獻聲,溫柔的聲音搭配所飾演角色肖奈的俊朗帥氣,不僅演繹出爆表「男友力」,也為這張「最青春」歌單增添了暖心氣息。據悉,《微微一笑很傾城》由聽見時代傳媒出品,亦是為劇集粉絲們貢獻出的專屬原聲。
  • 緊扣「微時代」脈搏 開展思想政治工作
    羅林曄    隨著現代網絡技術的高速發展,微信、微博等「微媒體」無處不在,無「微」不精彩的「微時代」悄然來臨,傳播主體的平民化、傳播內容的碎片化、傳播方式的立體化等,給思想政治工作帶來了嚴峻的挑戰。
  • 《微微一笑很傾城》貝微微肖奈甜蜜愛戀
    這個電視劇主要講述的是學校的校花學霸貝微微,很喜歡玩一個遊戲,名字叫做《夢遊江湖》,在遊戲中憑藉著自己實力躋身到網遊的高手行列之中。在拒絕了「真水無香」的伴侶邀請之後,沒想到江湖的第一高手「一笑奈何」向自己求婚。兩個人在遊戲中心意相通,貝微微沒有想到的是一直以來遊戲中的伴侶竟然是學校的風雲人物肖奈師兄。