热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何开发一款前端工具

来源|https:juejin.cnpost6899446879487180808作者|隐冬基本上,使用任何成熟的语言都可以开发cli工具,作为一个前端

来源 | https://juejin.cn/post/6899446879487180808

作者 | 隐冬

基本上,使用任何成熟的语言都可以开发 cli 工具,作为一个前端小白,还是 Javascript 比较顺手,因此我们选用nodejs作为开发语言,开发一款node-cli工具。

类似于脚手架工具,Node工具会自动去询问你一些预设的问题,然后将你回答的结果结合一些模板文件,给你生成一个项目结构。

那接下来我们以一个小型的脚手架工具为例,通过Nodejs完成一个Node工具,再来去深入体会一下Node工具的工作过程。

那我们知道脚手架工具实际上就是一个node-cli应用,那创建脚手架就是创建一个node-cli应用,那这里我们具体来操作一下,我们首先进入到命令行,通过mkdir去创建一个工具目录。

mkdir samlpe-clicd sample-cli

在这个目录下面我们通过yarn init 方式去初始化一个package.json文件

yarn init

有了这个文件之后通过编辑器打开这个目录,紧接着我们需要在package.json中添加一个bin字段,用于去指定一下我们cli应用的入口文件, 我们这里叫cli.js

{ "name": "sample-cli", "bin": "cli.js", ...}

再然后我们添加这个cli.js文件,跟以往我们在Node中书写的文件有所不同,cli的入口文件必须要有一个特定的文件头, 也就是在这个文件顶部写上这样一句话 #! /usr/bin/env node 我们在这个文件中console.log一句话。

#! /usr/bin/env node
console.log('cli working')

如果说你的操作系统是linux或者mac系统你还还需要去修改这个文件的读写权限,把他修改成755,这样才可以作为一个cli的入口文件。

我们回到命令行,我们通过yarn link 将这个模块映射到全局

yarn link

这时候我们就可以在命令行使用sample这样一个命令, 通过执行这个命令我们的console.log成功打印出来,表示代码执行了。也就意味着我们这个cli基础就已经ok了。

sample-cli

接下来我们实现一下脚手架的具体业务,也就是我们脚手架的工作过程。

首先我们需要通过命令行交互的的方式去询问用户的一些信息,然后紧接着呢根据用户反馈回来的结果我们去生成文件,

  1. 通过命令行交互的方式询问用户信息

  2. 根据用户反馈回来的结果生成文件

在Node当中去发起命令行交互询问我们使用inquirer这样一个模块,那我们需要通过npm安装一下这个模块,我这里使用yarn,安装在依赖文件当中。

yarn add inquirer --dev

那有了这个模块过后就可以在代码中去载入, inquirer这个模块提供一个叫做prompt的方法用于发起一个命令行的询问。

他可以接收一个数组参数,数组中每一个成员就是一个问题,可以通过type指定问题输入方式,然后name指定返回值的键,message去指定屏幕上给用户的一个提示,在promise的then里面拿到这个问题接收到用户的答案。

我们这里不着急往下写,我们先通过console.log去打印一下。

const inquirer = require('inquirer');
inquirer.prompt([ { type: 'input', name: 'name', message: 'Project name' }]).then(answer => { console.log(answer);})

回到控制台,我们命令行执行sample-cli, 此时就会提示我们需要输入项目的名称。

sample-cli

这样就可以看到问题和返回的结果。这也就证明inquirer确实可以帮我们发起命令行交互询问。

那有了inquirer之后接下来我们要考虑的就是动态的去生成我们的项目文件。

我们一般会根据模板去生成,所以我们在项目的跟目录下新建一个templates目录,在这个目录下我们去新建一些模板。

由于我们这里是讨论脚手架的工作过程&#xff0c;所以我们也不去关心模板里面有什么&#xff0c;我们就随便写点什么。我们可以通过 <%%>去替换询问过程中得到的答案。

index.html


我们还可以添加一些其他的模板文件&#xff0c;比如style.css

style.css

body { margin: 0; background-color: red;}

回到cli.js文件, 这时候我们可以在得到问题答案的位置&#xff0c;根据用户回答的问题去生成文件。不过在生成前我们一般会先将模板路径和目标目录确定下来。

模板的目录应该是项目当前目录的templates&#xff0c;我们可以通过path获取。

const path &#61; require(&#39;path&#39;);
// 工具当前目录const tmplDir &#61; path.join(__dirname, &#39;templates&#39;);

输出的目标目录一般是我们命令行在哪个目录去执行就应该是哪个路径&#xff0c;也就是cwd目录

const path &#61; require(&#39;path&#39;);
// 工具当前目录const tmplDir &#61; path.join(__dirname, &#39;templates&#39;);// 命令行所在目录const destDir &#61; process.cwd();

