【qiankun】微前端項目搭建與通信

官網(wǎng)地址:https://qiankun.umijs.org/

微前端是一種多個團隊通過獨立發(fā)布功能的方式來共同構建現(xiàn)代化 web 應用的技術手段及方法策略

·獨立開發(fā)精算、獨立部署

主應用

1. 安裝 qiankun

$ yarnadd qiankun # 或者 npm i qiankun -S

2. 在主應用中注冊子應用(主應用的main.js)

import{ registerMicroApps, start }from'qiankun';

registerMicroApps([

{

name:'react app',// app name registered

entry:'//localhost:7100', //子應用的地址(不包含標識和路由)

container:'#vue’,// 子應用掛載的div

activeRule:'/yourActiveRule', // 子應用的標識仰美,路由中會詳細說明

},

]);

// 啟動 qiankun

start();

手動加載本項目暫不需要。當子應用信息注冊完之后叔扼,一旦瀏覽器的 url 發(fā)生變化官研,便會自動觸發(fā) qiankun 的匹配邏輯藻治,所有 activeRule 規(guī)則匹配上的子應用就會被插入到指定的 container 中载矿,同時依次調用子應用暴露出的生命周期鉤子限书。

如果子應用不是直接跟路由關聯(lián)的時候虫蝶,你也可以選擇手動加載子應用的方式:

import{ loadMicroApp }from'qiankun';

loadMicroApp(

{

name:'app',

entry:'//localhost:7100',

container:'#yourContainer',

}

);

子應用

子應用不需要額外安裝任何其他依賴即可接入 qiankun 主應用。

1倦西、入口文件 main.js修改能真,為了避免根 id #app與其他的 DOM 沖突,需要限制查找范圍,在container范圍中查找

import'./public-path';

import Vue from'vue';

import VueRouter from'vue-router';

import App from'./App.vue';

import routes from'./router';

import store from'./store';

Vue.config.productionTip =false;

let router =null;

let instance =null;

