node构建cli过程

  |  

CLI

“CLI 是 Command Line Interface 的缩写,即命令行界面。

比如 npm, 本身也是通过 bin 属性安装为一个可执行命令的

构建一个 node 的 cli, 关键在于 package.json 的 bin 属性

// 可执行文件 配置后才可以在控制台使用你的命令
// 构建 cli 必须写的字段
"bin": {
"my-cli": "./index.js"
},

新建 bin 关联的可执行文件

index.js 文件

#!/usr/bin/env node  
// 上面一句必须写,告诉系统执行脚本时,调用node 环境
console.log("hello cli")

安装为cli命令

sudo npm i -g

// 或者 链接一下
// npm link

执行成功之后,就可以在终端执行 bin 下定义的命令

my-cli
// 输出
// hello cli

一个简单的例子

ls 命令,

// index.js
const fs = require("fs")
const pwdPath = process.cwd() // 当前cli命令所在的目录
const files = fs.readdirSync(pwdPath)
let output = files
.map(item => {
let stat = fs.statSync(pwdPath, +"/" + item)
let type = stat.isDirectory() ? "目录" : "文件"
return `[${type}] ${item}\r\n`
})
.join("")
console.log(output)

写一个静态服务器

#! /usr/bin/env node
// index.js
// -d 静态文件目录, -o -- host 主机 -p --port 端口号
// index.js主要用于读取 用户输入的参数 比如 http-server --port 8080
// 主要通过 yargs 这个包读取 用户命令参数
const yargs = require('yargs')
const Server = require('../src/app.js')
const argv = yargs.option('d', {
alias: 'root',
demand: false,
default: 'localhost',
description: '静态文件根目录'
}).option('o', {
alias: 'host',
demand: false,
default: 'localhost',
description: '请配置监听的主机'
}).option('p', {
alias: 'port',
demand: false,
type: 'number',
default: 8080,
description: '请配置监听的端口号'
}).usage('xh-server [options]')
.example('sh-server -d / -p 9090 -o localhost')
.help('h').argv
// usage 用法示例 options 参数配置

// argv = {d,root,o,host,p,host}

const server = new Server(argv)

需要一些默认的服务器信息

// config.js
const path = require('path')
module.exports = {
host: 'localhost',
port: '8080',
root: path.resolve(__dirname, '..', 'public')
}
// server.js

const config = require('./config.js')

const http = require('http')
const chalk = require('chalk')
const path = require('path')
const url = require("url")
const fs = require('fs')
const mime = require('mime')
const {promisify} = require('util')
const stat = promisify(fs.stat)
const readdir = promisify(fs.readdir)
const handlebars = require('handlebars')
// 每一个debug实例都有一个名字,需要设置环境变量才会生效 window 下 set DEBUG=static:app mac/linux下 export DEBUG=static:*

const debug = require('debug')('static:app')

// 编译模板,得到一个渲染的方法,返回后传入实际的数据就可以得到渲染后的html
// template/list.html
function list() {
const tmlp = fs.readFileSync(path.resolve(__dirname, 'template', 'list.html'),'utf-8')
return handlebars.compile(tmlp)
}
class Server {
constructor(argv) {
this.config = Object.assign({},config, argv)
this.server = http.createServer()
this.start()
this.list = list()
}
start() {
this.server.on('request', this.request.bind(this))
this.server.listen(this.config.port, () => {
let url = `${this.config.host}:${this.config.port}`
debug('server started at ' + chalk.green(url));
})
}
async request(req, res) {
const {pathname} = url.parse(req.url,true)
const filepath = path.join(this.config.root, pathname)
if(pathname === '/favicon.ico') return this.sendError(req,res)
try {
const statObj = await stat(filepath)
if(statObj.isDirectory()) { // 如果是目录的

let files = await readdir(filepath)
files = files.map(file => ({
name: file,
url: path.join(pathname,file)
}))
// 模版引擎编写
let html = this.list({
title: pathname,
files
})
res.setHeader('Content-Type', "text/html")
res.end(html)
} else {
this.sendFile(req,res,filepath, statObj)
}
} catch (error) {
console.log(error);
this.sendError(req,res)
}

}
sendFile(req, res,filepath, statObj) {
res.setHeader('Content-Type', mime.getType(filepath))
fs.createReadStream(filepath).pipe(res)
}

sendError(req,res) {
res.statusCode = 500
res.end('there is something wrong in the server! please try later!')
}
}
// new Server()

module.exports = Server

template/list.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{title}}</title>
</head>
<body>
<ul>
{{#each files}}
<li>
<a href="{{url}}"> {{name}}</a>
</li>
{{/each}}
</ul>
</body>
</html>

至此已经完成了。

有其他更多想实现的工具,可以敞开思维去实现

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. CLI
  2. 2. 新建 bin 关联的可执行文件
  3. 3. 安装为cli命令
  4. 4. 一个简单的例子
  5. 5. 写一个静态服务器
,