博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Node Cli 入门
阅读量:6973 次
发布时间:2019-06-27

本文共 3989 字,大约阅读时间需要 13 分钟。

第一行代码

命令行上简单的输入一行代码,然后马上就建立了一个模板工程,这种方式想想都会觉得很酷。例如使用vue-cli工具的vue命令可以创建一个高配的模板工程。作为第一行代码我们就先不玩那么高深的,就来个hello world

我们可以新建一个项目目录叫做test,然后进入该目录下npm init一路执行回车,最后在项目目录下新建一个bin文件夹,创建一个hello.js文件,然后写上:

#!/usr/bin/env nodeconsole.log("hello world");

修改package.json文件:

{  "name": "test",   "bin": {    "test": "bin/hello.js"  }}

然后执行 npm link 命令:

$ npm link...C:\Users\Administrator\AppData\Roaming\npm\test -> C:\Users\Administrator\AppData\Roaming\npm\node_modules\test\bin\hello.jsC:\Users\Administrator\AppData\Roaming\npm\node_modules\test -> E:\github-code\test

命令行执行test,会打印出:hello world。

node 全局路径

我们的hello world程序跑完了,这里重点聊聊两个问题:

  • #!/usr/bin/env node在这里有什么作用?

  • npm link 到底在这里有什么作用?

要理解这两个问题,首先我们要知道操作系统中都会有一个 PATH 环境变量,当系统调用一个命令的时候,就会在PATH变量中注册的路径中寻找,如果注册的路径中有就调用,否则就提示命令没找到。我们可以通过process.env获取本机系统中所有的环境变量。

对于模块的载入及缓存机制可以分为以下几中情况:

  • 载入内置模块(A Core Module)

  • 载入文件模块(A File Module)

  • 载入文件目录模块(A Folder Module)

  • 载入node_modules里的模块

  • 自动缓存已载入模块

这里我们重点关注的是载入node_modules里的模块。如果模块名不是路径,也不是内置模块,Node将试图去当前目录的node_modules文件夹里搜索。如果当前目录的node_modules里没有找到,Node会从父目录的node_modules里搜索,这样递归下去直到根目录。

我们通过全局命令安装的模块会保存在全局目录下,如:

npm install -g vue-cli

我们可以在{prefix}/node_modules目录下找到vue-cli文件夹,这个就包含了vue-cli的包。

对于不同的系统,{prefix}值不同,这里我们可以使用npm prefix命令获取:

npm prefix -g

当然我们也可以通过命令的get和set方法操作这个路径。

那么再去理解上面的两个问题就简单了,#!/usr/bin/env node主要是帮助脚本找到node的脚本解释器。npm link的作用相当于是将我们的工程进行了全局安装,但是不同的是我们可以在命令行进行使用package.json文件中bin字段下的命令。如上面的test工程通过 npm link,这一步可以将本地目录安装到模块全局目录{prefix}/node_modules下,并且会在{prefix}文件夹下生成test文件和test.cmd文件。另外最关键的时候会建立链接,当本地目录如test文件夹变动,全局模块目录下的test文件夹也会相应改变,在其他目录下调用test命令同样可以找到命令。

同样我们可以通过下面的命令卸载模块:

npm uninstall -g test

处理命令行参数

node process对象一个提供有关当前Node.js进程的信息和控制的全局对象,在node环境下无需通过require()即可调用。

process.argv属性返回一个数组,其中包含启动Node.js进程时传递的命令行参数。第一个元素是process.execPath, 如果需要访问argv [0]的原始值,可以使用process.argv0,第二个元素将是要执行的JavaScript文件的路径, 其余元素将是任何其他命令行参数。

#!/usr/bin/env nodeconsole.log('call %s', process.argv[2]);

然后输入test hello,打印出call hello

对于命令行参数处理,我们一般用现成的模块commander或yargs处理,提供了用户命令行输入和参数解析强大功能。这里我们就使用轻量级,表达力强大的commander进行处理。