functionrender(props ={}){

//為了避免根 id #app 與其他的 DOM 沖突扰柠,需要限制查找范圍

const{ container }= props;

router =newVueRouter({

//如果是子應用就設置標識

base:window.__POWERED_BY_QIANKUN__ ?'/app-vue/':'/',

mode:'history',

routes,

});

instance =newVue({

router,

store,

render: h =>h(App),

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

}

// 是否獨立運行

if(window.__POWERED_BY_QIANKUN__){

__webpack_public_path__ =window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;

}else{

render();

}

// 導出相應的生命周期鉤子

exportasyncfunctionbootstrap(){

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

}

exportasyncfunctionmount(props){

console.log('[vue] props from main framework', props);

render(props);

}

exportasyncfunctionunmount(){

instance.$destroy();

instance.$el.innerHTML ='';

instance =null;

router =null;

}

2.打包配置修改(vue.config.js):

設置跨域和打包格式

const{ name }=require('./package');// 不重要粉铐。自己起也可以

module.exports ={

devServer:{

headers:{

'Access-Control-Allow-Origin':'*',// 設置跨域

},

},

configureWebpack:{

output:{

library:`${name}-[name]`,// 配置導出庫的名稱

libraryTarget:'umd',// 把子應用打包成 umd 庫格式

jsonpFunction:`webpackJsonp_${name}`,//不是必須的

},

},

};

3.子應用生命周期鉤子介紹

子應用需要在自己的入口 js (通常就是你配置的 webpack 的 entry js) 導出 bootstrap、mount卤档、unmount三個生命周期鉤子蝙泼,以供主應用在適當?shù)臅r機調用。

/**

  • bootstrap 只會在子應用初始化的時候調用一次劝枣,下次子應用重新進入時會直接調用 mount 鉤子汤踏,不會再重復觸發(fā) bootstrap。

  • 通常我們可以在這里做一些全局變量的初始化舔腾,比如不會在 unmount 階段被銷毀的應用級別的緩存等溪胶。

*/

exportasyncfunctionbootstrap(){

console.log('react app bootstraped');

}

/**

  • 應用每次進入都會調用 mount 方法,通常我們在這里觸發(fā)應用的渲染方法

*/

exportasyncfunctionmount(props){

ReactDOM.render(<App />, props.container ? props.container.querySelector('#root'): document.getElementById('root'));

}

/**

  • 應用每次 切出/卸載 會調用的方法稳诚,通常在這里我們會卸載子應用的應用實例

*/

exportasyncfunctionunmount(props){

ReactDOM.unmountComponentAtNode(props.container ? props.container.querySelector('#root'): document.getElementById('root'));

}

/**

  • 可選生命周期鉤子哗脖,僅使用 loadMicroApp 方式(手動掛載)加載子應用時生效

*/

exportasyncfunctionupdate(props){

console.log('update props', props);

}

父子通信(父子應用store分離的方案實現(xiàn))

使用vuex的原因是為了獲取主應用的實時數(shù)據(jù),也為了實現(xiàn)子應用主應用的相互通信扳还。任何項目中vuex都有base.js才避,用來存儲公共信息。比如token氨距、用戶名等工扎。(現(xiàn)項目token等存儲在localstorage中)子應用單獨啟動時用自己的vuex中的base.js來存儲信息,base.js只能主應用進行修改衔蹲,同步到子應用肢娘。(不考慮子應用單獨運行可以不在子應用維護base.js)

step1:主應用向子應用傳遞store實例。

image.png

step2:子應用使用主應用共享的store實例并設置只屬于子應用的vuex

針對第一種情況舆驶,就是在入口文件中引入vuex橱健,并使用該插件,進而在創(chuàng)建vue實例的時候沙廉,傳入主應用共享的store拘荡。

Vuex正常使用的時候,所有的狀態(tài)值都是響應式的撬陵,可以直接用于Vue頁面之中珊皿,但是這里是非響應式的网缝,導致這個的原因其實十分簡單。這里的store實例是由主應用傳遞過來的蟋定,store中的狀態(tài)對于主應用的vue實例而言是親兒子粉臊,是響應式的,在子應用中驶兜,雖然可以使用共享store實例中的commit方法扼仲,但是對于子應用的實Vuex例而言,不是親兒子抄淑,是非響應式的屠凶,這樣分析之后,解決方案就十分明確:

在子應用中將共享的****store****實例進行響應式設置肆资,這是****Vue****現(xiàn)有的****API****方法****Vue.observable(store)

image.png

子應用的文件夾格式和使用方式

image.png
image.png

step4:子應用之間通信

子應用之間的通信可以通過父應用的vuex來傳遞矗愧。

登錄

1.1把子應用的登錄頁面移到主應用

1.2保留子應用的登錄,保證可以單獨啟動(目前登錄信息存儲在localstorage中)

路由

1.3因為qiankun的特性主應用調用子應用是路由前要加子項目標識

列:子應用中路由為/index郑原,子應用標識為/ child01贱枣,主應用的該路由就為/child01 /index

主應用和子應用設置標識必須相同

后臺返回的權限路由都要加子應用標識

遇到的問題

1、應用的部署颤专,需要通過nginx做反向代理,把指向子應用的訪問路徑轉發(fā)到子應用的服務入口

2钠乏、子應用套孫子應用未考慮栖秕,一個頁面多個子應用未考慮;

應用部署nginx

子應用中需配置晓避,跨域

location / {    

   add_header Access-Control-Allow-Origin *;  

   add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';

   add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested- With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

   if ($request_method = 'OPTIONS') {

       return 204;

   }

}

讓微應用文件更新之后訪問新的文件

問題描述:發(fā)版vue項目后簇捍,總是要強制刷瀏覽器才能生效

vue-cli里的默認配置,css和js的名字都加了哈希值俏拱,所以新版本css暑塑、js和就舊版本的名字是不同的,不會有緩存問題锅必。

但是把打包好的index.html放到服務器里去的時候事格,index.html在服務器端可能是有緩存的,這需要在服務器配置不讓緩存index.html

解決方法如下:

前端在index.html中添加:

   <meta http-equiv="Expires" content="0">

<meta http-equiv="Pragma" content="no-cache">

<meta http-equiv="Cache-control" content="no-cache">

<meta http-equiv="Cache" content="no-cache">

nginx 配置如下:

location = /index.html {

   add_header Cache-Control "no-cache, no-store";

}

開發(fā)規(guī)范

1.所有的資源(圖片/音視頻等)都應該放到src目錄搞隐,不要放在public或者static

資源放 src 目錄驹愚,會經(jīng)過 webpack 處理,能統(tǒng)一注入 publicPath劣纲。否則在主項目中會404逢捺。

2.請給 axios 實例添加攔截器,而不是 axios 對象

// 正確做法:給 axios 實例添加攔截器

const instance = axios.create();

instance.interceptors.request.use(function () {/.../});

// 錯誤用法:直接給 axios 對象添加攔截器

axios.interceptors.request.use(function () {/.../});

3.避免 css 污染

組件內樣式的css-scoped是必須的癞季。

對于一些插入到body的彈窗劫瞳,無法使用scoped倘潜,請不要直接使用原class修改樣式,請?zhí)砑幼约旱腸lass志于,來修改樣式涮因。盡量不將元素插入body

