如何实现一个简单的Node.js脚手架

原因

在工作中,需要开发一个脚手架,用于给相关用户提供相关的开发便利性。

适合人群

对前端、Node操作有一定的了解,同时向了解脚手架开发过程或者需要自己实现一个脚手架的开发者。

目标

  1. 开发一个简单的脚手架,能够提供给用户进行安装。
  2. 能够输出相关提示。
  3. 对用户文件进行读写操作。
  4. 在脚手架中使用Shell脚本。

更多与用户交互和文件操作等进阶内容可以查看同系列第二篇:如何实现一个脚手架进阶版(Vue-cli v2.9学习篇)

步骤

开发脚手架

脚手架的开发最开始过程与普通的前端项目相同,需要一个入口文件command.js和配置文件package.json

与其他配置文件不同的是,你需要在command.js文件第一行增加如下声明:

#! /usr/bin/env node

同时需要在package.json文件中加上一下一项:

{
  ...,
  "bin": {
       "cm-cli": "command.js"
   }
}

在配置文件中增加了此项后,只需要在配置文件根目录下执行npm link命令,即可使用cm-cli --help命令来查看加载的cm-cli脚手架。

如果你发布了你的脚手架,那么在其他用户使用命令npm install -g cm-cli之后,便可以在全局下使用你的脚手架了。

对用户进行提示

在对注释和命令进行提示中,我们需要使用到commander包,使用npm install commander即可进行安装。(如果NPM版本低于5,则需要添加--save参数保证更新package.json配置文件)。

commander是一个提供用户命令行输入和参数解析的强大功能。有需要的可以阅读相关的库文档。在这里我介绍两个用的最多的方法。

option

能够初始化自定义的参数对象,设置关键字和描述,同时还可以设置读取用户输入的参数。具体用法如下:

const commander = require('commander');

commander.version('1.0.0')
    .option('-a, --aaa', 'aaaaa')
    .option('-b, --bbb', 'bbbbb')
    .option('-c, --ccc [name]', 'ccccc')
    .parse(process.argv);


if (commander.aaa) {
    console.log('aaa');
}

if (commander.bbb) {
    console.log('bbb');
}

if (commander.ccc) {
    console.log('ccc', commander.ccc);
}

具体展示如下:

command

该方法能够在命令行增加一个命令。用户在执行此命令后,能够执行回调中的逻辑。具体用法如下:

commander
    .command('init <extensionId>')
    .description('init extension project')
    .action((extensionId) => {
        console.log(`init Extension Project "${extensionId}"`);
        // todo something you need
    });

具体展示效果如下:

对用户文件进行读写操作

通过上面的步骤,我们已经能够完成一个简单的脚手架了。下面,我们需要读取用户配置,同时为用户生成一些模板文件。

读取文件

现在,我们需要读取用户的cm-cli.json配置文件来进行一些配置。

我们可以使用Node.js的fs文件模块来对文件进度读操作,由于此处没有太多难点,因此略去。

写入文件模板

我们提前将模板文件存储在CDN上,再根据本地读取到的相关脚手架配置文件来进行模板的下载。

注:脚手架中读取的路径为使用者使用时当前路径,因此没有办法将模板文件存储在脚手架中进行读取。

我们可以使用诸如request这种库来帮助我们进行文件下载,简化操作步骤。执行npm install request`即可进行安装。

注:在文件写入时建议先判断文件是否存在,再进行覆盖。

使用Shell脚本

与Node.js提供的API函数来看,有些人更加倾向于使用Shell脚本来进行文件操作。幸运的是,我们也可以在我们的脚手架中引入node-cmd来启用对Shell脚本的支持。执行npm install node-cmd即可进行安装。

具体示例如下:

commander
    .command('init <extensionId>')
    .description('init extension project')
    .action((extensionId) => {
        id = extensionId;
        console.log(`init Extension Project "${extensionId}"`);

        cmd.get(
            `
            mkdir -p static/${extensionId}

            mkdir tmp
            mkdir tmp/source-file
            mkdir tmp/build-file
            curl -o tmp/source-file/index.js https://xxxxxxxx.com?filename=index.js
            touch tmp/source-file/index.css

            curl -o tmp/build-file/server.js https://xxxxxxxx.com?filename=server.js
            curl -o tmp/build-file/router.js https://xxxxxxxx.com?filename=router.js
            curl -o tmp/build-file/package.json https://xxxxxxxx.com?filename=package.json
            
            cp  tmp/source-file/* static/${extensionId}
            cp tmp/build-file/* ./
            rm -fr tmp
            npm install
            `,
            (err, data) => {
                console.log(data)
                if (!err) {
                    console.log('init success');
                    return;
                }

                console.error('init error');
            });
    });

我们可以快速的使用Shell脚本来进行文件夹的创建和文件模板的下载。

总结

脚手架想要在终端能够快速执行,可以在package.json配置文件中增加相关字段。

脚手架需要能够读取相关终端输入,可以使用commander库来快速开发。

脚手架需要能够执行Shell脚本,可以使用node-cmd库来快速实现需求。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏LanceToBigData

JavaWeb(一)Servlet中乱码解决与转发和重定向的区别

前言   前面其实已经把Servlet中所有的内容都介绍完了,这篇讲补充一点乱码和重定向与转发之间的区别! 一、request请求参数出现乱码问题 1.1、ge...

337100
来自专栏python3

python3--基础综合练习题

允许用户最多尝试3次,3次都没猜对的话,就直接退出,如果猜对了,打印恭喜信息并退出

33830
来自专栏达摩兵的技术空间

你不知道的opn模块

opn模块通常是作为跨平台的打开文件或者网站的模块,在web应用中最常见的使用是比如项目开发或者启动的时候打开浏览器进行访问。

7310
来自专栏青玉伏案

设计模式(六):控制台中的“命令模式”(Command Pattern)

今天的博客中就来系统的整理一下“命令模式”。说到命令模式,我就想起了控制台(Console)中的命令。无论是Windows操作系统(cmd.exe)还是Linu...

22190
来自专栏大内老A

WCF服务端运行时架构体系详解[下篇]

作为WCF中一个核心概念,终结点在不同的语境中实际上指代不同的对象。站在服务描述的角度,我们所说的终结点实际上是指ServiceEndpoint对象。如果站在W...

21670
来自专栏逆向技术

框架原理第一讲,熟悉常用的设计方式.(以MFC框架讲解)

          框架原理第一讲,熟悉常用的设计方式.(以MFC框架讲解) 一丶什么是框架,以及框架的作用 什么是框架?   框架,简而言之就是把东西封装好了...

277110
来自专栏Java进阶

如何用zookeeper 实现分布式锁

326100
来自专栏IMWeb前端团队

Nodejs进阶:基于express+multer的文件上传

概览 图片上传是web开发中经常用到的功能,node社区在这方面也有了相对完善的支持。 常用的开源组件有multer、formidable等,借助这两个开源组件...

58690
来自专栏mySoul

微信小程序自定义组件(二)

两个<custom-ul>以及<custom-li>两个组件都为自定义组件,如果进行通信会非常的难以操作,至此通过relations完成子父组件的定义,简化通信...

32030
来自专栏木头编程 - moTzxx

微信小程序Ⅳ [js文件的外部引用]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

91320

扫码关注云+社区

领取腾讯云代金券