第一步:主应用搭建

  1. 脚手架搭建antd pro 项目
  2. 安装@umijs/plugin-qiankun yarn add @umijs/plugin-qiankun -D
  3. 配置 qiankun 开启

    1. 插件构建期间配置子应用

      1. // config.ts
      2. //// qiankun 入口配置
      3. const QIANKUN_ENTRY = {
      4. app1: {
      5. develop: '//localhost:3400',
      6. test: '//test.app1.com/',
      7. production: '//app1.com/',
      8. },
      9. app2: {
      10. develop: '//localhost:3401',
      11. test: '//test.app2.com/app2/',
      12. production: '//app2.zhifuzi.com/app2/',
      13. },
      14. };
      15. export default defineConfig({
      16. ...config,
      17. qiankun: {
      18. master: {
      19. // 注册子应用信息
      20. apps: [
      21. {
      22. name: 'app1', // 唯一 id 与子应用的package.json 中的name相同
      23. entry: QIANKUN_ENTRY.zhifuzi[`${process.env.APP_ENV}`],
      24. // html entry 根据需求配置,这个项目我是将子应用独立仓库,独立上传服务器
      25. // 所以再配置的时候根据当前环境配置不同的打包地址选择入口
      26. },
      27. {
      28. name: 'app2', // 唯一 id
      29. entry: QIANKUN_ENTRY.zhifuzi[`${process.env.APP_ENV}`], // html entry
      30. },
      31. ],
      32. },
      33. },
      34. }

      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’, }, ], }, ]

  1. 到这一步 主应用的基本搭建已经完工,接下来要做的就是旧的子应用的qiankun注册
  2. <a name="AyDM5"></a>
  3. #### 第二步:子应用旧站qiankun注册
  4. 1. 子应用旧站安装qiankun `yarn add qiankun # 或者 npm i qiankun -S`
  5. 2. 导出相应的生命周期钩子
  6. ```javascript
  7. function render(props) {
  8. const { container } = props;
  9. ReactDOM.render(
  10. <AppContainer>
  11. <App />
  12. </AppContainer>,
  13. container
  14. ? container.querySelector("#roots")
  15. : document.querySelector("#roots")
  16. );
  17. }
  18. function storeTest(props) {
  19. props.onGlobalStateChange(
  20. (value, prev) =>
  21. console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),
  22. true
  23. );
  24. props.setGlobalState({
  25. ignore: props.name,
  26. user: {
  27. name: props.name,
  28. },
  29. });
  30. }
  31. if (!window.__POWERED_BY_QIANKUN__) {
  32. render({});
  33. }
  34. export async function bootstrap() {
  35. console.log("[react16] react app bootstraped");
  36. }
  37. export async function mount(props) {
  38. console.log("[react16] props from main framework", props);
  39. storeTest(props);
  40. render(props);
  41. }
  42. export async function unmount(props) {
  43. const { container } = props;
  44. ReactDOM.unmountComponentAtNode(
  45. container
  46. ? container.querySelector("#roots")
  47. : document.querySelector("#roots")
  48. );
  49. }
  1. 配置微应用的打包工具 ```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”: “*”, // 允许跨域 }, }

}

  1. 4. 根目录新增publice-path.js
  2. ```javascript
  3. // publice-path.js
  4. if (window.__POWERED_BY_QIANKUN__) {
  5. // eslint-disable-next-line no-undef
  6. __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
  7. }
  1. src/index.js 引入public-path.js import "../public-path"
  2. 为配合就应用原始的路由跳转,需要增加根据入口不同的前缀

    1. const base = window.__POWERED_BY_QIANKUN__ ? "/app1" : ""; // app1适配乾坤
    2. <Route path={`${base}/auth/login`} component={Login} />
    3. // 在qiankun的环境下,默认增加/app1 ,子应用的所有路由跳转都需要增加前缀

到这一步,主应用已经可以嵌入子应用,并且可以点击切换路由

第三步:子应用新站@umijs/plugin-qiankun注册

  1. 脚手架搭建antd pro 项目
  2. 安装@umijs/plugin-qiankun yarn add @umijs/plugin-qiankun -D
  3. 插件注册config.js ```javascript export default { qiankun: { slave: {}, }, };
  1. 4. 增加环境变量配置 根目录新增.env文件 `PORT=3401`
  2. 基本上到这一步为止已经能在主应用访问两个子应用了
  3. <a name="JxURr"></a>
  4. #### 第四步:子应用新站部署服务器
  5. 项目部署参考之前的文章 [服务端项目服务器配置流程(GitLab+Jenkins)](https://juejin.cn/post/6988058244396777486)<br />这里主要修改的是ngnix的配置,其余配置参考上述文章即可
  6. ```shell
  7. server {
  8. listen 80; # 监听本机所有 ip 上的 80 端口
  9. server_name test.app2.com; # 域名:www.example.com 这里 "_" 代表获取匹配所有
  10. root /storage/nginx/www/app2; # 站点根目录
  11. location / {
  12. add_header Access-Control-Allow-Origin *; // 配置允许跨域
  13. add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
  14. 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';
  15. index index.htm index.html index.php;
  16. try_files $uri $uri/ /index.html;
  17. }
  18. }

第五步:主应用部署服务器(nginx部署)

这里也只放出来nginx的配置路径

  1. server {
  2. listen 80;
  3. server_name test.base.com;
  4. root /storage/nginx/www/base;
  5. location / {
  6. add_header Access-Control-Allow-Origin *;
  7. add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
  8. 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';
  9. index index.htm index.html index.php;
  10. try_files $uri $uri/ /index.html;
  11. }
  12. location /app1/ {
  13. proxy_pass http://test.app1.com/;
  14. proxy_set_header Host $host:$server_port;
  15. proxy_redirect off;
  16. proxy_set_header X-Real-IP $remote_addr;
  17. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  18. proxy_connect_timeout 3600;
  19. proxy_read_timeout 3600;
  20. proxy_send_timeout 3600;
  21. }
  22. location /app2/ {
  23. proxy_pass http://test.app2.com/;
  24. proxy_set_header Host $host:$server_port;
  25. proxy_redirect off;
  26. proxy_set_header X-Real-IP $remote_addr;
  27. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  28. proxy_connect_timeout 3600;
  29. proxy_read_timeout 3600;
  30. proxy_send_timeout 3600;
  31. }
  32. }

到这一步所有配置已经完成了,线上测试站主应用可以访问两个子应用了,但是整个过程没有那么顺利,遇到过很多坑,下面对遇到的坑做一个总结

微前端落坑记录

  1. 刚开始部署在测试服务器上时,配置完成之后发现线上的主应用在子应用的入口是本地的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}],

  1. },
  2. {
  3. name: 'app2', // 唯一 id
  4. entry: QIANKUN_ENTRY.zhifuzi[`${process.env.APP_ENV}`], // html entry
  5. },
  6. ],
  7. },

},

  1. 2. 当设置动态的publicPath时,src文件外的文件,比如public里的一些json文件或者图片的地址就匹配不上publicPath![image.png](https://cdn.nlark.com/yuque/0/2021/png/22188112/1630574811756-ef5f686b-130d-44a4-a0b7-a814c37589e1.png#crop=0&crop=0&crop=1&crop=1&height=49&id=cjg4a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=49&originWidth=465&originalType=binary&ratio=1&rotation=0&showTitle=false&size=3272&status=done&style=none&title=&width=465)
  2. - 解决办法:基本上这个问题是因为主应用的入口错误,导致默认publicPath为主应用的路径,所以要将入口配置正确
  3. ```javascript
  4. • const QIANKUN_ENTRY = {
  5. app1: {
  6. develop: '//localhost:3400',
  7. test: '//test.app1.com/',
  8. production: '//app1.com/',
  9. },
  10. app2: {
  11. develop: '//localhost:3401',
  12. test: '//test.app2.com/app2/', // 重点:/app2/
  13. production: '//app2.zhifuzi.com/app2/',
  14. },
  15. };