@microup/boot

1.0.0-main-1.0.0.20230823203256 • Public • Published

microup Boot

安装依赖

推荐安装 pnpm 作为包管理器,可以更快的升级我们的依赖包。

npm i -g pnpm
pnpm i

MAC系统设置权限

chmod -R 777 node_modules

启动

pnpm run start

简介

microup 基础的 cli 工具包,负责对master、front、app包的打包,对这些包的js,css文件进行压缩与编译工作,最终生成微前端服务的镜像。

这个包基于 webpack5 模块联邦开发,共享 boot 与目标包 dependencies 中的依赖,公开目标包内注册的动态远程容器组件,共其他 remote 模块使用。

负责目标包的基础路由解析,通过一级路由代理到不同 remote 模块,开发时也可以指定访问线上或本地其他 remote 模块。

负责管理整个项目的一些依赖包,比如 react,mobx 等包都会注册在 boot 的 dependencies 中。

配置

.env

在使用boot打包或者启动项目时,可以在.env中配常量,这些常量将最终写入window._env_变量中,可全局访问。

使用这些常量

import {getEnv} from '@microup/utils';
const STATIC_URL = getEnv('STATIC_URL');

一些特殊常量

API_HOST=https://***.***.com # 后端接口地址
STATIC_URL=http://192.168.**.***:9095 # 前端静态服务地址
****=http://localhost:**** # 本地调试时,连接本地的其他 remote 模块
# 例如:app2=http://localhost:9101

config.js

在使用 boot 打包或者启动项目时,可以在config.js中配置 boot 的一些配置。

{
  master: '@microup/master', // master 目录地址
  port: 9101, // 本地运行端口
  scopeName: 'app1', // 属性则是 remote 模块的 scope 标识
  titlename: 'microup', // 设置浏览器标签页标题,也可以在启动时传入 TITLE_NAME 设置标题(cross-env GENERATE_SOURCEMAP=true)
  favicon: 'favicon.jpeg', // 设置浏览器标签页图标
  routes: { // 配置项目一级路由对
    app1: './react/index'
  },
  theme: { // 注入全局样式变量
    'primary-color': '#2979FF',
  },
  htmlTemplate: require.resolve('@microup/master/lib/index.template.html') // 设置 html 模板文件的地址
  webpackConfig(config) { // 设置webpack的配置,例如设置别名
    config.resolve.alias = {
      ...config.resolve.alias || {},
      [packageName]: path.resolve('.'),
      '@': path.resolve('./src'),
    };
    return config;
  },

  isDev: true, // 设置是否以 development|production 模式打包或启动,在打包时也可以使用 --dev true 设置为 development 模式
  ///////////////下边属性不常用////////////
  src: 'react', // 组件主体代码对应目录
  lib: 'lib', // compile 打包对应目录名(一般固定lib)
  output: './dist',// dist 打包目录名字
  exposes: {}, // 对外公开远程模块
  babelConfig(config, mode, env) { // babel 配置钩子
    return config;
  },
  tmpDirPath: path.join(__dirname, '../tmp'), // tmp 文件地址
  devServerConfig: { // 本地运行时,服务器配置
    hot: true,
    historyApiFallback: true,
    host: 'localhost',
  },
  browsers: [ // 浏览器兼容配置
    'last 2 versions',
    'Firefox ESR',
    '> 1%',
    'ie >= 8',
    'iOS >= 8',
    'Android >= 4',
  ],
  isPx2rem: false // 是否开启rem 模式
}

routes

其中 routes 属性配置项目一级路由对应目录,每个模块中都需要有一个 scopeName 对应的一级路由,以便作为 remote 模块时可以做模块的路由入口。

例如本次案例中 scopeName 为 app1 ,则路由中也需要设置 app1 对应目录。

scopeName: "app1"
routes: { // 配置项目一级路由对
	app1: './react/index'
},

这里 app1 在 url 中可以被 http://:/#/app1/ 匹配,例如:被http://192.168.20.133:9091/#/a1/匹配。

scopeName

scopeName 属性则是 remote 模块的 scope 标识,当前模块作为 remote 模块时,被 host 模块引用可以使用 ExternalComponent 组件加载。

例如 app2 中使用 app1 的组件:

import {ExternalComponent} from '@microup/utils';

<ExternalComponent
   system={{
      scope: 'app1', module: 'App1EC',
   }}
/>

被引用组件 App1EC 则需要使用/* externalize: App1EC */注册在 app1 内:

import React from 'react';

export default function (props) {
  return (<div>app1-externalize-components</div>);
}
/* externalize: App1EC */

任意组件都可以写入/* externalize: App1EC */,写入后其他模块都可以使用 ExternalComponent 组件访问。

指令

boot 包常用指令有 pnpm run compile 和 pnpm run start:bin

compile

使用 gulp 打包 master 与 boot 包内文件到 lib 目录,这里只通过 babel 编译,不进行压缩操作。然后通过 npm publish 命令把 lib 目录打包发往私有库中。

start:bin

通过 webpack dev server 开启一个本地 http 服务示例,用于测试当前 boot 包。