.el-dialog{

/* 不推薦使用組件原有的class */

}

.my-el-dialog{

/* 推薦使用自定義組件的class */

}

4.謹慎使用 position:fixed

在父項目中,這個定位未必準確恨憎,應盡量避免使用蕊退,確有相對于瀏覽器窗口定位需求,可以用position: sticky憔恳,但是會有兼容性問題(IE不支持)瓤荔。如果定位使用的是bottom和right,則問題不大钥组。

5.給 body 输硝、 document 等綁定的事件,請在 unmount 周期清除

js 沙箱只劫持了 window.addEventListener程梦。使用

document.body.addEventListener 或者 document.body.onClick 添加的事件并不會被沙箱移除点把,會對其他的頁面產(chǎn)生影響,請在 unmount 周期清除

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末屿附,一起剝皮案震驚了整個濱河市郎逃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挺份,老刑警劉巖褒翰,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異匀泊,居然都是意外死亡优训,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門各聘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來揣非,“玉大人,你說我怎么就攤上這事躲因≡缇矗” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵大脉,是天一觀的道長搁嗓。 經(jīng)常有香客問我,道長箱靴,這世上最難降的妖魔是什么腺逛? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮衡怀,結果婚禮上棍矛,老公的妹妹穿的比我還像新娘安疗。我一直安慰自己,他們只是感情好够委,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布荐类。 她就那樣靜靜地躺著,像睡著了一般茁帽。 火紅的嫁衣襯著肌膚如雪玉罐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天潘拨,我揣著相機與錄音吊输,去河邊找鬼。 笑死铁追,一個胖子當著我的面吹牛季蚂,可吹牛的內容都是我干的。 我是一名探鬼主播琅束,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼扭屁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了涩禀?” 一聲冷哼從身側響起料滥,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎艾船,沒想到半個月后葵腹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡丽声,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了觉义。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雁社。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖晒骇,靈堂內的尸體忽然破棺而出霉撵,到底是詐尸還是另有隱情,我是刑警寧澤洪囤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布徒坡,位于F島的核電站,受9級特大地震影響瘤缩,放射性物質發(fā)生泄漏喇完。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一剥啤、第九天 我趴在偏房一處隱蔽的房頂上張望锦溪。 院中可真熱鬧不脯,春花似錦、人聲如沸刻诊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽则涯。三九已至复局,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間粟判,已是汗流浹背亿昏。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留浮入,地道東北人龙优。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像事秀,于是被迫代替她去往敵國和親彤断。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內容