微前端之子应用的启动与改造

本文假设你已经创建好了所有子应用。

启动

微前端中往往有多个子应用。

如果要同时启动所有的子应用,你当然可以一个一个的去启动。

如果你嫌这样麻烦的话,接着往下看。

你可以创建这样一个启动脚本文件,命名为 run.js。这个脚本会通过 child_process 创建多个 shell 命令,每个命令负责一个应用,具体代码如下:

js 复制代码
const childProocess = require('child_process')
const path = require('path')

const filePath = {
  vue2: path.join(__dirname, '../vue2'),
  vue3: path.join(__dirname, '../vue3'),
  react15: path.join(__dirname, '../react15'),
  react16: path.join(__dirname, '../react16'),
  main: path.join(__dirname, '../main'),
}
// 进入子目录 npm start 启动项目
function runChild () {
  Object.values(filePath).forEach(item => {
    childProocess.spawn(`cd ${item} && npm start`, {
      stdio: "inherit",
      shell: true
    })
  })
}
runChild()

修改最外层 package.json

json 复制代码
{
  "scripts": {
    "start": "node run.js"
  }
}

执行 npm start,所有应用都会被启动。

注意:每个子应用的启动脚本要统一为 npm start

改造

子应用要想接入微前端,肯定得需要改造,主要调整是在入口文件。

这里分别拿 Vue3 和 React16 举例。

Vue3

改造前:

js 复制代码
import { createApp } from 'vue'
import App from './App.vue'

import router from './router'
createApp(App).use(router).mount('#app')

改造后:

js 复制代码
import { createApp } from 'vue'
import App from './App.vue'

import router from './router'

let instance = null

const render = () => {
  instance = createApp(App)
  instance.use(router).mount('#app')
}

// 不在微前端环境
if(!window.__MICRO_WEB__) {
  render()
}

export const bootstrap = () => {
  console.log('开始加载');
}

export const mount = () => {
  render()
  console.log('渲染成功')
}

export const unmount = () => {
  console.log('卸载', instance)
}

React16

改造前:

js 复制代码
import React from 'react'
import "./index.scss"
import ReactDOM from 'react-dom'
import BasicMap from './src/router';

ReactDOM.render((
    <BasicMap />
  ), document.getElementById('app-react'))

改造后:

js 复制代码
import React from 'react'
import "./index.scss"
import ReactDOM from 'react-dom'
import BasicMap from './src/router';

const render = () => {
  ReactDOM.render((
    <BasicMap />
  ), document.getElementById('app-react'))
}

// 不在微前端环境
if (!window.__MICRO_WEB__) {
  render()
}

export const bootstrap = () => {
  console.log('开始加载');
}

export const mount = () => {
  render()
}

export const unmount = () => {
  console.log('卸载')
}

改造完成后,在 window.vue3 或 window.react16 中都会多出 bootstrapmountunmount 这三个方法。(vue3 和 react16 是在 vue.config.jswebpack.config.js 中分别定义的 library 名字)。

原理分析

webpack 默认打包成立即执行函数:

js 复制代码
(function(){
    ...
})()

如果设置了 library,webpack 将会把打包的结果赋于 library 定义的变量:

js 复制代码
var react16 = (function(){
    ...
})()
相关推荐
摸鱼的春哥2 小时前
春哥的Agent通关秘籍07:5分钟实现文件归类助手【实战】
前端·javascript·后端
啊森要自信2 小时前
CANN ops-cv:揭秘视觉算子的硬件感知优化与内存高效利用设计精髓
人工智能·深度学习·架构·transformer·cann
国强_dev2 小时前
轻量级实时数仓架构选型指南
架构
念念不忘 必有回响3 小时前
viepress:vue组件展示和源码功能
前端·javascript·vue.js
roman_日积跬步-终至千里3 小时前
【系统架构设计-综合题】计算机系统基础(1)
架构
C澒3 小时前
多场景多角色前端架构方案:基于页面协议化与模块标准化的通用能力沉淀
前端·架构·系统架构·前端框架
崔庆才丨静觅3 小时前
稳定好用的 ADSL 拨号代理,就这家了!
前端
江湖有缘3 小时前
Docker部署music-tag-web音乐标签编辑器
前端·docker·编辑器
代码游侠3 小时前
复习——Linux设备驱动开发笔记
linux·arm开发·驱动开发·笔记·嵌入式硬件·架构
恋猫de小郭4 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter