什么是Nodejs Cli利用?

简略来说就是在命令行能够应用nodejs来执行的利用,例如:vue-cli、creat-react-app、webpack-cli等;在前端开发过程中咱们会用到很多的工具,这些工具在装置过后能够间接应用命令行执行;留神在全局装置和在我的项目装置不同。

// 全局装置,间接执行命令> npm install webpack webpack-cli -g> webpack// 我的项目装置,须要借助npx执行> npm install webpack webpack-cli --save-dev> npx webpack

Nodejs Cli利用的工作流程!

1、启动过程:

命令行执行命令 => 依据package.json中bin查问入口 => 执行入口js文件cli.js

2、执行过程:

命令行执行js文件性能启动=> 命令行询问用户问题 => 联合问题答案+模板等文件 => 生成构造文件

Nodejs Cli利用的入口文件:cli.js

1、入口文件门路 ,首先在package.json 中增加bin字段

{  "name": "ncl",  "main": "index.js",  "bin": {    "ncl": "./cli.js"   //入口文件,ncl和name保持一致  },  ...}

2、入口文件特定的文件头 ,在cli.js顶部输出

#!/usr/bin/env node

3、入口文件权限
// 如果是 Linux 或者 macOS 零碎下还须要批改此文件的读写权限为 755
// 具体就是通过 chmod 755 cli.js 实现批改

4、简略测试模块
npm link 能够将模块链接到全局,也能够链接到应用该模块的我的项目node_modules中;这样在开发模块的过程中,不必公布到npm也能够应用模块进行测试。

> npm link // 在自定义模块我的项目的目录执行,将模块连贯到全局> ncl // 间接执行模块,应用模块名

Nodejs Cli利用的示例

该示例的性能实现一个自定义的脚手架:在命令行询问用户一些简略的问题作为参数,而后主动生成一些我的项目文件。其中的文件能够通过模板生成,也能够传递数据到模板。

1、装置一些依赖模块

> npm install inquirer --save //nodejs环境下,实现命令行的用户交互插件 > npm install ejs --save //模板引擎

2、cli.js中定义命令行询问用户问题

  • inquire.prompt进行命令行的用户询问操作
  • inquirer.prompt返回值为一个promise对象
  • inquirer.prompt的参数为一个数组
const inquirer = require('inquirer')inquirer.prompt([    {        type: 'input',        name: 'name',        message: '请输出项目名称?'    }]).then(anwsers => {    // anwsers: { name: "xxx" } //anwsers返回一个后果对象})

3、获取模板目录和指标生成目录

const path = require('path')// 模板目录// __dirname 获取以后执行代码文件的绝对路径// tmplDir 为templates的绝对路径const tmplDir = path.join(__dirname, 'templates')// 目标目录// process.cwd()返回 Node.js 过程的当前工作目录。// process参考api文档:http://nodejs.cn/api/process.htmlconst destDir = process.cwd()

4、模板引擎渲染模板

const ejs = require('ejs')const path = require('path')// 通过模板引擎渲染文件// 参数1:fileDir为文件的绝对路径// 参数2:渲染模板所需变量,存在anwsers对象外面// 参数3:回调函数,result为新文件ejs.renderFile(fileDir, anwsers, (err, result) => {  if (err) throw err  // 将后果写入指标文件门路  fs.writeFileSync(fileDestDir, result)})
// 一个package.json作为模板的示例:{"name": "<%= name %>",  "version": "<%= version %>",  "description": "<%= description %>",  "author": "<%= author %>",  "bin": "cli.js",  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1"  },  "license": "ISC"}

5、读取目录下的文件

  // 将模板下的文件全副转换到目标目录  // 参数1:path  // 参数2:回调函数,参数files为文件相对路径组成的数组  fs.readdir(tmplDir, (err, files) => {    if (err) throw err    files.forEach(file => {      // 通过模板引擎渲染文件      // 解决 file       })    })  })

6、将文件写入门路

// 将后果写入指标文件门路// 参数1:文件的绝对路径// 参数2:文件内容fs.writeFileSync(fileDestDir, result)

模板文件相干

这里是依据本人的需要将须要主动生成的文件放到模板目录下,没有变动的或者对立的文件就不须要应用模板引擎。
1、模板门路:templates;

2、通常将整顿好的我的项目构造整体拷贝到templates下,例如:vue的示例源文件、lint文件、package.json等等;

测试模块执行

本地开发能够应用npm link关联模块目录和依赖此模块的我的项目node_modules目录;也能够公布到npm源上后间接装置应用模块。

1、关联模块:

> cd nodejs-cli-sample //Nodejs Cli利用的目录> npm link // 将模块连贯到全局

2、执行模块:

> cd nodejs-cli-demo // 在我的项目目录执行模块> ncl // 间接执行模块,应用模块名(ncl 是我的项目nodejs-cli-sample的名称)

公布Nodejs Cli利用

1、能够间接应用npm publish公布到源上

> npm publish --registry=https://registry.xxxx

2、要思考到npm源是否有写权限,能够公布到本人公司的npm源上或者yarn源上

// 淘宝镜像源是只读的,publish不下来// 公布到yarn的镜像源之后,应用淘宝镜像源时能够手动同步放慢模块下载速度yarn publish --registry https://registry.yarnpkg.com/

残缺示例代码

1、NodeJs Cli利用cli.js 入口文件

#!/usr/bin/env node// Node CLI 利用入口文件必须要有这样的文件头// 如果是 Linux 或者 macOS 零碎下还须要批改此文件的读写权限为 755// 具体就是通过 chmod 755 cli.js 实现批改const fs = require('fs')    // 文件读写const path = require('path')    // 门路获取const inquirer = require('inquirer')    //命令行用户交互const ejs = require('ejs')  // 模板引擎// 脚手架的工作过程:启动 => 命令行询问用户问题 => 联合问题答案+模板 => 生成构造文件inquirer.prompt([    {        type: 'input',        name: 'name',        message: '请输出项目名称(\'\')'    },    {        type: 'input',        name: 'version',        message: '请输出我的项目版本号(1.0.0)'    },    {        type: 'input',        name: 'description',        message: '请输出我的项目备注(\'\')'    },    {        type: 'input',        name: 'author',        message: '请输出作者名称(\'\')'    }]).then(anwsers => {    // anwsers: { name: "xxx" } //anwsers返回一个后果对象    // 模板目录绝对路径    const tmplDir = path.join(__dirname, 'templates')    // 目标目录    const destDir = process.cwd()    // 读取目录下所有文件    let readFiles = (dir) => {        return new Promise((resolve, reject)=>{            // 参数1:目录门路            // 参数2:回调函数(谬误对象,files为文件相对路径组成的数组)            fs.readdir(dir, (err, files) => {                if (err) reject(err)                resolve(files)            })        })    }    // 解决模板文件    let ejsRender = (file) => {        return new Promise((resolve, reject)=>{            // 模板文件绝对路径            let dir = path.join(tmplDir, file)            // 参数1:文件门路            // 参数2:数据对象            // 参数3:回调函数(谬误对象,渲染后的新文件)            ejs.renderFile(dir, anwsers, (err, result) => {                if (err) reject(err)                resolve(result)            })        })    }    // 1、先读取目录下所有文件    // 2、应用ejs渲染所有模板    // 3、再将新文件写到指标门路    readFiles(tmplDir).then((files)=>{        files.forEach(file => {            ejsRender(file).then((result)=>{                // 指标文件绝对路径,file其实是文件相对路径                let fileDestDir = path.join(destDir, file)                // 将后果写入指标文件门路                // 参数1:文件绝对路径                // 参数2:渲染后新文件                fs.writeFileSync(fileDestDir, result)            },throwError)        })    },throwError)})/** * 谬误处理函数 * @param {*谬误对象} error  */function throwError(error){    throw error}

2、package.json 示例模板文件,应用的ejs模板引擎

{"name": "<%= name %>",  "version": "<%= version %>",  "description": "<%= description %>",  "author": "<%= author %>",  "bin": "cli.js",  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1"  },  "license": "ISC"}