微前端实践 | 青训营笔记

118 阅读2分钟

这是我参与「第四届青训营」笔记创作活动的的第13天

微前端

原因:团队成员使用不同的技术栈,考虑到时间紧、任务重,没有时间成本去学习新的技术,因此采用微前端技术确保团队能合作开发,且项目各模块能正常运行。

优点

  • 技术栈无关
    主框架不限制接入应用的技术栈,微应用具备完全自主权
  • 独立开发、独立部署
    微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
  • 增量升级
    在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
  • 独立运行时
    每个微应用之间状态隔离,运行时状态不共享

使用 qiankun 开发微前端。

实践过程

基座配置

import { registerMicroApps, start } from 'qiankun';


registerMicroApps([
  {
    name: 'reactApp',
    entry: '//localhost:3000',
    container: '#container',
    activeRule: '/app-react',
  },
  {
    name: 'vueApp',
    entry: '//localhost:8080',
    container: '#container',
    activeRule: '/app-vue',
  },
  {
    name: 'angularApp',
    entry: '//localhost:4200',
    container: '#container',
    activeRule: '/app-angular',
  },
]);
// 启动 qiankun
start();

子应用配置

  1. 在 src 目录新增 public-path.js,解决子应用挂载时,访问静态资源冲突
  if (window.__POWERED_BY_QIANKUN__) {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
  }
  1. 入口文件 index.js 修改,为了避免根 id #root 与其他的 DOM 冲突,需要限制查找范围。
  import './public-path';
  import React from 'react';
  import ReactDOM from 'react-dom';
  import App from './App';


  function render(props) {
    const { container } = props;
    ReactDOM.render(<App />, container ? container.querySelector('#root') : 
    document.querySelector('#root'));
  }


  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);
    render(props);
  }


  export async function unmount(props) {
    const { container } = props;
    ReactDOM.unmountComponentAtNode(container ? container.querySelector('#root') :  
    document.querySelector('#root'));
  }
  1. 修改 webpack 配置

安装插件 @rescripts/cli,当然也可以选择其他的插件,例如 react-app-rewired

npm i -D @rescripts/cli` 
  1. 根目录新增 config-overrides.js
const { name } = require('./package');


module.exports = {
  webpack: (config) => {
    config.output.library = `${name}-[name]`;
    config.output.libraryTarget = 'umd';
    config.output.jsonpFunction = `webpackJsonp_${name}`;
    config.output.globalObject = 'window';


    return config;
  },


  devServer: (_) => {
    const config = _;


    config.headers = {
      'Access-Control-Allow-Origin': '*',
    };
    config.historyApiFallback = true;
    config.hot = false;
    config.watchContentBase = false;
    config.liveReload = false;


    return config;
  },
};

启动

配置完子应用和基座后,需要将各个项目都 启动 ,否则会报错。

实践问题

  1. Uncaught TypeError: application 'qiankun-micro-app1' died in status LOADING_SOURCE_CODE: Failed to fetch

image.png

解决方法:来自 github 的提醒:

image.png

  1. Uncaught Error: application 'qiankun-micro-app1' died in status LOADING_SOURCE_CODE: [qiankun]: You need to export lifecycle functions in qiankun-micro-app1 entry

image.png

  1. 启动服务时报错:

image.png

  1. Uncaught TypeError: application 'micro-app4' died in status SKIP_BECAUSE_BROKEN: vue_router__WEBPACK_IMPORTED_MODULE_5__.default is not a constructor

image.png