微前端之案例——以antpro为主,react、vue、angular为子应用
【注】按照案例来,一定可以成功(每一步都写清楚了)
1. 主要技术:
qiankun、react(umi框架)+antd、vue+vant、angular+antd
qiankun官网
umi-qiankun 、 umi-qiankun案例
2. 搭建主应用:
参考:antd pro官网底部
yarn create umi main-app
> ant-design-pro
> 选择 pro v4
> 选择 typescript
> 选择 simple
> 选择 antd@4
yarn install 或者 npm install
主应用中增加.env文件,加入一行“PORT=8020”,指定端口
yarn start 或者 npm run start 启动,访问本地地址,如下图所示
[图片上传失败...(image-a1b2b7-1616382070563)]
2.1 安装qiankun
yarn add qiankun
2.2 安装包@umijs/plugin-qiankun
yarn add @umijs/plugin-qiankun -D
3. 配置React子应用与主应用的连接
3.1 创建子应用
mkdir sub-react-umi
cd sub-react-umi
yarn create @umijs/umi-app
yarn install 或者 npm install
子应用创建.env文件,增加一行"PORT=8021"
3.2 子应用中安装@umijs/plugin-qiankun
yarn add @umijs/plugin-qiankun -D
3.3 子应用package修改name
打开 package.json 文件,在第一行添加属性 name 及相应属性值"sub-react-umi"
3.4 主应用中注册子应用
参考:umi官方配置
{
...
qiankun: {
master: {
apps: [
{
name: 'sub-react-umi',
entry: '//localhost:8021',
},
],
},
},
}
3.5 主应用路由中装载子应用
在 主应用的config/config.ts 文件中,在 routes 属性下进行添加:
{
...,
{
name: 'list.table-list',
...,
},
{
name: 'sub-react-umi',
icon: 'smile',
path: '/sub-react-umi',
microApp: 'sub-react-umi',
}
}
3.6 子应用注册qiankun
参考:umi官方子应用配置
在.umirc.ts文件中添加如下代码(.umirc.ts与config/config.js作用一致,具体查看umi官方):
{
...,
qiankun: {
slave: {}
}
}
3.7 子应用导出生命周期
参考:umi官方配置
在子应用的 src/app.ts
里导出 qiankun
对象,如果没有app.ts自行创建。
export const qiankun = {
// 应用加载之前
async bootstrap(props: any) {
console.log('app1 bootstrap', props);
},
// 应用 render 之前触发
async mount(props: any) {
console.log('app1 mount', props);
},
// 应用卸载之后触发
async unmount(props: any) {
console.log('app1 unmount', props);
},
};
4. 配置Vue子应用与主应用的连接
4.1 创建子应用
vue create sub-vue-cli
>vue-cli-4
4.2 子应用在 src 目录新增 public-path.js
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
4.3 子应用入口文件 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')
}
// 独立运行时
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 子应用打包配置修改(vue.config.js
)
如果有vue.config.js则直接增加配置,如果没有请先新建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}`,
},
},
};
4.5 主应用中注册+装载子应用
打开主应用的config.ts文件,加入如下代码(类似3.4)
{
name: 'sub-vue-cli', // 唯一 id
entry: '//localhost:8022', // html entry
}
打开主应用的routes.ts文件,加入如下代码(类似3.5)
{
name: 'sub-vue-cli',
icon: 'smile',
path: '/sub-vue-cli',
microApp: 'sub-vue-cli',
}
至此,vue配置完成,启动起来可以直接访问了。
但是会遇到一个问题,问题描述:“Missing message: “menu.xxx“ for locale: “zh-CN“, using default message as fallback”。
解决办法:在主应用的config/defaultSettings.ts中,将proSettings中的menu做下修改,具体如下:
const proSettings: DefaultSettings = {
...,
menu:{
locale: false // 修改为false则没有了错误
}
}
5. 配置Angular子应用与主应用的连接
5.1 创建子应用
ng new sub-angular
>sub-angular
5.2 子应用在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 设置子应用的路由模式
在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;
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 项目只能安装 9.x 版本,angular 10 项目可以安装最新版
npm i @angular-builders/[email protected] -D
在根目录下增加custom-webpack.config.js
文件,内容如下:
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
文件,修改的具体内容如下
...> 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 主应用中注册+装载子应用
打开主应用的config.ts文件,加入如下代码(类似3.4)
{
name: 'sub-angular', // 唯一 id
entry: '//localhost:8023', // html entry
}
打开主应用的routes.ts文件,加入如下代码(类似3.5)
{
name: 'sub-angular',
icon: 'smile',
path: '/sub-angular',
microApp: 'sub-angular',
}
5.7 解决zone.js问题
angular默认引入zone文件,当它为子应用之后,引入路径放到父应用中
父应用引入zone.js,一定在引入import qiankun之前,在父应用src目录下新建app.js文件,并且在父应用中npm install --save-dev zone
文件中写入import 'zone.js';
在子应用的src/polyfills.ts
里面的引入 zone.js
代码删掉
在微应用的 src/index.html
里面的 标签加上下面内容,微应用独立访问时使用
至此,项目可以启动并且访问
5.8 打包问题解决
修改tsconfig.json文件
// 将原有的targe:es2015删除,写入如下代码
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
5.9 解决各个应用名称相同问题
子应用的src/index.html页面中将app-root标签增加 id="angular9",如下:
同时修改src/app/app.components.ts中selector中的内容,如下:
selector: '#angular9 app-root',
微服务应用到此,可以初步展开了...