umijs 隐藏开发工具_如何定制企业级前端研发框架?(基于 UmiJS)

前言

当开发前端应用(PC、H5、SSR 等)时,会怎么做?

从头开始初始化,拷贝 webpack 配置、安装一堆 babel 插件、手写一系列 ESLint 规则等,这些流程下来仅仅只能将 Hello World 项目运行起来;然后你开始将初始化操作封装成 脚手架,一键生成新项目。

但此时 A 应用中有构建最佳实践,想下沉为基础能力;

又比如 B 应用实现了一套插件机制,可以让应用可插拔式使用内部功能/技术栈;

...

此时,怎样让前端基础能力被上层框架直接使用,而不是每个前端框架都去开发一套 构建系统、AST、插件机制、目录约束、路由、渲染、错误处理等?

蚂蚁内部的实践是:基于UmiJS或 @umijs/core 封装适用特定业务场景的上层业务框架。

UmiJS 或 @umijs/core

UmiJS 定位是插件化的企业级前端应用框架,广义的 UmiJS = 内核 + @umijs/preset-built-in (内置插件集) + @umijs/preset-react(React 技术栈插件集),整个包大小约 100M。一图胜千言,架构如下图:

也许有同学会问,为什么 UmiJS 要加 runtime、core、bundler 等抽象层(Adaptor)?

因为前端库/工具迭代频繁,短短几年经历好几代打包工具(rollup、webpack)、好几个前端 UI 框架(React、Vue),对前端不变地是我们依旧需要 bundler / compiler、runtime。UmiJS 通过对配置强管控,降低框架对底层依赖配置耦合。

关于 @umijs/core 文档较少,core 中定义了前端可插拔式框架所需的最基本功能,也就是除了 core 内核外,umi 其它功能均由插件组成(包括 dev、build 等)Service(核心 Service 类)

Config(配置类):用户配置获取

PluginAPI(插件基础 API):插件开发中的 api.* 实现来源于此钩子方法执行底层为 tapable,支持通过 before 和 step 调整顺序

Route(前端路由类)

Html(Html 类):定义了一系列操作 html 的工具方法,通过模板生成 html 文件。

如何定制?

如果你所在当前业务线需要开发一套可插拔前端框架 largefish,同时需要针对业务线开发定制插件集(例如 @umijs/preset-largefish)

基于 umi

// packages/largefish

// 额外的 umi 插件集process.env.UMI_PRESETS = require.resolve('@umijs/preset-largefish');

// 执行 umi 命令const child = fork(require.resolve('umi/bin/umi'), process.argv.slice(2), {

stdio: 'inherit',

});

fork 一份 umi 进程,然后加上 largefish 插件集,然后我们就可以愉快地用

$ largefish dev

// => dev 开发

$ largefish build

// => build 构建

同时在 @umijs/preset-largefish 里,我们可以将插件集功能拆分:

// packages/preset-largefishexport default {

plugins: [

// 埋点 './tracert',

// 监控 './monitor',

// 登录鉴权 './auth',

// 部署平台相关 './deploy',

// ... ]

}

这样你的框架 largefish 就具备了业务线插件功能,如果我们的框架 bigfish 需要用到你业务线的登录鉴权,我可以直接在 bigfish 中引用你的 ./auth 插件,开发者可无缝接入。

基于 @umijs/core

基于 @umijs/core 可快速构建出一个简易的可插拔前端框架 (mediumfish),并且基于简易框架的插件可同时兼容 UmiJS 体系,有一套独立的插件集 @umijs/preset-mediumfish。

import { dirname, join } from 'path';

import { IServiceOpts, Service as CoreService } from '@umijs/core';

class Service extends CoreService {

constructor(opts: IServiceOpts) {

// umi 内核版本 process.env.UMI_VERSION = require('../package').version;

super({

...opts,

presets: [

// 定制插件集,可自由发挥封装业务线专属的插件集 require.resolve('@umijs/preset-mediumfish'),

...(opts.presets || []),

],

plugins: [...(opts.plugins || [])],

});

}

}

(async () => {

await new Service({ cwd: process.cwd() }).run({

// command 注册 name,

// command 参数 args,

});

})()

因为用了 @umijs/core,不包含 dev、build 等一系列功能,不过你可以基于此插件集进行扩展与定制:

// packages/preset-mediumfish

export default {

presets: [

// dev 开发 './dev',

// 构建 './build'

// ... ]

}

为了让底层构建工具解耦,我们提供了 @umijs/bundler-webpack,可直接复用 umi 的构建能力。选 umi 还是 @umijs/core 进行封装呢?取决于业务形态,如果你的业务偏中后台,可以基于 umi 进行封装;其他情况可选择 @umijs/core

框架封装实践

Bigfish

Bigfish 是基于 umi 研发的蚂蚁集团前端开发框架,实际上 Bigfish = umi + @alipay/umi-preset-bigfish(蚂蚁内部插件集,包括埋点、监控、权限等一系列功能)

内部 Bigfish 框架与 Umi 版本之间怎样协同的呢?

这点还是有不少实践的,首先,出于内部框架稳定性考虑,我们在 Bigfish 里锁定 umi 的 minor 版本:

// bigfish/package.json

{

"dependencies": {

"umi": "~3.2.8"

}

}

// umi-preset-bigfish/package.json

{

"dependencies": {

"@umijs/preset-react": "~1.6.0"

}

}

这样指定的好处有两点:享受 umi bugfix 后给 bigfish 带来的好处

umi 的不兼容改动(Break Change) 升级可以在 Bigfish 兼容后再使用。

dumi

dumi 是基于 Umi 为组件开发场景而生的文档工具,dumi = umi + @umijs/preset-dumi(组件开发、文档插件集)。因为 dumi 可以利于 umi 的构建能力,preset-dumi 加上对 markdown 解析、展示功能,快速构建出一套可插拔的组件研发及文档展示框架。**

alita

alita 是社区同学 xiaohuoni 基于 Umi 开发的移动端研发框架,alita = umi + @alitajs/umi-presets-alita(移动端插件集)。详见

参考

希望以本文,了解到 Umi 3 的一些基本组成、架构等。同时欢迎对前端基础技术感兴趣的同学,一同交流,宜鑫,蚂蚁集团-体验技术部。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值