【记一忘三二】脚手架学习

前置知识

ShellCMDBash的区别

Shell 是计算机操作系统中的一个用户界面,用于让用户与操作系统进行交互。它是一个命令行解释器,接收用户输入的命令,解释并执行这些命令,然后将结果返回给用户。 Shell 分为两种方式:

  • GUI(Graphical User Interface)是图形用户界面,它可以在计算机屏幕上显示图形界面,让用户与计算机进行交互。
    • 文件管理器:用户可以查看、创建、修改和删除文件。
  • CLI(Command Line Interface)是命令行界面,它使用命令行来与计算机进行交互,命令行界面通常使用文本输入和输出。
    • CMD:是 Windows 操作系统的默认命令行界面,它提供了许多命令来管理文件和目录,执行程序,启动应用程序等。
      • CMD 窗口中输入 cnpm 命令,优先在当前目录下寻找 是否存在 cnpm.cmd 文件
    • Bash:是 LinuxmacOS 操作系统的默认命令行界面,它提供了许多命令来管理文件和目录,执行程序,启动应用程序等。

WindowsLinux 执行 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包

  1. 打开 cmd 命令行窗口
  2. 输入 npm install -g cnpm
  3. 下载 cnpm 包到全局 nodejsnode_modules 目录下
  4. 扫描 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包

  1. 输入 cnpm --version 命令
  2. 在当前目录查找是否存在 cnpm.cmd 文件
  3. Path 全局环境变量所有目录路径中查找是否存在 cnpm.cmd 文件
  4. 执行 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);
相关推荐
初圣魔门首席弟子10 分钟前
c++中this指针使用bug
前端·c++·bug
AI视觉网奇6 小时前
rknn yolo11 推理
前端·人工智能·python
gplitems1236 小时前
Gunslinger – Gun Store & Hunting WordPress Theme: A Responsible
开发语言·前端·javascript
wyzqhhhh9 小时前
less和sass
前端·less·sass
Nan_Shu_61410 小时前
学习:uniapp全栈微信小程序vue3后台-额外/精彩报错篇
前端·学习·微信小程序·小程序·uni-app·notepad++
excel11 小时前
Vue3 中的双向链表依赖管理详解与示例
前端
前端小白从0开始12 小时前
Chrome DevTools高级用法:性能面板内存泄漏排查
前端·chrome·chrome devtools
EveryPossible12 小时前
带有渐变光晕
前端·javascript·css
jojo是只猫12 小时前
Vue 3 开发的 HLS 视频流播放组件+异常处理
前端·javascript·vue.js
卓码软件测评12 小时前
第三方软件登记测试机构:【软件登记测试机构HTML5测试技术】
前端·功能测试·测试工具·html·测试用例·html5