现在对于前端框架的定义越来越广泛了,在前端工程化中的某一个环节的特定方案,都可泛称为一个前端框架。konos 是一个插件化的前端框架基座,如果你对 umi 有所了解的话,可以把它当作一个没有任何功能的 umi core 基座。konos 提供了一些简单的接口,方便用户扩展和编写 cli 服务。比如想写一个 'yarn create app' 用于初始化项目的话,只需要:然后执行 'npx konos init cli' 就可以完成一个和用户交互后生成脚手架的工作。
这个需求最初来自灵犀开发平台的灵蜂框架需求,它需要将部分模块通过产物包的方式提供给用户,而部分模块以源码的方式提供,然后需要在开发的时候将所有的模块串通,因为不同模块之间存在业务关联和鉴权。所以再编写这个框架的时候,我就想这么特殊的需求,放到 alita 里面不是很合理,而且和业务性关联性太强了,最终可能需要将这个框架交付到业务开发人员的手里维护。就需要这个框架的可扩展性极强,上手难度极低。所以将核心的功能抽离成 konos,将业务性绑定的放到脚手架本地的 scripts 中,但是同时将他映射为本地的可执行命令。(这个不在本次的分享内容中)
这就完成了一个 hj 框架,你可以使用 hj xxx 的命令来启动对应的 cli 服务,比如内置的 hj inits config,可以在当前项目生成 hj 框架的配置文件。以下举几个例子来展示如何基于 konos 编写一个部门级别的前端框架:可能你刚开始不知道需要加什么配置,你可以在你需要的时候再回来添加,这里我为了后续描述的连续性,先在这里全部列出了,我这次需要使用的配置。因为部分模块是以产物包的方式提供给用户,所以就需要一个上传和下载的云端,如果有服务器提供,你可以根据上传和下载的接口来完成这个流程,我这里为了演示方便,就用 npmjs 作为我的云端。这个要考虑到对接的模块是以什么框架构建的,但是正常的产物包是放在 'dist' 或者 'build',所以我们默认去找这两个目录,当然也提供配置给用户指定,就是上面添加的 'outputPath':找到构建产物包之后,其实很简单,只要新建一个 'package.json',然后使用 'npm publish' 就可以把包发布到 npm 上。新建文件 src/commands/publish.ts前面说到上传非常简单,只需要执行 'npm publish' 就可以,那下载是不是只要执行 'npm install' 就可以呢?其实这要看和我们的需求是否符合了,'npm install' 会将子包放到 'node_modules' 文件夹下,然后所安装的模块也需要编写在项目的 package.json 文件中,但是这个包显然与我们正在开发的项目无关,并且放到 'node_modules' 之后也很“难”找到,当然通过包名查找也不是很难,但是如果后续还需要预览,做文件代理显然是一个大问题。所以我们需要编写一个特定的 'npm install' 来完成我们的需求,这要求我们对于 npm 的执行有一定的了解,这里不做过多的展开。简而言之就是下载-解压的过程。npm 除了根据 package.json 执行 'install' 之外还可以使用通过执行 'npm pack repo@version' 将指定的包下载到本地文件,当然了,需要注意的是下载的执行目录要避免是一个 npm 包,因为 'npm pack' 也用来将当前项目做一个打包压缩,你可以简单的理解为执行 'npm publish' 的时候,其实是先执行了 'pack' 再上传。你可以在任意空文件夹下尝试一下,比如执行 'npm pack xiaohuoni@0.0.1',将会在当前文件夹下得到 'xiaohuoni-0.0.1.tgz' 文件,然后使用解压工具打开它就能得到和 'npm install xiaohuoni@0.0.1' 一样的内容,只是存放路径不一样而已。因此我们需要做的只是简单的解压文件操作,将文件解压到它对应的包名的目录下,使用 linux 命令就可以完成:由于 linux 命令在 window 上需要打开 git 提供的命令行工具才能正确执行,所以我们使用 node 包 'tar' 来完成。为了加快每次执行安装的过程,我们可以加一个简易的缓存机制,如果本地已经存在对应的 'tgz' 包,就使用本地的包而不再从 npm 上下载。关于需要指定安装的模块,我们通过增加一个配置 'dependencies' 来完成:dependencies 使用和 package.json 中的 dependencies 配置一致,这对于前端人员来说,零理解成本。上面我们提到文件将被解压到对应包名的目录下,比如 '@lingxi-assets/demo' 默认的解压路径是 '/build/demo',模块相互之间存在关联性,所以这个文件结构,可能会遇到需要灵活配置的时候,因此我们增加一个配置 'paths' 用来指定包名对应的解压路径。'@lingxi-assets/demo' 最终会被解压到 '/build/hello' 目录。新建文件 src/commands/install.ts
至此这个需求就都完成了,下面,我再举一个前端框架常见的需求举例,我们再框架构建之后,总会在本地打开,看看构建产物是否都正确生成,不管构建环节的脚本和测试做的多么完善,这也算是一种人工的兜底行为,我们常用的就是 'cd build && serve' 这会在本地 3000 端口启动一个 server 服务,能代理映射到 build 目录,因此我们可以方便的访问 'build/index.html' 文件来验证产物。但是常常遇到一个问题,本地开发使用 proxy 作为代理,中转了请求,但是在 build 之后 proxy 可能就无效了,因此我们现在的需求就是,在 build 之后,如何继续使用 proxy 配置。其实我们可以简单的写一个命令,如 'hj preview'。其实就是一个 express 中间件,需要的数据,我们可以通过增加两个配置 'proxy' 'nginx'来指定。根据上面的配置,我们就可以实现,当访问首页的时候,自动代理到 'demo' 目录,当请求以 '/server' 开头的路径会被中转到目标服务器,所以只要 proxy 配置与开发时使用的 proxy 配置一致,nginx 配置与部署时使用的 nginx 对应,就可以在本地更好的还原云端的部署情况。这在调试验证的时候,非常好用。新建文件 src/commands/preview.ts
不知道细心的你有没有发现,上面实现的三个功能,每个功能实现代码行数都没超过 100 行,其中还包括空行和必要的模版代码。这在使用 konos 之前是比较难做到的,毕竟简单的 cli 的命令行配置也要写不少的代码。另外文件其实可以放在任意的目录下,模版脚手架为了逻辑上能更好的管理项目,因此区分了 'commands' 'config' 'generators' 'inits' 这几个文件夹,你可以完全按照你的个人喜好来重新组织文件结构,只需要最终在 'src/preset.ts' 文件中,使用上你编写的文件即可。
假如把 'umi' 'alita' 'fish-x' 这样的通用框架称为公司级前端框架的话,那基于 konos 的产物,就是部门级的前端框架了,它拥有更高的客制化和超高的纯净度,但同时也代表着它没有附带任何的功能实现,每一步要做什么都需要开发者自己实现,所以如果是常规的前端需求,最好还是选用公司级的前端框架,毕竟框架给的足够多。不过好在 konos 开发人员仅仅需要掌握一点点的 node 和 express 知识。当然你也可以把部门级框架当作公司级框架的功能补充,以 konos 的灵活性完全可以兼容所有的前端框架。