根据 project.config.js 文件中路由配置开启这个服务示例。

boot 包内的服务示例写于 exampleMaster 中,该目录只在开发环境加载使用,执行 compile 时会过滤这个目录中的内容。线上环境则不在需要。

配置项 master: './src/exampleMaster' 作用是服务示例所用 master 文件的位置,master 负责全局状态管理,权限校验,路由重定向等功能。

配置项 routes 作用是一级路由与对应组件位置的描述

# 只是本地开发
routes: {
  a1: './src/exampleMaster/App1',
  a2: './src/exampleMaster/App2'
},

目录

目录解析

boot
|-bin # nodeJs 命令行实现方案
|-lib # 执行 compile 后生产的打包目录
|-src #
|  |--bin # webpack 配置目录
|  |--exampleMaster # 服务示例代码,用于测试 boot 包
|  |--store # boot 状态管理目录,仅用于 boot 内部
|  |--utils # 一些 boot 的全局方法
|  |--.env # 本地运行时服务参数配置
|  |--default.config.js # 默认 boot 配置,主要是外放的 webpack 一些配置
|  |--index.template.html # 本地运行时 html 模板
|-tmp # entry入口目录,打包时自动生成,加载 Master 组件
|-gulpfile.js # boot compile 指令运行内容,负责对 src 打包工作
|-project.config.js # 本地运行 start:bin 时,根据这个配置启动一个 host 模块

bin目录

该目录存储 boot 作为 cli 可运行的指令,有 micro-up-boot startmicro-up-boot distmicro-up-boot compilemicro-up-boot compile

stert

开启一个开发环境,主要用于前端开发时使用。

参数有-c|--config设置 boot 配置文件目录。

参数有-s|--src设置跟组件对应目录,默认目录是react,src 配置项优先获取指令上的变量参数,如果没有设置,则会获取 config.js 文件中设置的 src 项。

参数有-l|--lib设置 boot 打包后的目录名,通常无需设置

例如:app1设置开启本地运行的开发环境 host 模块

"scripts": {
	"start": "micro-up-boot start --config ./react/config.js",
},

dist

用于app、front包的打包,该指令不用于 master、boot包打包。

基本参数同上,在此基础多出-d|--dev参数,在生产环境打包无需开启,如果需要测试或打开发环境代码包时设置为 treu 即可。

"scripts": {
	"dist:dev": "micro-up-boot dist --config ./react/config.js --dev true"
},

compile

目前仅用于 master 打包,打出 master 的lib 包。

prePublish

用于修改 package.json 中的版本属性。

使其改为这样的示例格式0.0.1-dev-0.0.1.20230810182951

后边 20230810182951 这串数字是当前时间精确到秒,保证每次打包都会有新的版本产生,部署时可以根据排序优先选择最大时间的对应包;并且 master 包引用时可以使用范围定义:"@microup/boot": ">=1.0.0-main-1.0.0 <1.0.0-main-1.0.1"保证每次pnpm update @microup/boot都可以下载到最新的boot包。

注:该指令目前已经废弃,这个功能已在ci的脚本中实现。

src目录

boot 包主要代码,主要对webpack的配置与开发。

生成tmp

tmp 目录由 Nunjucks 模板文件自动生成,是 webpack 入口,作用是加载 Master 组件, 以及分发 routes 路由与访问 remote 模块。

在src/bin/common 目录下generateApp.jsgenerateEntry.jsgenerateEnvironmentVariable.jsgenerateRoute.js文件代码通过 Nunjucks 模板引擎,根据 nunjucks 中的模板生成对应的 jsx 文件,放于 tmp 目录中。

前端模块,在执行 dist 和 stert 指令时,tmp 在 node_modules/@microup/boot 目录下都会生成。

路由处理详情,请查看 master 包内文档。

加载 Master 组件

