使用Caporal.js创建自己的约曼风格脚手架工具
开始一个新项目(尤其是作为JavaScript开发人员)通常是一个重复而乏味的过程。对于每个新项目,我们通常需要添加一个package.json
文件,引入一些标准依赖项,配置它们,创建正确的目录结构,添加各种其他文件……
但我们是懒惰的开发者,对吧?幸运的是,我们可以自动化这个过程。它不需要任何特殊的工具或奇怪的语言——如果你已经知道JavaScript,这个过程实际上非常简单。
在本教程中,我们将使用Node.js构建一个跨平台命令行界面(CLI)。这将允许我们使用一组预定义的模板快速搭建出一个新项目。它将是完全可扩展的,因此您可以很容易地根据自己的需要进行调整,并自动消除工作流程中繁琐的部分。
为什么要自己卷?
尽管有很多类似的工具可以完成这个任务(例如自由民),通过建立我们自己的,我们获得知识,经验,并可以使它完全定制。您应该始终考虑创建自己的工具而不是使用现有工具的想法,特别是当您试图解决专门的问题时。这听起来可能与总是重用软件的惯例相反,但在某些情况下,实现您自己的工具可能是非常有益的。获取知识总是有帮助的,但你也可以提出高度个性化和高效的工具,特别适合你的需要。
话虽如此,我们不会完全重新发明轮子。CLI本身将使用一个名为Caporal.js.在内部它也将使用提示要求用户数据和shellJS它将在我们的Node.js环境中为我们提供一些Unix工具。我选择这些库主要是因为它们易于使用,但是在完成本教程之后,您将能够将它们替换为最适合您需求的替代品。
与以往一样,你可以在Github上找到完成的项目:https://github.com/必威西盟体育网页登录sitepoint-editors/node-scaffolding-tool
现在让我们开始吧……
使用Caporal.js启动并运行
首先,在计算机上的某个地方创建一个新目录。建议为该项目创建一个专用目录,该目录可以长时间保持不变,因为每次都会从该目录调用最后的命令。
进入目录后,创建一个package.json
文件内容如下:
{“名称”:“脚手架”,“版本”:“1.0.0”,“主要”:“index.js”,“本”:{“脚手架”:“index.js”},“依赖”:{“伍长烟草”:“^ 0.3.0”,“颜色”:“^ 1.1.2”,“提示”:“^ 1.0.0”,“shelljs”:“^ 0.7.7”}}
这已经包括了我们需要的一切。现在要执行安装包npm安装
所有标记的依赖项都将在我们的项目中可用。这些包的版本是撰写本文时的最新版本。如果在此期间有新的版本可用,您可以考虑更新它们(注意任何API更改)。
注意脚手架
价值箱子
.它指示了我们的命令的名称,以及每次我们在终端中输入该命令时将要调用的文件(index.js
).您可以根据需要随意更改这个值。
建立入口点
CLI的第一个组件是index.js
文件,其中包含命令列表,选项和各自的函数,将提供给我们。但是在编写这个文件之前,让我们先更详细地定义我们的CLI要做什么。
- 主要的(也是唯一的)命令是
创建
,它允许我们创建我们选择的项目样板。 - 的
创建
命令采用强制的模板
参数,它指示我们要使用哪个模板。 - 它还需要
——变体
选项,该选项允许我们选择模板的特定变体。 - 如果没有提供特定的变量,它将使用默认的变量(我们将在后面定义)。
js允许我们以一种紧凑的方式定义上面的内容。让我们将以下内容添加到我们的index.js
文件:
#!/usr/箱子/env节点常量掠夺=需要(“伍长烟草”);掠夺.版本(“1.0.0”).命令(“创建”,“创建新应用程序”).论点(“模板> <”,“要使用的模板”).选项(“< >变体——变体”,'哪个<变量>的模板将被创建').行动((arg游戏,选项,日志记录器)= >{控制台.日志({arg游戏:arg游戏,选项:选项});});掠夺.解析(过程.argv);
第一行是a工作以表明这是一个Node.js可执行文件。
这里包含的shebang只适用于类unix系统。Windows不支持shebang,所以如果你想直接在Windows上执行文件,你必须寻找一个解决方案。通过npm运行命令(在本节末尾解释)可以在所有平台上运行。
接下来,我们将包含Caporal.js
包作为掠夺
然后开始定义程序。使用命令功能,我们定义创建
命令作为第一个参数,第二个参数是一些描述。这将显示在我们的CLI自动生成的帮助选项中(使用——帮助
).
然后,我们把模板
参数中的参数函数,因为它是必选参数,所以我们将它括在尖括号内(<
而且>
).
我们可以这样定义变量选项——> <变体变体
在选择功能.这意味着调用命令的选项——变体
该值将存储在变体
变量。
最后,在操作命令我们传递另一个函数来处理当前命令。这个回调函数有三个参数:
- 传递的参数(
arg游戏
) - 传递的选项(
选项
) - 在屏幕上显示内容的实用程序对象(
日志记录器
).
现在,我们将登出传递的参数和选项的值,这样我们就可以了解如何从CLI获取执行操作所需的信息。
对象的最后一行传递信息脚手架
命令到Caporal.js解析器,它将完成繁重的工作。
使CLI全局可用
现在可以测试应用程序,看看是否一切都按计划进行。要做到这一点,我们需要让它对我们的系统使用全局可用Npm的link命令.从项目根目录执行以下命令:
npm链接
流程完成后,我们就可以执行了脚手架
在我们终端的任何目录中,而无需显式引用index.js
文件:
脚手架创建节点—变体MVC
你会得到这样的回复:
{参数:{模板:“节点”}选项:{变体:mvc的}}
这是我们接下来将使用的从模板创建项目的信息示例。
构建模板
我们的模板将由文件和目录结构组成,我们需要启动和运行特定类型的项目。每个模板都有一个package.json
文件中有一些占位符值,我们可以用实际数据填充。
首先,创建一个模板
目录和一个节点
目录在里面。在节点
目录,创建一个默认的
目录(如果我们不提供变体
选项)和第二个名为mvc
来创建一个Node.js项目MVC体系结构).
最终的结构应该是这样的:
.├──模板├──node├──default├──MVC
现在我们需要填充默认的
而且mvc
文件夹的项目文件。方法中提供的方法,也可以自己创建样例应用程序.
接下来,我们可以继续在需要动态值的地方放置变量标识符。每个模板文件夹都应该包含一个package.json
文件。打开这些文件,用大写字母(没有空格)和方括号包括所有变量。
这是package.json文件在我们的默认模板:
{“名称”:“[名字]”,“版本”:“版本”,“描述”:“[描述]”,“主要”:“server.js”,“脚本”:{“测试”:"echo \"错误:没有指定测试\" && exit 1",“开始”:“节点server.js”,“开始:开发”:“nodemon server.js”},“作者”:“(作者)”,“许可证”:“许可证”,“依赖”:{“dotenv”:“^ 2.0.0”,“哈皮神”:“^ 16.1.0”,“隐谷”:“^ 4.1.0”},“devDependencies”:{“nodemon”:“^ 1.11.0”}}
创建所有变量后,将它们放入_variables.js
在相同的模板目录下,像这样:
/* *变量替换* -------------------- *它们在这里出现时被询问给用户。用户输入将替换模板文件中的占位符值*/模块.出口=[“名字”,“版本”,“描述”,“作者”,“许可证”];
导出的数组中的名称在文件中是相同的,但是是小写的,并且没有方括号。我们将使用这个文件在CLI中请求每个值。
现在我们可以继续构建函数创建
命令,将做所有的工作。
创建“Create”函数
在我们的index.js
文件,我们之前传递了一个简单的函数行动()
用于记录CLI接收到的值。现在,我们将用一个新函数替换该函数,该函数将把模板文件复制到脚手架
命令执行成功。我们还将用通过用户输入获得的值替换占位符变量。
在一个自由
目录(以便保持内容有条理),添加一个create.js
文件并放入以下内容:
模块.出口=(arg游戏,选项,日志记录器)= >{};
我们将把应用程序的所有逻辑都放在这个函数中,这意味着我们需要改变我们的index.js
相应的文件:
#!/usr/箱子/env节点常量掠夺=需要(“伍长烟草”);常量createCmd=需要(“。/ lib /创建”);掠夺.版本(“1.0.0”).命令(“创建”,“创建新应用程序”).论点(“模板> <”,“要使用的模板”).选项(“< >变体——变体”,'哪个<变量>的模板将被创建').行动(createCmd);掠夺.解析(过程.argv);
导入依赖项和设置变量
现在回到create.js
文件,我们可以将以下内容放在文件的开头,以使所需的包可用:
常量提示=需要(“提示”);常量壳牌=需要(“shelljs”);常量fs=需要(“fs”);常量颜色=需要(“颜色/安全”);//将提示设置为绿色,并使用“Replace”文本提示.消息=颜色.绿色(“替换”);
注意定制设置提示消息。这完全是可选的。
在导出函数中,我们要添加的第一件事是一些变量:
常量变体=选项.变体||“默认”;常量templatePath=`$ {__dirname}/ / . . /模板$ {arg游戏.模板}/$ {变体}`;常量localPath=过程.慢性消耗病();
如你所见,我们正在抓变体
选项传递给脚手架
命令并将其设置为“默认”
如果省略此选项。的变量templatePath
包含指定模板和的完整路径localPath
包含对执行命令所在目录的引用。
复制模板文件
方法复制文件的过程非常简单cp函数从shellJS
.在我们刚刚包含的变量下面,添加以下变量:
如果(fs.existsSync(templatePath)){日志记录器.信息(“复制文件…”);壳牌.cp(“- r”,`$ {templatePath}/*`,localPath);日志记录器.信息(文件已经被复制了!);}其他的{日志记录器.错误(`所请求的模板$ {arg游戏.模板}还没有被发现。`)过程.退出(1);}
首先,我们确保模板存在,如果不存在,我们将使用logger.error ()
函数from Caporal.js如果模板存在,我们将使用显示通知消息logger.info ()
我们将使用shell.cp ()
.的- r
选项指示它应该复制文件递归地从模板路径到执行命令的路径。文件复制完成后,我们将显示一条确认消息。因为shellJS函数是同步的,我们不需要使用回调、承诺或类似的东西——我们只需要以过程化的方式编写代码。
替换变量
虽然替换文件中的变量听起来是一件复杂的事情,但如果我们使用正确的工具,它是相当简单的。其中一个是经典的sed来自Unix系统的编辑器,可以动态转换文本。ShellJS为我们提供了这个实用程序它可以在Unix系统(Linux和MacOS)以及Windows上运行。
要完成所有替换,在文件中添加以下代码段,位于我们之前创建的代码的下面:
常量变量=需要(`$ {templatePath}/ _variables`);如果(fs.existsSync(`$ {localPath}/ _variables.js`)){壳牌.rm(`$ {localPath}/ _variables.js`);}日志记录器.信息(“请填写以下值……”);//请求变量值提示.开始().得到(变量,(犯错,结果)= >{//如果选择了其他MIT License文件,则删除MIT License文件//如果你使用了自己的模板,就省略这段代码如果(结果.许可证= = !“麻省理工学院”){壳牌.rm(`$ {localPath}/许可证`);}//替换所有文件中的变量值壳牌.ls(“rl”,“。”).forEach(条目= >{如果(条目.isFile()){//将'[VARIABLE] '替换为提示符中相应的变量值变量.forEach(变量= >{壳牌.sed(“我”,`\ \ [$ {变量.包含()}\ \]`,结果[变量],条目.的名字);});//在文件中插入当前年份壳牌.sed(“我”,“\ \[年\ \]”,新日期().getFullYear(),条目.的名字);}});日志记录器.信息(“✔成功!”);});
我们从阅读,和开始变量
设置为模板的内容_variables.js
我们之前创建的文件。
然后,因为我们已经从模板中复制了所有文件,所以第一个如果
语句将删除_variables.js
文件从我们的本地目录,因为它只需要在CLI本身。
方法获取每个变量的值提示工具,将变量数组传递给get ()
函数。通过这种方式,CLI将询问数组中每个项的值,并将结果保存在名为结果
它被传递给回调函数。该对象将每个变量作为键,将输入的文本作为值。
下一个如果
语句只在使用存储库中包含的模板时才需要,因为我们还包括一个LICENSE文件。尽管如此,看看如何为每个变量检索值是有用的,在本例中,从许可证
财产的使用result.license
.如果用户输入的license不是麻省理工学院
,然后删除许可证
文件从目录中删除rm ()
函数的ShellJS。
现在我们进入了有趣的部分。通过使用ls函数从ShellJS中,我们可以得到当前目录中所有文件的列表(.
),我们将替换变量。我们传递给它rl
选项,所以它变成递归,返回a文件对象而不是文件名。
使用循环遍历文件对象列表forEach ()
对于每一个,我们检查是否正在接收文件使用isFile ()
函数。如果我们得到一个目录,我们什么都不做。
然后,对于我们得到的每个文件,我们循环所有变量并执行sed
函数如下:
壳牌.sed(“我”,`\ \ [$ {变量.包含()}\ \]`,结果[变量],条目.的名字);
这里我们正在经过-我
选项,该选项允许我们替换文本,然后传递一个正则表达式字符串,该字符串将匹配变量
标识符,大写,并用方括号括起([
而且]
).然后,该正则表达式的每个匹配都将被相应变量的值(结果(变量)
),最后传递要替换的文件名称forEach ()
函数(entry.name
).
第二个sed
是完全可选的。这个只是用来替换的(年)
本年发生的事件。有用的许可证
或README.md
文件。
就是这样!现在我们可以在空目录中再次执行命令,看看它如何生成一个项目结构,并用新值替换所有变量:
//生成一个node .js MVC项目脚手架create node——variable MVC //生成一个默认的node .js项目脚手架create node
在执行命令之后,它应该开始询问变量的值,一旦过程完成,它将显示一条成功消息。要检查一切是否如预期的那样进行,打开一个包含变量的文件,您应该看到在CLI过程中输入的文本,而不是大写的标识符。
如果您使用了[the repo](https://github.com/sitepoint-editors/node-scaff必威西盟体育网页登录olding-tool)中的模板
),您还应该生成了工作的Node项目,可以通过运行来启动npm安装
紧随其后的是npm开始
.
接下来做什么
我们已经成功地创建了一个CLI工具,可以从模板中创建新的Node.js项目,但我们不必在这里停止。因为我们从头开始构建我们的工具,所以我们对它能做什么有绝对的自由。你可以以以下的想法为灵感:
- 扩展变量以替换代码块,而不是简单的单词;中可以使用更复杂的正则表达式和捕获组
sed
函数来实现这一点。 - 添加更多命令来为每种项目创建特定的文件,比如为MVC模板创建新模型。
- 包括将项目部署到服务器的命令,这可以通过使用rsync库和通过SSH的远程命令来实现。
- 如果您有一个复杂的设置,您还可以尝试添加命令来构建静态资产或源文件,这在静态站点的情况下可能很有用。
- 使用
mv
函数从变量名重命名文件。
结论
在本教程中,我演示了如何构建CLI,以便在熟悉的环境中快速启动新项目。但这不是一个单一用途的项目-您可以根据需要扩展它。自动化工具的创建是开发人员的特点。如果你发现自己在做重复的工作,停下来想想是否可以把它自动化。大多数情况下,这是可能的,而且长期的好处是巨大的。
现在轮到你了?你喜欢把重复性和乏味的工作自动化吗?您选择的工具包是什么?请在下面的评论中告诉我。
本文由琼阴,卡米洛·雷耶斯和蒂姆Severien.感谢所有SitePoint的同行审必威西盟体育网页登录稿人,让SitePoint的内容成为最好的!