第一步:主应用搭建
- 脚手架搭建antd pro 项目
- 安装@umijs/plugin-qiankun
yarn add @umijs/plugin-qiankun -D 配置
qiankun开启插件构建期间配置子应用
// config.ts//// qiankun 入口配置const QIANKUN_ENTRY = {app1: {develop: '//localhost:3400',test: '//test.app1.com/',production: '//app1.com/',},app2: {develop: '//localhost:3401',test: '//test.app2.com/app2/',production: '//app2.zhifuzi.com/app2/',},};export default defineConfig({...config,qiankun: {master: {// 注册子应用信息apps: [{name: 'app1', // 唯一 id 与子应用的package.json 中的name相同entry: QIANKUN_ENTRY.zhifuzi[`${process.env.APP_ENV}`],// html entry 根据需求配置,这个项目我是将子应用独立仓库,独立上传服务器// 所以再配置的时候根据当前环境配置不同的打包地址选择入口},{name: 'app2', // 唯一 identry: QIANKUN_ENTRY.zhifuzi[`${process.env.APP_ENV}`], // html entry},],},},}
b. 装载子应用,绑定路由 ```javascript // route.ts
export default=[ …route, { path: ‘/app1’, routes: [ { // 配置微应用 app1 关联的路由 path: ‘/app1’, name: ‘app1’, microApp: ‘app1’, }, ], }, { path: ‘/app2’, routes: [ { // 配置微应用 app2 关联的路由 path: ‘/app2’, name: ‘app2’, microApp: ‘app2’, }, ], }, ]
到这一步 主应用的基本搭建已经完工,接下来要做的就是旧的子应用的qiankun注册<a name="AyDM5"></a>#### 第二步:子应用旧站qiankun注册1. 子应用旧站安装qiankun `yarn add qiankun # 或者 npm i qiankun -S`2. 导出相应的生命周期钩子```javascriptfunction render(props) {const { container } = props;ReactDOM.render(<AppContainer><App /></AppContainer>,container? container.querySelector("#roots"): document.querySelector("#roots"));}function storeTest(props) {props.onGlobalStateChange((value, prev) =>console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),true);props.setGlobalState({ignore: props.name,user: {name: props.name,},});}if (!window.__POWERED_BY_QIANKUN__) {render({});}export async function bootstrap() {console.log("[react16] react app bootstraped");}export async function mount(props) {console.log("[react16] props from main framework", props);storeTest(props);render(props);}export async function unmount(props) {const { container } = props;ReactDOM.unmountComponentAtNode(container? container.querySelector("#roots"): document.querySelector("#roots"));}
配置微应用的打包工具 ```javascript export default config={ …config, output: {
// 把子应用打包成 umd 库格式(必须) library:
${name}-[name], publicPath: “/“, libraryTarget: “umd”, jsonpFunction:webpackJsonp_${name}, },devServer:{ port: 3400, //配置端口为3400 headers: { “Access-Control-Allow-Origin”: “*”, // 允许跨域 }, }
}
4. 根目录新增publice-path.js```javascript// publice-path.jsif (window.__POWERED_BY_QIANKUN__) {// eslint-disable-next-line no-undef__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;}
- src/index.js 引入public-path.js
import "../public-path" 为配合就应用原始的路由跳转,需要增加根据入口不同的前缀
const base = window.__POWERED_BY_QIANKUN__ ? "/app1" : ""; // app1适配乾坤<Route path={`${base}/auth/login`} component={Login} />// 在qiankun的环境下,默认增加/app1 ,子应用的所有路由跳转都需要增加前缀
到这一步,主应用已经可以嵌入子应用,并且可以点击切换路由
第三步:子应用新站@umijs/plugin-qiankun注册
- 脚手架搭建antd pro 项目
- 安装@umijs/plugin-qiankun
yarn add @umijs/plugin-qiankun -D - 插件注册config.js ```javascript export default { qiankun: { slave: {}, }, };
4. 增加环境变量配置 根目录新增.env文件 `PORT=3401`基本上到这一步为止已经能在主应用访问两个子应用了<a name="JxURr"></a>#### 第四步:子应用新站部署服务器项目部署参考之前的文章 [服务端项目服务器配置流程(GitLab+Jenkins)](https://juejin.cn/post/6988058244396777486)<br />这里主要修改的是ngnix的配置,其余配置参考上述文章即可```shellserver {listen 80; # 监听本机所有 ip 上的 80 端口server_name test.app2.com; # 域名:www.example.com 这里 "_" 代表获取匹配所有root /storage/nginx/www/app2; # 站点根目录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';index index.htm index.html index.php;try_files $uri $uri/ /index.html;}}
第五步:主应用部署服务器(nginx部署)
这里也只放出来nginx的配置路径
server {listen 80;server_name test.base.com;root /storage/nginx/www/base;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';index index.htm index.html index.php;try_files $uri $uri/ /index.html;}location /app1/ {proxy_pass http://test.app1.com/;proxy_set_header Host $host:$server_port;proxy_redirect off;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_connect_timeout 3600;proxy_read_timeout 3600;proxy_send_timeout 3600;}location /app2/ {proxy_pass http://test.app2.com/;proxy_set_header Host $host:$server_port;proxy_redirect off;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_connect_timeout 3600;proxy_read_timeout 3600;proxy_send_timeout 3600;}}
到这一步所有配置已经完成了,线上测试站主应用可以访问两个子应用了,但是整个过程没有那么顺利,遇到过很多坑,下面对遇到的坑做一个总结
微前端落坑记录
- 刚开始部署在测试服务器上时,配置完成之后发现线上的主应用在子应用的入口是本地的localhost:3400,导致本地的应用关闭之后,测试站主应用就不能访问了
解决方法:根据打包命令配置当前的入口,获取当前的 APP_ENV 环境变量 配置不同的子应用入口 ```javascript // package.json { “build:test”: “cross-env APP_ENV=test umi build”, “build:prod”: “cross-env APP_ENV=production umi build”, } // config.ts
// qiankun 入口配置 const QIANKUN_ENTRY = { app1: { develop: ‘//localhost:3400’, test: ‘//test.app1.com/‘, production: ‘//app1.com/‘, }, app2: { develop: ‘//localhost:3401’, test: ‘//test.app2.com/app2/‘, production: ‘//app2.zhifuzi.com/app2/‘, }, };
// config 配置
qiankun: {
master: {
// 注册子应用信息
apps: [
{
name: ‘app1’, // 唯一 id 与子应用的package.json 中的name相同
entry: QIANKUN_ENTRY.zhifuzi[${process.env.APP_ENV}],
},{name: 'app2', // 唯一 identry: QIANKUN_ENTRY.zhifuzi[`${process.env.APP_ENV}`], // html entry},],},
},
2. 当设置动态的publicPath时,src文件外的文件,比如public里的一些json文件或者图片的地址就匹配不上publicPath- 解决办法:基本上这个问题是因为主应用的入口错误,导致默认publicPath为主应用的路径,所以要将入口配置正确```javascript• const QIANKUN_ENTRY = {app1: {develop: '//localhost:3400',test: '//test.app1.com/',production: '//app1.com/',},app2: {develop: '//localhost:3401',test: '//test.app2.com/app2/', // 重点:/app2/production: '//app2.zhifuzi.com/app2/',},};