webpack加载第一个文件是 tmp/bootstrap.index.js 它只有一句代码import('./{{ bootstrap }}') 起作用是解决Shared module is not available for eager consumption错误以及拆分出更大块的初始化代码。(详情参考

然后在 tmp/app.index.js 中会渲染 Master组件。

{Master ? <Master AutoRouter={AutoRouter}/> : <AutoRouter/>}

Master 组件根据 config.js 中配置的路径查找组件,通常都是指向'@microup/master'包,boot 包除外。

master: '@microup/master', // 非 boot
master: './src/exampleMaster', // boot

webpack配置

webpack 配置代码主要位于src/common/config/getWebpackCommonConfig.js中,主要处理: babel 对 js 代码编译与压缩、less 模块化与编译、ts配置注入与编译、全局样式变量注入、全局env数据注入、sourceMap、模块联邦这些工作。

babel js代码编译

babel 配置代码的文件位于src/bin/common/config/getBabelCommonConfig.js中。

目前babel 版本为 7;使用preset-envpreset-react预设;useBuiltIns 模式默认使用 entry ,在 app.nunjucks.jsx 中使用 import "core-js"全量引入 core-js;core-js 版本默认使用 3.29.1。

注:@babel/polyfill 已被弃用,交由core-js处理(详情参考)。

注:useBuiltIns 模式默认没有使用 usage ,为避免扩展其他包时 polyfill 失效,如切换 usage 模式,需要删掉 app.nunjucks.jsx 中的 import "core-js"

less 模块化

webpack 配置中,使用 oneOf 匹配命名 .module.less 结尾与 .less 结尾的文件,根据命名中是否有 module 判断是否开启 modules 。

开启 less 模块化后,可以使用变量引入方式添加样式例如:

// index.module.less
.red {
  color: red;
}
// index.jsx
import classnames from 'classnames'
import styles from './index.module.less'
export default withRouter((props) => {
  return (
    <div>
      <div className={classnames(styles.red)}>master</div>
    </div>
  );
})
全局样式变量注入

样式变量通过 lessOptions.modifyVars 注入,如果需要js处理的动态样式变量也可以使用 @plugin

默认样式变量包括一些主题颜色与提示颜色,这个配置位于 src/default.config.js 中。

  theme: {
    'primary-color': '#2979FF',
    'bg-color': '#fff',
    'info-color': '#2979FF',
    'warning-color': '#FD7D23',
    'success-color': '#1AB335',
    'error-color': '#F34C4B',
    'border-color': 'fade(#CBD2DC, 50%)',
    'text-color': '#12274D',
    'heading-color': '#12274D',
    'disabled-text-color': 'fade(@text-color, 45%)',
    'disabled-bg-color': 'fade(#F2F3F5 , 60)',
  },

如需要在特定模块添加样式变量时,也可以在 host 模块启动前修改修改 config.js 文件,做 theme 的覆盖

const config = {
  master: '@microup/master',
  port: 9101,
  scopeName: 'app1',
  theme: { // 覆盖或添加当前模块的样式变量
  	'text-color2': '#12274D',
  },
  routes: {
    app1: './react/index'
  },
  htmlTemplate: require.resolve('@microup/master/lib/index.template.html')
};

样式变量在引用时,可以直接使用 @ 引入:

.red {
  color: @primary-color;
}
env数据注入

env数据处理的代码位置位于 src/bin/common/generateEnvironmentVariable.js 中,获取当前模块 .env 文件数据与 boot 包中 .default.env 文件据做融合,生成 env-config.js 文件,运行后注入到 window._env_ 中。

// generateEnvironmentVariable.js 中
const combineEnv = {
	NODE_ENV: JSON.stringify(env),
    ...defaultEnv.parsed,
	...customEnv.parsed,
};
fs.writeFileSync(
	envConfigPath,
	`window._env_ = ${JSON.stringify(combineEnv)};`,
);

// 生成的 env-config.js 文件
window._env_ = {"NODE_ENV":"\"development\"","API_HOST":"https://api.test.yqcloud.com","LOCAL":"true","TITLE_NAME":"micorUp","COOKIE_SERVER":"localhost:cookieServer","FILE_SERVER":"localhost:fileserver","STATIC_URL":"http://192.168.20.133:9095","app1":"http://localhost:9101"};
sourceMap

默认情况下运行 start 指令时开启 sourceMap,运行 dist 打包时关闭 sourceMap。如果需要手动设置开启,也可以传入 GENERATE_SOURCEMAP 变量开启

"scripts": {
	"dist:bin": "cross-env GENERATE_SOURCEMAP=true node bin/micro-up-boot dist --config ./project.config.js -s src"
}
alias

在 config.js 配置文件中可以设置别名。

webpackConfig(config) {
	config.resolve.alias = {
  		...config.resolve.alias || {},
  		[packageName]: path.resolve('.'),
  		'@': path.resolve('./src'),
	};
	return config;
},

别名设置后在 js 文件中使用

import styles2 from '@/exampleMaster/index.module.less'

别名设置后在 less 文件中使用,@ 前边需要加上 ~ 符号。

@import '~@/exampleMaster/admin.less';
模块联邦(Module Federation)

exposes 属性

可以允许 host 在运行时通过公开远程模块的方法来设置远程模块的 publicPath。(详情参考

exposes 属性注入方式:

主要通过 getExternalizeExposes() 方法公开远程模块。

其次 config 注册的 routes 也将公开成为远程模块,这也是微前端实现 remote 模块间连接的重要步骤。

也可以在 config.js 中传入 exposes 属性,注入外放模块。

getExternalizeExposes 工作:

getExternalizeExposes 方式主要通过扫描文件中 externalize:** 注释(例如:/* externalize: App2EC */)注册外放组件。在每次打包 remote 模块时都会扫描模块内的 externalize 组件,注册后,在 host 模块中,可以使用 ExternalComponent 组件引入注册的组件。

// remote 模块中(app2)
export default function (props) {
  console.log(props)
  return (<div>app2-externalize-components</div>);
}
/* externalize: App2EC */

// host 模块中
<ExternalComponent
   system={{
      scope: 'app2', module: 'App2EC',
   }}
/>

Package Sidebar

Install

npm i @microup/boot

Weekly Downloads

0

Version

1.0.0-main-1.0.0.20230823203256

License

MIT

Unpacked Size

127 kB

Total Files

41

Last publish

Collaborators

  • wuzhan