前置知识
Shell
、CMD
、Bash
的区别

Shell
是计算机操作系统中的一个用户界面,用于让用户与操作系统进行交互。它是一个命令行解释器,接收用户输入的命令,解释并执行这些命令,然后将结果返回给用户。 Shell
分为两种方式:
GUI
:(Graphical User Interface)
是图形用户界面,它可以在计算机屏幕上显示图形界面,让用户与计算机进行交互。- 文件管理器:用户可以查看、创建、修改和删除文件。
CLI
:(Command Line Interface)
是命令行界面,它使用命令行来与计算机进行交互,命令行界面通常使用文本输入和输出。CMD
:是Windows
操作系统的默认命令行界面,它提供了许多命令来管理文件和目录,执行程序,启动应用程序等。- 在
CMD
窗口中输入cnpm
命令,优先在当前目录下寻找 是否存在cnpm.cmd
文件
- 在
Bash
:是Linux
和macOS
操作系统的默认命令行界面,它提供了许多命令来管理文件和目录,执行程序,启动应用程序等。
Windows
和 Linux
执行 js
文件的区别
Windows
通过 cmd
可执行文件执行js
文件

Linux
通过 \#!/usr/bin/env node
用指定脚本的解释器
bash
#!/usr/bin/env node
js
#!/usr/bin/env node
console.log(22)
Windows
使用全局使用 npm包
如何全局安装 npm包

- 打开
cmd
命令行窗口 - 输入
npm install -g cnpm
- 下载
cnpm
包到全局nodejs
的node_modules
目录下 - 扫描
package.json
文件,判断是否存在bin
属性-
如果存在
bin
属性json{ "bin": { "cnpm": "bin/cnpm.js" } }
-
nodejs
文件夹创建cnpm.cmd
文件 、cnpm
文件 -
cnpm.cmd
文件 :由于在Windows
系统下,无法直接运行js
文件,所以需要创建一个cmd
文件,将node
运行js
文件的命令写入cmd
文件中判断
nodejs
文件夹下是否存在node.exe
文件,如果存在,则使用node.exe
执行cnpm.js
文件,否则通过node
命令在全局环境中寻找node.ext
执行cnpm.js
文件 -
cnpm
文件:软链接至cnpm.cmd
文件,主要方便用户输入cnpm
命令时,通过cnpm
文件软链接至cnpm.cmd
文件,如何执行cnpm.cmd
文件。 测试得知:在CMD
窗口输入cnpm
命令时,并不会通过cnpm
文件寻找cnpm.cmd
文件,而是会直接执行cnpm.cmd
文件,所以在CMD
窗口cnpm
文件没有意义。cnpm
文件的存在是为了做兼容处理,有些Shll
窗口支持通过cnpm
文件软链接至cnpm.cmd
文件(暂未发现)。
-
-
如何执行全局 npm包

- 输入
cnpm --version
命令 - 在当前目录查找是否存在
cnpm.cmd
文件 - 在
Path
全局环境变量所有目录路径中查找是否存在cnpm.cmd
文件 - 执行
cnpm.cmd
文件,在cnpm.cmd
文件中,通过node
命令执行cnpm.js
文件`
脚手架的入门
自定义命令安装至全局
js
#!/usr/bin/env node
console.log(222)
json
{
"name": "hc",
"version": "1.0.0",
"bin": {
"hc": "./bin/index.js"
}
}
shell
# 安装全局脚手架
npm link
# 卸载全局脚手架
npm uninstall hc -g
在执行npm link
命令时,需要控制台进入项目目录
脚手架尝试
原生实现
js
#!/usr/bin/env node
const process = require('node:process')
const packageJson = require('../package.json')
const command = process.argv[2]
// 全局选项
if (/^(--|-)/.test(command)) {
const option = command.replace(/(--|-)/, '')
if (['v', 'V', 'version'].includes(option)) {
console.log(`版本号:${packageJson.version}`)
}
}
else {
if (command === 'init') {
let [option, value] = process.argv.slice(3)
option = option.replace(/(--|-)/, '')
console.log(`项目初始化:${value}`)
}
}
yargs
js
#!/usr/bin/env node
import process from 'node:process'
import yargs from 'yargs'
import { hideBin } from 'yargs/helpers'
const cli = yargs(hideBin(process.argv))
cli
.scriptName('hc')
.strict()
.wrap(cli.terminalWidth())
.version('0.0.1')
.help()
.usage('hc [命令] [参数] [选项]')
.command({
command: 'init <name>',
describe: '初始化项目',
builder: (yargs) => {
return yargs
.usage('hc init [参数] [选项]')
.positional('name', {
describe: '项目名称',
type: 'string',
demandOption: true,
})
.option('force', {
alias: 'f',
describe: '强制覆盖同名项目',
type: 'boolean',
default: false,
})
.version(false)
},
handler({ name, force }) {
if (force) {
console.log('强制覆盖同名项目')
}
console.log(`初始化项目:${name}`)
},
})
.option('debug', {
describe: '开启调试模式',
type: 'boolean',
default: false,
alias: 'd',
})
.alias('h', 'help')
.alias('v', 'version')
.group(["help", "version", "debug"], "全局选项")
.demandCommand(1, '请输入命令')
.fail((msg, error) => {
if (error) {
throw error
}
console.error(msg)
process.exit(1)
})
.argv
commander
js
import process from 'node:process';
import { Command } from 'commander';
const program = new Command();
program
.name('hc')
.version('0.0.1', "-V,--version", "显示版本号")
.option('-d, --debug', '是否显示调试信息')
.helpOption('-h, --help', '显示帮助信息')
.description("一个用于快速创建项目模板的命令行工具")
program
.command("init")
.argument("[projectName]", "项目名")
.option("-f, --force", "是否强制初始化")
.description("初始化项目")
.action((projectName, options) => {
if (options.force) {
console.log("强制初始化项目");
}
console.log("初始化项目:", projectName);
})
const serveProgram = new Command("serve");
serveProgram
.description("服务管理")
serveProgram
.command("start")
.argument("[port]", "端口号", 3000)
.description("启动项目")
.action((port) => {
console.log("启动服务,端口号:" + port);
});
program
.command("install", "下载依赖", {
executableFile: "./install.js",
hidden: true
})
.alias("i")
program
.argument("<command>", "默认命令")
.action((command) => {
console.log("执行命令:" + command);
});
program.addCommand(serveProgram);
program.parse(process.argv);