1 写在前面的话
创新互联公司专业为企业提供项城网站建设、项城做网站、项城网站设计、项城网站制作等企业网站建设、网页设计与制作、项城企业网站模板建站服务,10余年项城做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。搭一个脚手架,考验了你的 nodejs 水平、工程化能力、以及工具服务的设计能力,是前端进阶不可或缺的过程
笔者在开发 cli 的过程中,调研流行的 cli 并形成最佳实践,本文旨在用最短的篇幅实现主要功能,揭露核心原理,同时提供 demo 仓库与大家学习探讨。
通篇阅读大约需要 10 分钟,基于本教程自己撸一个 cli 大约需要花费 15 分钟
2 脚手架的雏形
其实脚手架的初衷,就是提供一个最佳实践的基础模板,因此模板拷贝是其核心功能
几年前我曾写过一个极简的脚手架,大该干了这么一件事儿
一个命令,就可以把我预设的完整的工程目录创建好,特别方便效率。
我想,这应该算是一个雏形脚手架吧
3 脚手架需要考虑的
上面雏形脚手架可以很好的服务于个人需求,但是毕竟过于干瘪和简陋,要想成为被大家广泛接受的工具,还需要完善。
大家熟知的 vue-cli create-react-app @tarojs/cli umi 最基本功能:首先提出一些列问题选项,然后为你的新建项目提供一份模板并安装依赖,再提供调试构建命令
没错,最核心的部分就是这个思路;但如果要做成一个可伸缩的、用户友好的,还需考虑这些需求:
看起来信息量有点大,但其实都并不晦涩,我们一一说明一下意图
3.1 模板支持版本管理
比如用户使用 v1.0.0 的模板创建了项目,半年后,已经迭代升级到了 v2.0.0。我们需要依旧能够找到 v1.0.0 版本,因为老用户不想或者不方便升级。
像我之前的雏形脚手架,将模板打一个压缩包放在云服务器上是不可行的,一旦更新就全量替换了
npm 仓库天然支持版本管理,因此将模板发布到 npm 上自然解决了这个问题 (非开源项目,可考虑自建仓库或者私有的仓库)
3.2 支持扩展新模板
比如我们一开始我们的脚手架支持 H5 的模板。
半年后,随着业务发展,需支持微信小程序的模板。
此时,我们无需额外再开发一个 cli,而是让 cli 一开始设计的就支持扩展,这符合了开放封闭的设计原则
3.3 自动检测版本更新
npm 提供了一些命令来检测包的版本,比如你 npm view react version 返回 16.9.0,告知你最新版本
借此,可以判断用户目前安装的是否最新版本,并提示用户更新
3.4 根据用户选择,生成个性化模板
模板虽说是为了统一,但也要在统一中支持差异,可通过问询用户,来提供差异化支持,比如:
这些问询的结果,将影响我们最终的模板,比如我们根据是否 TypeScript 会在两套预设的模板中选一个套,将用户输入的「项目介绍」插入 package.json 的 description 字段等等
3.5 友好的UI界面
合适的格式、颜色、字体、进图条等,给与用户良好的信息反馈
下文会介绍一些常用的库,来提供这些功能
3.6 构建功能独立,可因模板而异
我们通常使用 webpack 来构建/调试,对于不同的模板,构建流程存在较大差异,我们需要支持为不同的模板配置不同的构建
因此构建能力也被抽离成单独的 npm 包,模板中可指定其构建包
3.7 多人合作项目,能确保构建结果一致
因为存在多版本,我们需要约束,让所有项目的贡献者的产出是一致的
其核心原则就是:针对那些可能导致差异的因素,我们都收录到工程中,让 git 仓库记录,从而实现同样,因此,现在流行的脚手架,如 umi taro,都将 构建能力 local 化到本地工程中,后续会做详细阐明
4 脚手架的三类包
一个被实践检验,能够符合上述需求的脚手架架构,其实非常简单,首先我们拆分成三类 npm 包:
包 | 功能 | 安装位置 | 备注 |
---|---|---|---|
全局命令包 | 就像一个大脑,负责响应全局命令,并进行调度 | 全局包路径 | global 安装,提供全局命令 |
模板插件包 | 初始化工程所拷贝的模板 | 某个约定路径,如 ~/.maoda |
模板可随业务扩展 |
构建插件包 | 提供构建(webpack)能力 | 工程内 (目前主流脚手架都改用此方案) | 不同模板可使用同一构建包,也可不同 |
注:构建插件包,早期很多脚手架都把它放在工程外,比如放在全局,优势是多工程可复用一套 webpack 能力,但弊端也暴露出来,即在多人协同开发的项目中,由于构建插件包不在工程里没能被 git 仓库收录,导致一些不可预期的差异结果。
其调度关系如下:
5 全局命令包
前面说了一通理论,下面开始正式搭建
全局命令包的功能:负责接收全局命令,并调度。
比如我做的 cli 的模板 demo cli-tpl
npm i cli-tpl -g # 或 yarn global add cli-tpl