上千 star 的 Fes.js 是如何炼成的?

4,091 阅读7分钟

前言:Fes.js 从 2017 年诞生到今天有 5 个年头,它到底是如何一步步变成一个好用的前端应用解决方案的呢?

诞生

在2017年,我加入现在的公司,工作内容是开发客服业务相关的中后台应用。日复一复的开发相似的东西,逐渐变得枯燥乏味,于是我想弄一个框架来实现快速开发中后台应用,它就是 fes.js

fes.js 的愿景:

  • Fast:极致的开发体验
  • Easy:上手简单
  • Strong:健壮的代码和优越的性能

成长

fes.js 最初定位只是中后台应用解决方案,现在不仅可以开发中后台应用,还可以开发H5,成为通用前端应用解决方案。那么 fes.js 到底做了那些改变才能顺利华丽转型呢?

V1

中后台前端应用大多要处理这些事:

  1. 构建, dev 和 build
  2. 入口index.html
  3. 入口main.js,初始化 vue 实例
  4. 路由相关
  5. 权限相关
  6. 页面布局
  7. 接口请求
  8. ...

在当时 CLI 工具很热门,比如 Vue-CLI 和团队内的 mn,他们处理构建相关事情,而其他事情需要项目自行处理。那么开发新项目步骤就是先拷贝老项目,再改改代码,再添加新功能,久而久之发现一些问题:

  1. 继承 “待优化” 代码,不熟悉改起来很费劲,不改又是隐患
  2. 技术栈老旧,升级很费劲,不如重新弄一套新的
  3. 一个 request 工具函数,十种写法,维护起来心累

那么提供一个封装这些通用功能的框架,统一代码规范和代码组织方式,代码优化和升级交给框架,用户完全不用操心,v1 版本就做这了这些事。

设计思路

截屏2022-05-19 下午2.43.35.png

模块划分

截屏2022-05-24 下午2.42.59 (1).png

  • fes-cli 是命令行工具,提供预编译、创建工程、开启开发调试、打包发布等能力。
  • fes-core 是运行时框架,提供固定页面布局,提供权限管理、储存管理、路由管理、接口管理、状态管理、数据字典管理、环境管理等API。以插件的方式提供运行时的扩展。
  • fes-ui 是组件库,包含30+的PC端组件库,可以快速搭建出增删改查等页面。

使用方式

  1. 全局安装命令
wnpm i @webank/fes-cli -g
  1. 在项目中申明依赖
{
    "dependencies": {
        "@webank/fes": "^1.0.0"
    }
}
  1. 安装依赖后在项目根目录运行
fes dev 

自此v1版本诞生,把开发应用比作建房子的话,使用 fes.js 相当于给你毛坯房,只需要装修

V2

当 v1 版本迭代运行一段时间后,我们遇到一些问题:

  1. 模块划分不合理 v1 版本对用户屏蔽了 fes-ui 的概念,用户不需要了解如何安装和注册这些组件,只需要在 package.json 中声明依赖 @webank/fes ,在代码中使用组件。 理想很完美,但是现实很骨感。fes-ui 是高频更新的,fes-core 是低频更新的。当 fes-ui 不兼容更新升级大版本号时,由于 @webank/fes 依赖 fes-ui ,那么 @webank/fes 也必须跟随升级大版本,给 @webank/fes 可用性稳定性带来挑战。

  2. 全局 fes 命令 v1 版本预期用户在本地全局安装 fes 命令,在构建平台中也全局安装 fes 命令,应付不同项目可以节省非常多安装时间。如果 fes-cli 非常稳定,几乎不更新,那么是可行的。然而现实是 fes-cli 也需要更新迭代,同时fes-cli 提供的预构建、mock等能力需要项目配合,存在不同项目需要使用不同版本 fes-cli 的可能。

准备在 v2 版本解决上面问题。

设计思路

运行思路跟 v1 版本一致,要进行两项改动: 1、拆分 @webank/fes 为 @webank/fes-core 和 @webank/fes-ui,解耦两个模块 2、fes-cli 改为项目启动,非全局安装

模块划分

截屏2022-05-24 下午3.59.02.png

