qiankun微服務,將多個不一樣技術棧的系統(React,Vue,Angular,jQuery)等聚合成一個系統,各個系統又能各自獨立部署運行,適用於大型團隊和大型前端項目。javascript
基於qiankun微服務的在線預覽:php
點擊預覽效果 css
獲取項目源碼前端
項目 | 技術棧 | 端口 | 訪問地址 |
---|---|---|---|
主項目(main-react) | Ant Design Pro | 5000 | http://qiankun.fancystore.cn |
子項目1(app1-react) | Ant Design Pro | 5001 | http://app1.fancystore.cn |
子項目2(app2-react) | Ant Design Pro | 5002 | http://app2.fancystore.cn |
子項目3(app3-vue) | Vue Element Template | 5003 | http://app3.fancystore.cn |
公共資源庫(qiankun-common) | TypeScript | https://github.com/czero1995/qiankun-common |
npm install @umi/qiankun --save or yarn add @umi/qiankun --save
// 在config/config.ts加入 qiankun: { master: { apps: [ { name:'app1', entry: process.env.NODE_ENV === 'production' ? '//app1.fancystore.cn' : '//localhost:5001', }, { name:'app2', entry: process.env.NODE_ENV === 'production' ? '//app2.fancystore.cn:' : '//localhost:5002', }, { name:'app3', entry: process.env.NODE_ENV === 'production' ? '//app3.fancystore.cn:' : '//localhost:5003', }, ], sandbox: true, //是否啓用沙箱 prefetch: true, //是否啓用prefetch特性 } }
// src/pages/document.ejs id=root-master
// src/layouts/MicroAppLayout import BasicLayout from '@ant-design/pro-layout'; import { KeepAlive, Provider } from 'react-keep-alive'; import { MicroAppWithMemoHistory } from 'umi'; import allRoutes from '../../config/routes'; function MicroAppLayout(props) { let targetMicro = '' const transRoutes = (routes, pathname) => { routes.map(item => { if (item.routes) { return transRoutes(item.routes, pathname) } if (item.path === pathname) { targetMicro = item.microName } }) return targetMicro } return <Provider> <KeepAlive name={props.location.pathname}> { targetMicro ? <MicroAppWithMemoHistory name={transRoutes(allRoutes[0].routes, props.location.pathname)} url={props.location.pathname} /> : <BasicLayout></BasicLayout> } </KeepAlive> </Provider> } export default MicroAppLayout;
// src/app.ts import LoadingComponent from '@/components/PageLoading'; import { dynamic } from 'umi'; const transRoutes = (routes) => { routes.forEach(item => { if(item.routes){ return transRoutes(item.routes) } if(item.microName){ item.component = dynamic({ loader: (a) => import(/* webpackChunkName: 'layouts__MicroAppLayout' */ '@/layouts/MicroAppLayout'), loading: LoadingComponent, }) } }) } export function patchRoutes({ routes }) { transRoutes(routes[0].routes) }
### 2. 子應用React(Ant Desin Pro)vue
#### 2.1 安裝qiankunjava
npm install @umi/qiankun --save or yarn add @umi/qiankun --save
#### 2.2 子項目註冊qiankun,在config/config.ts加入react
qiankun: { slave: {} }
#### 2.3 修改根節點 src/pages/document.ejswebpack
id=root-slave
#### 2.4 在src目錄下新建app.ts,導出相應的生命週期鉤子,子項目須要去區分好是qiankun環境仍是當前環境,若是是qiankun環境,使用空白的模板(src/layouts/BlankLayout),若是是當前環境,使用默認的模板(src/layouts/BasicLayout),這樣能內嵌到qiankun環境下運行也能獨立開發部署git
const isQiankun = window.__POWERED_BY_QIANKUN__ export const qiankun = { // 應用加載以前 async bootstrap(props) { console.log('app1 bootstrap', props); }, // 應用 render 以前觸發 async mount(props) { console.log('app1 mount', props); }, // 應用卸載以後觸發 async unmount(props) { console.log('app1 unmount', props); }, }; export async function patchRoutes({routes}) { if(isQiankun){ routes[0]['component'] = require('@/layouts/BlankLayout').default } }
output: { // 把子應用打包成 umd 庫格式(必須) library: `${name}-[name]`, libraryTarget: 'umd', jsonpFunction: `webpackJsonp_${name}`, }
headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Headers": "*" }
let install = null; function render(props) { install = new Vue({ router, store, render: h => h(App) }).$mount('#app3') } if (window.__POWERED_BY_QIANKUN__) { __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; } else { render(); } export async function bootstrap(props) { } export async function mount(props) { render(props); } export async function unmount(props) { install.$destroy(); install = null }
Ant Design Pro多標籤頁,點擊標籤頁的展現不一樣的應用頁面會致使被銷燬,內容數據被初始化和丟失,在src/layouts/MicroAppLayout下:github
引入 react-keep-alive 包 主應用須使用 MicroAppWithMemoHistory, 若使用 MicroApp 無效果。
qiankun環境下頁面跳轉404
在qiankun環境下,全部的路由改動都會涉會觸發qiankun的路由監聽,須要對環境作出判斷: export const qiankunJump = (url:string,name='頁面名稱',params = null) =>{ window.__POWERED_BY_QIANKUN__ ? history.pushState(params,name,url): umiHistory.push(url) } qiankunJump('/xxx')
qiankun external會報 Cannot read property 'createContext' of undefind
子項目是umi項目,只要配置了externals就會出錯,須要更改exteranls的寫法,去掉window externals: { 'react': 'window.React', 'react-dom': 'window.ReactDOM', } => externals: { react: 'React', 'react-dom': 'ReactDOM', }
若是主子應用使用的是相同的庫或者包(react,react-dom,moment等),能夠用externals的方式來引入,減小加載重複包致使資源浪費. qiankun將子項目的外鏈script標籤內容請求完後,會記錄到一個全局變量中,下次再次使用,他會先從這個全局變量中取。這樣就會實現內容的複用,只要保證兩個連接的Url一致便可 const fetchScript = scriptUrl => scriptCache[scriptUrl] || (scriptCache[scriptUrl] = fetch(scriptUrl).then(response => response.text())); 因此只要子項目配置了webpack的externals,這些公共依賴在同一臺服務器上,就能夠實現子項目的公共依賴的按需引入,一個項目使用了以後,另外一個項目再也不重複加載,能夠直接複用這個文件。
解決資源共用的問題,能夠提升項目的維護性,否則多個系統共用的組件或者工具維護起來很費力。 1. 經常使用的就是發佈成npm包,各個項目去安裝更新包。本地調試能夠用npm link。但反覆的更新包也是比較繁瑣。 2. 還有一種方式是用git庫引入, 在package.json的依賴中加入 "qiankun-common": "git+https://git@github.com:czero1995/qiankun-common.git" 使用 import { commonUtil } from 'qiankun-common'; util.qiankunJump('/xxx')
### 項目啓動
1. 進入main-react npm install npm run start 2. 進入app1-react npm install npm run start 3. 進入app2-react npm install npm run start 4. 進入app3-react npm install npm run dev
### 項目部署
子應用Nginx須要配上跨域請求頭:
add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Credentials true; add_header Cache-Control no-cache;
Nginx開啓gzip壓縮:
gzip on; gzip_min_length 200; gzip_buffers 4 16k; gzip_comp_level 9; gzip_vary on; gzip_disable "MSIE [1-6]\."; gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json;