官网:

安装:

npm install --save commander

commander 特性:

  • 自记录代码

  • 自动生成帮助

  • 合并短参数(“ABC”==“-A-B-C”)

  • 默认选项

  • 强制选项​​

  • 命令解析

  • 提示符

commander API:

  • —— 暴露Command对象

  • —— 暴露Option对象

  • —— 初始化自定义参数对象,设置“关键字”和“描述”

  • —— 初始化命令行参数对象,直接获得命令行输入

  • —— 定义命令名称

  • —— 定义顶级命令的参数语法

  • —— 解析预期参数

  • —— 注册命令的回调函数

  • —— 定义参数,需要设置“关键字”和“描述”,关键字包括“简写”和“全写”两部分,以”,”,”|”,”空格”做分隔

  • —— 允许命令行未知参数

  • —— 解析argv,设置选项和定义时调用命令

  • —— 添加命令描述

  • —— 设置命令别名

  • —— 设置/获取用法

处理用户输入

node提供了标准的命令行输入的API——。

const readline = require('readline');const rl = readline.createInterface(process.stdin, process.stdout);rl.question('what is your name? ',  function(answer){    console.log(`name is ${answer}`);    rl.close();});

注意:当调用该代码时,Node.js 程序不会终止,直到 readline.Interface 被关闭,因为接口在等待 input 流中要被接收的数据。

配合异步流程控制典型的co 模块使用:

let readlinePrompt = function (query) {  return new Promise(function (resolve, reject) {    rl.question(query, function(answer){      resolve(answer);    });  });};co(function *() {      var template = yield prompt('what is template-name? ');    var project = yield prompt('what is project-name? ');    console.log(`template-name is ${template}`);    console.log(`template-name is ${project}`);    rl.close();})

为了简便我们一般都会使用或者之类的模块。如使用co-prompt模块我们可以这样写:

const prompt = require('co-prompt');co(function *() {      var template = yield prompt('what is template-name? ');    var project = yield prompt('what is project-name? ');    console.log(`template-name is ${template}`);    console.log(`template-name is ${project}`);})

下载git模板

参考vue-cli中下载git模板项目的方法,这里主要是使用了download-git-repo模块,以及使用ora模块显示下载状态。

let templateName = program.args[1]let templateDir = path.join(home, '.plus-templates', templateName.replace(/\//g, '-'))let clone = program.clone || falsefunction downloadAndGenerate(template) {  const spinner = ora('downloading template').start();  download(template, templateDir, { clone: clone }, function (err) {    spinner.stop();    if (err) logger.fatal('Failed to download repo ' + template + ': ' + err.message.trim())    // generate  })}

参考

转载地址:http://fyosl.baihongyu.com/

你可能感兴趣的文章
前端之html5和css3
查看>>
跟KingDZ学HTML5之四 继续探究Canvas之路径
查看>>
054_VisualForce Ajax 01
查看>>
ASCII码、字符与字符串的显示
查看>>
Java 二进制,八进制,十进制,十六进制转换
查看>>
PHP7语法知识(四):目录文件操作、Cookie与Session、MySQL数据库的使用、Redis数据库、PHP处理XML与JSON...
查看>>
bzoj1212
查看>>
Datawhale编程——队列
查看>>
Bzoj3597: [Scoi2014]方伯伯运椰子
查看>>
LOJ #2985. 「WC2019」I 君的商店
查看>>
CSS 基本知识
查看>>
JSON数据传递
查看>>
用Python将word文件转换成html(转)
查看>>
移动widget开发
查看>>
CentOS 6.8 安装Tomcat7
查看>>
Nginx 502 bad gateway问题的解决方法
查看>>
11. Container With Most Water - Medium
查看>>
解决Android中图片圆角——.9图
查看>>
retain和copy的区别 #import @class 的区别
查看>>
CSS基础语法
查看>>