使用方式

  1. 在项目中申明依赖
{
    "dependencies": {
        "@webank/fes-core": "^2.0.0",
        "@webank/fes-ui": "^2.0.0",
    },
    "devDependencies": {
        "@webank/fes-cli": "^2.0.0",
    }
}
  1. 安装依赖后在项目根目录运行
fes dev 

v2 版本还把 Vue 从 1.0 升级到 2.0,webpack 升级到 4.0,带来了更好的开发体验。

V3

在 v2 版本运行一段时间后,我们又遇到一些问题:

  1. 扩展能力弱 v2 版本封装 Vue 的插件能力提供扩展。Vue 插件在运行时做事情,无法在构建阶段做事情。比如说我想把 src/icons 文件夹下的 svg 文件自动生成 Vue 组件并注册,Vue 插件就无法实现。它需要在构建阶段扫描 icons 文件夹,根据文件名生成额外代码。

  2. 过于固化 使用 fes.js 好比在格局固定的毛坯房基础上进行装修,添加各种东西。时代在变,用户想要有更好居住的体验,不满足毛坯房的格局,但是 fes.js 无法变更格局。

为了解决这些问题, fes.js 一是需要强化扩展能力,让插件支持运行时和构建时。二是不再固定毛坯房的格局,而是把毛坯房的房间抽象为插件,让用户自由选择用什么插件来组成毛坯房。 v3 以插件机制重写全部代码。

设计思路

插件机制:

截屏2022-05-24 下午5.50.09.png

webpack 等构建器执行编译之前,各插件可以读取文件、配置、环境变量,执行相应逻辑后把运行时代码写入.fes 临时目录,然后在入口文件fes.js添加运行时代码依赖。通过此方式插件可以支持构建时和运行时扩展能力。此架构下,核心逻辑是插件的生命周期管理。

执行 fes dev的运行流程:

截屏2022-05-25 上午10.16.52.png

模块划分

截屏2022-05-24 下午7.46.49.png

fes 内置包preset-build-inruntime,包含构建、路由、入口文件、运行时插件机制内容,不包含任何业务相关的内容,所以从此 fes.js 摇身一变成为通用的前端应用解决方案。

虚线包含的插件根据业务需求自由挑选。比如开发中后台应用,布局可以使用fes-plugin-layout,权限设置可以使用fes-plugin-access

插件

截屏2022-05-24 下午7.47.50.png

使用方式

  1. 在项目中申明依赖
{
    "dependencies": {
        "@fesjs/fes": "^2.0.0"
    }
}
  1. 安装依赖后在项目根目录运行
fes dev 

v3 版本还把 Vue 升级到 3.0,webpack 升级到 5.0,进一步优化了开发体验。同时发布了新的基于 Vue3 组件库 FES-Design,FES-Design的设计体系目前还在不断的探索中,希望今后能够通过更多的积累为用户提供一款更优秀更专业的企业级产品设计体系。

V4

在开发 v3 版本时 webpack 刚发布 5.0,考虑到 webpack 生态,我们继续用 webpack 作为构建器,构建相关的逻辑围绕 webpack 进行。在去年,前端圈各种构建器方案冒出来了,比如esbuilder、vite、tsc等。体验 vite 之后觉得真香,webpack 完全打不过,打不过就加入吧!

设计思路

v3 版本中 webpack 相关的构建逻辑在包@webank/preset-built-in中,把他们从中剥离出来形成新模块 fes-builder-webpack,同时基于 vite 开发构建逻辑形成新模块fes-builder-vite。 名称以fes-builder-开头的包是负责处理构建逻辑的插件集,会优先加载,实现逻辑的方式依然基于插件机制。

模块划分

截屏2022-05-24 下午8.35.22.png

使用方式

  1. 在项目中申明依赖
{
    "dependencies": {
        "@fesjs/fes": "^3.0.0",
        "@fesjs/builder-vite": "^3.0.0"
    }
}
  1. 安装依赖后在项目根目录运行 fes dev

未来

未来 fes.js 会变成什么样,我也不知道,我知道的是 fes.js 跟随潮流变成适合它的样子。

fes 和 fes-design 均已开源,欢迎大家体验。

fes.js :
地址: github.com/WeBankFinTe…
文档: fesjs.mumblefe.cn/next

fes-design:
地址: github.com/WeBankFinTe…
文档: fes-design.mumblefe.cn