微前端之案例——以antpro為主烁登,react怯屉、vue、angular為子應(yīng)用
【注】按照案例來(lái)饵沧,一定可以成功(每一步都寫清楚了)
1. 主要技術(shù):
qiankun锨络、react(umi框架)+antd、vue+vant狼牺、angular+antd
2. 搭建主應(yīng)用:
參考:antd pro官網(wǎng)底部
yarn create umi main-app
> ant-design-pro
> 選擇 pro v4
> 選擇 typescript
> 選擇 simple
> 選擇 antd@4
yarn install 或者 npm install
主應(yīng)用中增加.env文件,加入一行“PORT=8020”锁右,指定端口
yarn start 或者 npm run start 啟動(dòng)失受,訪問(wèn)本地地址,如下圖所示
[圖片上傳失敗...(image-a1b2b7-1616382070563)]
2.1 安裝qiankun
yarn add qiankun
2.2 安裝包@umijs/plugin-qiankun
yarn add @umijs/plugin-qiankun -D
3. 配置React子應(yīng)用與主應(yīng)用的連接
3.1 創(chuàng)建子應(yīng)用
mkdir sub-react-umi
cd sub-react-umi
yarn create @umijs/umi-app
yarn install 或者 npm install
子應(yīng)用創(chuàng)建.env文件咏瑟,增加一行"PORT=8021"
3.2 子應(yīng)用中安裝@umijs/plugin-qiankun
yarn add @umijs/plugin-qiankun -D
3.3 子應(yīng)用package修改name
打開 package.json 文件拂到,在第一行添加屬性 name 及相應(yīng)屬性值"sub-react-umi"
3.4 主應(yīng)用中注冊(cè)子應(yīng)用
參考:umi官方配置
{
...
qiankun: {
master: {
apps: [
{
name: 'sub-react-umi',
entry: '//localhost:8021',
},
],
},
},
}
3.5 主應(yīng)用路由中裝載子應(yīng)用
在 主應(yīng)用的config/config.ts 文件中,在 routes 屬性下進(jìn)行添加:
{
...,
{
name: 'list.table-list',
...,
},
{
name: 'sub-react-umi',
icon: 'smile',
path: '/sub-react-umi',
microApp: 'sub-react-umi',
}
}
3.6 子應(yīng)用注冊(cè)qiankun
在.umirc.ts文件中添加如下代碼(.umirc.ts與config/config.js作用一致码泞,具體查看umi官方):
{
...,
qiankun: {
slave: {}
}
}
3.7 子應(yīng)用導(dǎo)出生命周期
參考:umi官方配置
在子應(yīng)用的 src/app.ts
里導(dǎo)出 qiankun
對(duì)象兄旬,如果沒(méi)有app.ts自行創(chuàng)建。
export const qiankun = {
// 應(yīng)用加載之前
async bootstrap(props: any) {
console.log('app1 bootstrap', props);
},
// 應(yīng)用 render 之前觸發(fā)
async mount(props: any) {
console.log('app1 mount', props);
},
// 應(yīng)用卸載之后觸發(fā)
async unmount(props: any) {
console.log('app1 unmount', props);
},
};
4. 配置Vue子應(yīng)用與主應(yīng)用的連接
4.1 創(chuàng)建子應(yīng)用
vue create sub-vue-cli
>vue-cli-4
4.2 子應(yīng)用在 src 目錄新增 public-path.js
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
4.3 子應(yīng)用入口文件 main.js 修改余寥,為了避免根 id #app 與其他的 DOM 沖突领铐,需要限制查找范圍
在main.js中將原有代碼替換為如下代碼:
import './public-path'
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import routes from './router'
import store from './store'
Vue.config.productionTip = false
let router = null
let instance = null
function render (props = {}) {
const { container } = props
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/sub-vue-cli/' : '/',
mode: 'history',
routes
})
instance = new Vue({
router,
store,
render: h => h(App)
}).$mount(container ? container.querySelector('#app') : '#app')
}
// 獨(dú)立運(yùn)行時(shí)
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)
render(props)
}
export async function unmount () {
instance.$destroy()
instance.$el.innerHTML = ''
instance = null
router = null
}
4.4 子應(yīng)用打包配置修改(vue.config.js
)
如果有vue.config.js則直接增加配置,如果沒(méi)有請(qǐng)先新建vue.config.js文件
const { name } = require('./package');
module.exports = {
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
},
configureWebpack: {
output: {
library: `${name}-[name]`,
libraryTarget: 'umd',// 把微應(yīng)用打包成 umd 庫(kù)格式
jsonpFunction: `webpackJsonp_${name}`,
},
},
};
4.5 主應(yīng)用中注冊(cè)+裝載子應(yīng)用
打開主應(yīng)用的config.ts文件宋舷,加入如下代碼(類似3.4)
{
name: 'sub-vue-cli', // 唯一 id
entry: '//localhost:8022', // html entry
}
打開主應(yīng)用的routes.ts文件绪撵,加入如下代碼(類似3.5)
{
name: 'sub-vue-cli',
icon: 'smile',
path: '/sub-vue-cli',
microApp: 'sub-vue-cli',
}
至此,vue配置完成祝蝠,啟動(dòng)起來(lái)可以直接訪問(wèn)了音诈。
但是會(huì)遇到一個(gè)問(wèn)題幻碱,問(wèn)題描述:“Missing message: “menu.xxx“ for locale: “zh-CN“, using default message as fallback”。
解決辦法:在主應(yīng)用的config/defaultSettings.ts中细溅,將proSettings中的menu做下修改褥傍,具體如下:
const proSettings: DefaultSettings = {
...,
menu:{
locale: false // 修改為false則沒(méi)有了錯(cuò)誤
}
}
5. 配置Angular子應(yīng)用與主應(yīng)用的連接
5.1 創(chuàng)建子應(yīng)用
ng new sub-angular
>sub-angular
5.2 子應(yīng)用在src目錄新增public-path.js
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
5.3 設(shè)置子應(yīng)用的路由模式
在src/app/app-routing.module.ts
文件下,做如下更改
// 引入下列代碼
import { APP_BASE_HREF } from '@angular/common';
@NgModule({
...,
// @ts-ignore
providers: [{ provide: APP_BASE_HREF, useValue: window.__POWERED_BY_QIANKUN__ ? '/sub-angular' : '/' }]
})
5.4 修改入口文件src/main.js
修改后如下所示:
import './public-path';
import { enableProdMode, NgModuleRef } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
if (environment.production) {
enableProdMode();
}
let app: void | NgModuleRef<AppModule>;
async function render() {
app = await platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
}
if (!(window as any).__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap (props: Object) {
console.log(props);
}
export async function mount (props: Object) {
render();
}
export async function unmount (props: Object) {
console.log(props);
// @ts-ignore
app.destroy();
}
5.5 修改webpack
打包配置
首先:安裝 @angular-builders/custom-webpack
插件喇聊,注意:angular 9 項(xiàng)目只能安裝 9.x 版本恍风,angular 10 項(xiàng)目可以安裝最新版
npm i @angular-builders/custom-webpack@9.2.0 -D
在根目錄下增加custom-webpack.config.js
文件,內(nèi)容如下:
const appName = require('./package.json').name;
module.exports = {
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
},
output: {
library: `${appName}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${appName}`,
},
};
修改augular.json
文件誓篱,修改的具體內(nèi)容如下
...> architect > build > builder目錄下修改為:
"builder": "@angular-builders/custom-webpack:browser",
緊跟著的options增加如下配置
"options": {
...,
"customWebpackConfig": {
"path": "./custom-webpack.config.js"
}
}
...> architect > serve > builder目錄下修改為:
"builder": "@angular-builders/custom-webpack:dev-server",
5.6 主應(yīng)用中注冊(cè)+裝載子應(yīng)用
打開主應(yīng)用的config.ts文件朋贬,加入如下代碼(類似3.4)
{
name: 'sub-angular', // 唯一 id
entry: '//localhost:8023', // html entry
}
打開主應(yīng)用的routes.ts文件,加入如下代碼(類似3.5)
{
name: 'sub-angular',
icon: 'smile',
path: '/sub-angular',
microApp: 'sub-angular',
}
5.7 解決zone.js問(wèn)題
angular默認(rèn)引入zone文件燕鸽,當(dāng)它為子應(yīng)用之后兄世,引入路徑放到父應(yīng)用中
父應(yīng)用引入zone.js,一定在引入import qiankun之前啊研,在父應(yīng)用src目錄下新建app.js文件御滩,并且在父應(yīng)用中npm install --save-dev zone
文件中寫入import 'zone.js';
在子應(yīng)用的src/polyfills.ts
里面的引入 zone.js
代碼刪掉
在微應(yīng)用的 src/index.html
里面的 <head>
標(biāo)簽加上下面內(nèi)容,微應(yīng)用獨(dú)立訪問(wèn)時(shí)使用
<!-- 也可以使用其他的CDN/本地的包 -->
<script src="https://unpkg.com/zone.js" ignore></script>
至此党远,項(xiàng)目可以啟動(dòng)并且訪問(wèn)
5.8 打包問(wèn)題解決
修改tsconfig.json文件
// 將原有的targe:es2015刪除削解,寫入如下代碼
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
5.9 解決各個(gè)應(yīng)用名稱相同問(wèn)題
子應(yīng)用的src/index.html頁(yè)面中將app-root標(biāo)簽增加 id="angular9",如下:
<app-root id="angular9"></app-root>
同時(shí)修改src/app/app.components.ts中selector中的內(nèi)容沟娱,如下:
selector: '#angular9 app-root',
微服務(wù)應(yīng)用到此氛驮,可以初步展開了...