建议阅读 Umi 微前端, 了解 微前端 的基本使用

简介

  • Lerna 是一个快速、领先的构建系统, 用于管理和发布来自同一源码仓库的多个 JavaScript/TypeScript 软件包

  • Umi 企业级前端开发框架, 它提供了一套完整的 Web 应用开发解决方案, 包括路由、状态管理、数据请求、页面布局、主题定制等功能

实践

包版本

  • node: 18.20.7

  • npm: 10.8.2

  • lerna: 8.1.8

  • umi: 4.3.35

项目目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|-- 根目录
|-- packages # 项目目录, 名称要跟 package.json 中 workspaces 以及 lerna.json 中 packages 一致
|-- app # 主应用app
|-- src
|-- .umi # 动态生成的文件夹
|-- .env # 配置启动端口和禁用 babel 的缓存
|-- .umirc.ts # umi 配置文件
|-- app1 # 子应用app1
|-- src
|-- .umi # 动态生成的文件夹
|-- .env # 配置启动端口和禁用 babel 的缓存
|-- .umirc.ts # umi 配置文件
|-- app2 # 子应用app2
|-- src
|-- .umi # 动态生成的文件夹
|-- .env # 配置启动端口和禁用 babel 的缓存
|-- .umirc.ts # umi 配置文件
|-- lerna.json # lerna 配置文件
|-- package.json # 全局配置文件

搭建 monorepo 项目 (可选)

  • 通过 npm install lerna -g 全局安装 lerna

  • 命令行执行 npx lerna init 初始化项目

  • 配置项目

    1
    2
    3
    4
    5
    {
    "npmClient": "npm", // 使用 npm
    "packages": ["packages/*"], // 指定包目录
    ... // 其他配置
    }
    1
    2
    3
    4
    {
    "workspaces": ["packages/*"],
    ... // 其他配置
    }

创建主/子应用

  • 依次执行下面命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 从根目录进入 packages 目录
    cd ./packages

    # 创建主应用 app
    npx create-umi@latest

    # What's the target folder name?
    app

    # Pick Umi App Template
    Ant Design Pro

    # Pick Npm Client
    npm

    # Pick Npm Registry (这一步会在 根目录 下创建 `.npmrc` 文件)
    npm
  • packages/app/package.json 中配置 name 一定要配置, 否则 npm workspaces 找不到项目

    1
    2
    3
    4
    {
    "name": "app",
    ... // 其他配置
    }
  • packages/app 下新建 .env 文件, 并配置 启动端口和禁用 babel 的缓存

    1
    2
    PORT=8000
    BABEL_CACHE=none
  • 依次执行下面命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 从根目录进入 packages 目录
    cd ./packages

    # 创建子应用 app1
    npx create-umi@latest

    # What's the target folder name?
    app1

    # Pick Umi App Template
    Simple App

    # Pick Npm Client
    npm

    # Pick Npm Registry (这一步会在 根目录 下创建 `.npmrc` 文件, 不需要可以删除)
    npm
  • packages/app1/package.json 中配置 name 一定要配置, 否则 npm workspaces 找不到项目

    1
    2
    3
    4
    {
    "name": "app1",
    ... // 其他配置
    }
  • packages/app1 下新建 .env 文件, 并配置 启动端口和禁用 babel 的缓存

    1
    2
    PORT=8001
    BABEL_CACHE=none
  • 依次执行下面命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 从根目录进入 packages 目录
    cd ./packages

    # 创建子应用 app2
    npx create-umi@latest

    # What's the target folder name?
    app2

    # Pick Umi App Template
    Simple App

    # Pick Npm Client
    npm

    # Pick Npm Registry (这一步会在 根目录 下创建 `.npmrc` 文件, 不需要可以删除)
    npm
  • packages/app2/package.json 中配置 name 一定要配置, 否则 npm workspaces 找不到项目

    1
    2
    3
    4
    {
    "name": "app2",
    ... // 其他配置
    }
  • packages/app2 下新建 .env 文件, 并配置 启动端口和禁用 babel 的缓存

    1
    2
    PORT=8002
    BABEL_CACHE=none

启动项目

在根目录下执行 npm install 安装依赖

  • 方式一:进入各个应用目录, 分别执行 npm run dev

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 进入 packages/app 目录
    cd ./packages/app
    # 启动主应用
    npm run dev

    # 进入 packages/app1 目录
    cd ./packages/app1
    # 启动子应用
    npm run dev

    # 进入 packages/app2 目录
    cd ./packages/app2
    # 启动子应用
    npm run dev
  • 方式二:进入根目录, 执行 npm run dev -w=xxx, -w 就是 --workspace, xxx 对应各个应用 package.jsonname, 详见:npm workspace

    1
    2
    3
    4
    5
    6
    7
    8
    # 根目录下启动主应用
    npm run dev -w=app

    # 根目录下启动子应用
    npm run dev -w=app1

    # 根目录下启动子应用
    npm run dev -w=app2

主应用链接子应用

在主应用 packages/app/.umirc.ts 中添加下面内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
export default {
routes: [
{ path: '/', redirect: '/home' },
{ name: '首页', path: '/home', component: './Home' },
{ name: '权限演示', path: '/access', component: './Access' },
{ name: ' CRUD 示例', path: '/table', component: './Table' },
// 新增微应用示例
{ name: 'App1', path: '/app1/*', microApp: 'app1' },
{ name: 'App2', path: '/app2/*', microApp: 'app2' },
],
qiankun: {
master: {
apps: [
{
name: 'app1', // 与上面 routes 中 microApp 对应
entry: '//localhost:8001', // packages/app1/.env 文件中的 PORT
},
{
name: 'app2', // 与上面 routes 中 microApp 对应
entry: '//localhost:8002', // packages/app2/.env 文件中的 PORT
},
],
},
},
... // 其他配置
};
  • 安装 qiankun 插件

    1
    2
    # 根目录下执行
    npm i @umijs/plugins -D -w=app1 -w=app2
  • 在子应用 packages/app1/.umirc.tspackages/app2/.umirc.ts 文件中引入 qiankun 插件

    1
    2
    3
    4
    5
    6
    7
    export default {
    plugins: ['@umijs/plugins/dist/qiankun'],
    qiankun: {
    slave: {},
    },
    ... // 其他配置
    };

更多微前端配置

Umi 项目原理?🤔

  1. 通过 create-umi@latest 创建项目, 会生成一个 .umirc.ts 配置文件

  2. 当项目启动时, 通过 Webpack插件 找到 .umirc.tssrc/app.ts 文件, 并生成 src/.umi/* 文件夹

  3. 这个插件应该在 @umi 某个包里面, 具体干了什么事情?

  • 根据用户配置动态生成 根组件, 就是常见的 createRoot(document.getElementById('root')).render(<App />)

  • 根据用户配置动态加载插件, 减少打包体积


参考文章:【鸣谢】

Umi 微前端