手持企业级脚手架15分钟
1写在前面的字
搭建脚手架考验了你的nodejs水平、工程能力以及工具和服务的设计能力,这是前端推进不可或缺的过程
在开发cli的过程中,作者研究了流行的cli并形成了最佳实践。本文的目的是在最短的空间内实现主要功能,揭示核心原理,提供演示仓库供大家学习和讨论。
阅读整篇文章大约需要10分钟,获得基于本教程的cli大约需要15分钟
2脚手架的雏形
事实上,脚手架的初衷是提供最佳实践的基本模板,因此模板复制是其核心功能
几年前,我写了一个极简主义的脚手架,我应该做这样的事情
当npm发布一个全局安装的包来执行命令时,wget是我的云服务中的一个压缩包,解压当前文件夹中的一个命令,可以创建我预设的完整项目目录,特别方便高效。
我觉得这应该算是一个原型脚手架
3需要考虑脚手架
上面的原型脚手架可以很好地服务于个人需求,但毕竟太干太粗糙,要想被大家广泛接受,还需要改进。
众所周知,vue-CLI create-react-app @ tarojs/cliumi最基本的功能如下:首先,提出一些问题选项列表,然后为您的新项目提供模板并安装依赖项,然后提供调试和构建命令
是的,核心部分就是这个想法;但是,如果您想使它具有可扩展性和用户友好性,您需要考虑以下要求:
模板支持版本管理,扩展新模板,自动检测版本更新,根据用户选择生成个性化模板。友好的UI界面在构建功能上是独立的,可以因模板而异(如区分H5/PC/weapp/RN)。多人合作项目可以确保一致的施工结果。看似信息量很大,其实并不晦涩。让我们一个一个解释意图。
3.1模板支持版本管理
比如用户用v1.0.0的模板创建项目,半年后已经迭代升级到v2.0.0,我们还需要能找到v1.0.0版本,因为老用户不想升级或者不方便升级。
就像我之前的原型支架一样,把模板放在云服务器上的压缩包里是不可行的。一旦更新,它将被完全替换
Npm仓库自然支持版本管理,所以向npm发布模板自然就解决了这个问题(对于非开源项目,可以考虑自建仓库或者私有仓库)
3.2支持扩展新模板
例如,当我们开始时,我们的脚手架支撑着H5的模板。
半年后,随着业务的发展,我们需要支持微信小程序的模板。
此时,我们不需要开发额外的cli,而是让cli从一开始就支持扩展,这符合开放和封闭的设计原则
3.3版本更新的自动检测
Npm提供一些命令来检测包的版本。例如,您的npm视图react版本返回16.9.0来通知您最新的版本
因此可以判断用户目前是否安装了最新版本,并提示用户更新。
3.4根据用户的选择,生成个性化模板
虽然模板是为了统一,但也要支持统一中的差异,通过询问用户提供差异化支持,比如:
这些查询的结果将影响我们的最终模板。比如根据TypeScript是否会选择两套预置模板中的一套,将用户输入的“项目介绍”插入package.json的description字段,以此类推
3.5友好的用户界面
适当的格式、颜色、字体、画线等。给用户良好的信息反馈
下面将介绍一些常用的库来提供这些功能
3.6建筑功能是独立的,可以因模板而异
我们通常使用webpack来构建/调试。对于不同的模板,构建过程有很大的不同,因此我们需要支持为不同的模板配置不同的构建
因此,构建能力也被提取到单独的npm包中,其构建包可以在模板中指定
3.7多人合作项目可确保一致的施工结果
因为有多个版本,我们需要约束来使所有项目贡献者的输出一致。它的核心原则是:对于那些可能导致差异的因素,我们将它们包含在项目中,让git仓库记录下来,从而达到相同。因此,流行的脚手架,如umi taro,将把建筑能力本地化为本地项目,这将在后面详细解释。
脚手架的四种包装
一个经过实践检验,能够满足上述要求的脚手架框架,其实很简单。首先,我们将其分为三种类型的npm包:
包功能安装位置备注全局命令包就像一个大脑,负责响应全局命令,调度全局包路径的全局安装,提供全局命令模板插件包初始化项目复制的模板的某个约定路径。例如,~/。maoda模板可以构建具有业务扩展的插件包,以提供webpack功能。在项目中(目前主流脚手架反而采用这种方案),不同的模板可以使用同一个构建包,也可以不同。注意:构建插件包,早期被很多脚手架放在项目外面,比如整体情况。优点是多个项目可以重用一组webpack功能,但缺点也暴露出来了,即在由多人开发的项目中,因为构建插件包不
调度关系如下:
5全球指挥包
我之前说过一个理论,我开始在下面正式构建它
全局命令包功能:负责全局命令的接收和调度。
例如,我制作了cli模板演示cli-tpl
在全局安装npm i cli-tpl -g#或纱线全局add cli-tpl后,会公开一个d cli命令(自行命名),该命令具有以下典型功能:
曝光全局命令由package.json中的bin指定,请参考我的演示
命令效果dcli install [pkgName]安装一个“模板插件包”到~/。茂达路。如果已经安装然后执行,请要求更新到最新版本,例如安装dcli install gen-tpl dcli init用模板初始化一个新项目。执行后,您将被要求从已安装的模板中选择dcli build,并在项目的根目录中执行它(或者将其写入项目的脚本中)。尝试阅读项目所依赖的“构建插件包”并执行dcli build,类似于DCLibuild,只是在调试5.1 cli的开发中,只有一些值得收集的第三方调味包。
重要性包名函数要求minimist解析用户命令,process.argv通过对象必要的fs-extra成为fs库的扩展,并支持promise必要的粉笔从console.log color制作您的单词。例如,成功时的绿色单词“import-from”类似于“require”,但它支持指定目录,以便您可以require.resolve项目目录。例如,如果全局包想要引用项目路径下的内容,就需要解析-如上所述,但这只是必须的。决心。询问者询问用户并记录反馈结果。接口交互的工件需要yeoman-environment [core]执行一个“模板插件包”,后面会详细描述。easy-table类似于console.table,Output漂亮的table锦上添花ora提供加载菊花锦上添花semver提供版本对比锦上添花figlet console.log给出漂亮的大logo锦上添花cross-产卵跨平台child _ process(cross-Windows/Mac)锦上添花osenv跨平台系统信息锦上添花打开跨平台开放app,比如在调试时打开chrome 5.2命令分析和分发
命令解析和分发是Global Command Package的核心功能,其流程相对简单。您也可以直接查看warehouse cli-tpl(所有函数都被压缩到大约300行代码)
Cli版本更新判断:
先获取这个package.json中的版本,然后通过npm view cli-tpl version命令查询当前npm库的最新版本,通过对比得出结论,提醒用户更新分析用户命令
获取用户通过process.argv[2]执行的实际命令,例如,dcli install可以获取install(官方版本建议使用minimist来分析参数)处理命令。
例如,install命令用于动态映射install.js文件来处理这个逻辑。注意:require支持动态名称,例如require('。/scripts/'命令)。如果命令是install,将映射并执行脚本/install.js文件。接下来,我们将看看接下来的四个核心命令,主要是:
Command effect install帮助用户安装/升级一个“模板插件包”init帮助用户初始化一个项目,并复制模板构建调用项目中的“构建插件包”,帮助用户在webpack中构建dev,帮助用户启动devServer进行调试。下面逐一介绍每个命令的实现过程和效果:
5.3安装命令:安装一个“模板插件包”
安装意味着将此模板插件包下载到硬盘上;在这里,我制作了一个演示包gen-tpl(稍后将详细分解),它具有最小的功能来帮助解释
dcli安装gen-TPL
核心处理流程如下:
首先判断gen-tpl包是否已经安装在硬盘缓存目录~/.maoda下。
如果没有,接下来安装它(相当于在~/中执行npm安装。maoda目录)。如果有,版本低,会提示升级。如果有,且版本最新,则不视为安装过程,即Execsync(' NPM I[Email Protected]-S ',{CWD :' ~/)。maoda'})
我们可以为“模板插件包”的名称制定一个约定,也就是说,它有一个固定的前缀,比如gen-xxx
5.4 init命令:选择“模板插件包”来初始化一个新项目
这是脚手架的高频核心功能
dcli init
此时,脚本/init.js文件将被分发以供执行。让我们看看它的逻辑
查询硬盘缓存目录下的package.json文件~/。maoda,读取其中的依赖项字段,并获得已安装的“模板插件包”
如果没有安装,系统会提示用户首先安装,并让用户选择一组模板
使用inquery库启动对话并列出已安装的模板供用户选择。例如,上图中的gen-pc gen-h5 gen-tpl会触发模板初始化过程
例如,如果用户选择了模板gen-tpl,那么库yeoman-environment将用于执行缓存目录~/中的包。maoda/gen-tpl/index.js注意:这相当于两个js文件的跨目录引用执行。当执行前面提到的库导入的“模板插件包”时,开始正常的模板复制过程(稍后详述)
这里,包名直接用作选项。为了让演示更直观,通常会将包的描述作为选项,这样更友好。例如,gen-pc包可以被描述为生成pc模板
5.5构建命令:在项目中执行构建
dcli大楼
确定项目目录
项目目录是执行目录,用于读取项目的构建插件是通过process.cwd()获得的
阅读项目中同意的配置文件。在这个演示中,对于maoda.js(使用约定的配置,类似于web pack . config . js . babe LRC . pretierrc),读取maoda.js中的构建器配置项(即指定的构建插件包)。例如,如果在本演示中将它指定为build-tpl,则读取自定义webpack配置(该配置被认为是webpackCustom字段,稍后将被合并/覆盖为默认webpack配置)并使用内置插件包来打包webpack
判断是否已经安装了build-tpl,执行npm install(或者说纱添加,这里有一个小技巧,根据用户项目中锁文件的类型判断是否安装了用户使用的npm或者纱,然后直接执行build-tpl。通常我们用配置文件来表示“构建插件包”,也可以直接在命令中表示,比如dcli build-builder=后者往往适合一组代码来封装各种结果,比如JD。COM的芋头cli
通常大家都习惯npm运行build纱build,只需在我们的模板中添加一行:到package.json即可。
{ ' script ' : { ' build ' : ' dclibuild ' } } 5.6 dev命令:启动devServer进行调试
类似于build,但是webpack的配置不同,这里省略
6模板插件包
核心功能:提供模板文件夹的副本。这里还有一个项目gen-tpl的示例(只有50行代码)
处理过程如下:
询问用户并获得反馈答案
比如项目名称是什么,描述你的项目,是否使用TypeScript,是否使用Sass/Less/Stylus等。根据用户的回答,复制相应的模板,再细分两份
直接复制:将模板插件包中的文件夹/文件直接复制到用户项目目录中填写模板副本,将用户的答案填充到文档的相应位置,类似于WebpackHTMLPlugin和ejs。例如,将name: %=packageName%填入name:我的项目在项目中执行与npm相关的安装。
【重点来了】好像流程还挺多的。事实上,只需一个现成的轮子,即yeoman-generator就可以完成,它可以帮助我们打包所有这些过程。我们只需要继承基类,编写几个预置的生命周期函数,没头没脑,惨不忍睹(详情请参考模板仓库)
module.exports=类扩展生成器{//[查询会话]prompt(){返回this.prompt ([{type:' input ',name:' appname ',Message: '请输入项目名称:',},{type:' list ',选项3360 ['JavaScript ',' typescript'],name:' language ',message: '请选择项目语言',Default: ' typescript ',},然后(回答={这个。answers=answers })}//[模板副本]写入(){//从模板路径复制到工程路径this.fs.copy(this.templatePath())、this . destinationpath())}/[安装依赖项]install(){ this . install dependencies()} end(){ this . log(' happy coding!')}}显然,“模板插件包”导出了一个类,我们需要通过上面提到的“全局命令包”中的yeoman-environment来启动:
//[节选自全局命令包的init命令,略有修改以提高可读性] yoemanev。注册(解析自('。/maoda ',' gen-TPL '),' gen-TPL') yoemanev。运行(' gen-TPL ',(e,D)={dthis。控制台(' happy coding ',' green')})这里,上面提到的resolve-from包也用于跨目录引用解析
Yeoman是一个比较完善的生态,模板插件包可以通过yeoman提供的全局命令yo来创建,但不是必须的,这里就不展开了。
7构建插件包
同样,我们提供了一个构建插件包的模板build-tpl (20行代码,从webpack开始)。webpack配置是空的,您可以在开发过程中自行定制
实际上,构建插件包的核心是webpack能力,这里就不展开了。在这里,我们将只描述呼叫关系。以dcli构建为例,“全局命令包”在收到构建命令后启动“构建插件包”
从(流程)导入。CWD(),‘构建第三方物流’)是的,就这么简单。从库中导入可以使用跨文件目录的特定目录来指定文件。使全局包直接执行项目目录的包效果,与同一项目下的require('build-tpl ')相同
您也可以在这里使用导入cwd库
而build-tpl,一个构建插件包,负责将内置的webpack.config.js与用户工程下定制的webpackCustom合并,然后执行webpack流程
当然,构建工具不必使用webpack,例如,在构建Taro这样的小程序代码时,可以选择rollup或者自己创建一组工具
8写在最后的话
作者认为,只有足够简洁,才能降低入门门槛,强化记忆;因此,本文的案例在成熟的脚手架上不断被删除,这些部分增加了内存负担,只保留了本质和核心,旨在快速在脑海中建模一个企业级脚手架,并提供一个包含脚手架三个组件的仓库/npm包,以增加可操作性。如果我们需要引用并实际开发,我们需要继续丰富它的血肉,包括但不限于:
异常处理(如某些边界条件)webpack配置需要改进(本演示中的webpack.config为空)。UI和推广语言可以更友好。根据业务需求,可以扩展附加命令,如卸载包和发布cdn文章。博客地址:https://github.com/imaoda/js-front-end-practice欢迎批评和指正。
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。
版权声明:手持企业级脚手架15分钟是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。