明确这两个目录&#xff0c;我们就可以通过fs模块去读取一下模板目录下一共有哪些文件。把这些文件全部输入到我们的目标目录&#xff0c;我们通过fs的readDir方法&#xff0c;这个方法会自动扫描目录下的所有文件

fs.readdir(tmplDir, (err, files) &#61;> { if (err) { throw err; } files.forEach(file &#61;> { console.log(file); // 得到每个文件的相对路径 })})

我们可以通过模板引擎去渲染路径对应的文件&#xff0c;先去安装一款模板引擎&#xff0c;这里我们使用ejs

yarn add ejs --dev

安装过后&#xff0c;回到代码中引入这个模板引擎, 通过模板引擎提供的renderFile去渲染这个路径对应的文件。

第一个参数是文件的绝对路径&#xff0c;第二个参数是模板引擎在工作的时候的数据上下文&#xff0c;第三个参数是回调函数&#xff0c;也就是我们在渲染成功过后的回调函数&#xff0c;当然如果你在渲染过程中出现了意外那你可以通过throw err的方式把这个错误抛出去。

我们可以先把result通过打印的方式打印出来看一下。

const fs &#61; require(&#39;fs&#39;);const path &#61; require(&#39;path&#39;);const inquirer &#61; require(&#39;inquirer&#39;);const ejs &#61; require(&#39;ejs&#39;);
// 工具当前目录const tmplDir &#61; path.join(__dirname, &#39;templates&#39;);// 命令行所在目录const destDir &#61; process.cwd();
inquirer.prompt([ { type: &#39;input&#39;, name: &#39;name&#39;, message: &#39;Project name&#39; }]).then(answer &#61;> { fs.readdir(tmplDir, (err, files) &#61;> { if (err) { throw err; } files.forEach(file &#61;> { ejs.renderFile(path.join(tmplDir, file), answer, (err, result) &#61;> { if (err) { throw err; } console.log(result); }) }) })})

编辑完成之后我们运行一下脚手架工具。

sample-cli

此时打印出来的这个结果其实是已经经过模板引擎工作过后的结果&#xff0c;我们只需要将这个结果通过文件写入的方式写入到目标目录就可以了&#xff0c;那目标目录应该是通过path.join把我们destDir以及我们的file做一个拼接。内容就是我们这里的result。

files.forEach(file &#61;> { ejs.renderFile(path.join(tmplDir, file), answer, (err, result) &#61;> { if (err) { throw err; } fs.writeFileSync(path.join(destDir, file), result); })})

完成过后我们找到一个新的目录&#xff0c;使用一下这个脚手架

sample-cli

我们输入项目名称过后&#xff0c;就会发现他会自动把我们模板里面的文件自动生成到对应的目录里面&#xff0c;至此我们就已经完成了一个非常简单&#xff0c;非常小型的一个脚手架应用。

那我们也回顾了一下脚手架的工作过程&#xff0c;其实脚手架的工作原理并不复杂&#xff0c;但是他的意义却是很大的&#xff0c;因为他确实在创建项目环节大大提高了我们的效率。

我们可以将自己的工具发布至npm上&#xff0c;提供给更多的人使用。

至于发布npm也非常的简单&#xff0c;首先我们需要注册npm账号&#xff0c;有两种方式可以注册&#xff0c;一种是登录npm官网https://www.npmjs.com/, 另一种是使用命令npm adduser。

npm adduser

会提示你输入用户名&#xff0c;密码&#xff0c;以及邮箱。

注册好后登录npm账号。

npm login

依次输入第二步中第一种方法注册的用户名、密码和邮箱。

登录成功后执行npm发布命令。

npm publish

注意&#xff1a;如果报错&#xff1a;&#39;You do not have permission to publish "samlpe-cli". Are you logged in as the correct user?&#39;

表示包samlpe-cli名字已经在包管理器已经存在被别人用了&#xff0c;需要更该包名称&#xff0c;我们可以前往package.json中的name中换一个名字。

{ "name": "sample-cli1", "version": "1.0.0", "bin": "cli.js", ...}

再次执行publish命令。出现 &#43;sample-cli1&#64;1.0.0即表示发布成功。

如果发布时报错&#xff1a;no_perms Private mode enable, only admin can publish this module:

表示当前不是原始镜像&#xff0c;要切换回原始的npm镜像

npm config set registry https://registry.npmjs.org/

至此你的node工具就可以提供给其他人使用了。

如果需要更新你的工具&#xff0c;只要继续执行npm publish就可以更新发布了&#xff0c;不过需要注意&#xff0c;每次发布都需要修改版本号version的值&#xff0c;同一个版本不允许发布两次。

{ "name": "sample-cli1", "version": "1.0.1", "bin": "cli.js", ...}

如果想要撤销本次发布可以执行

npm unpublish

不过需要注意&#xff0c;只有在发包的24小时内才允许撤销发布的包&#xff0c;超过24小时&#xff0c;就无法撤回了。

本文完〜


推荐阅读
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
author-avatar
手机用户2502869943
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有