@microup/boot
v1.0.0-main-1.0.0.20230823203256
Published
The boot package for the microup platform is a cli building tool for frontends services.
Downloads
1
Maintainers
Readme
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 start
、micro-up-boot dist
、micro-up-boot compile
、micro-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.js
、generateEntry.js
、generateEnvironmentVariable.js
、generateRoute.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-env
和preset-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',
}}
/>