всех с Новым годом!
Несколько лет назад я получил на работе задание разработать свой CLI, вот и пошел изучать. Его не сложно найти, просто используйте соответствующий API-интерфейс nodejs.
На данный момент реализованы следующие функции:
- Введите новую команду, чтобы загрузить шаблон шаблона с github, а затем создайте соответствующее приложение.
- Введите команду create, чтобы быстро создать шаблонные файлы.
Далее будет поэтапно проанализирован процесс создания CLI, который также является процессом записи воспоминаний.
1. Создайте проект CLI
Создайте файл package.json проекта с помощью npm init. Затем отредактируйте файл в основном, чтобы добавить
"bin": {
"jsm": "./bin/jsm.js"
},
Затем создайте свой собственный файл сценария в текущем каталоге, соответствующий приведенной выше конфигурации, какmkdir bin && touch bin/jsm.js
Отредактируйте созданный файл и добавьте
#!/usr/bin/env node
console.log('Hello CLI')
Далее запустите его в корневом каталоге проектаnpm i -g
, теперь вы можете использовать команду jsm в командной строке.
Примечание: обязательно добавьте в начале#!/usr/bin/env node
, иначе не получится.
详解:package.json文件只有加上了bin字段,才能在控制台使用你的命令,对应的这里的命令就是jsm,对应的执行文件为bin/jsm.js。 其实"jsm"命令就是 "node bin/jsm.js" 的别称,只有你用npm i -g全局安装后才可以用,开发的过程中直接用node bin/jsm.js即可。
2. Разобрать параметры команды
CLI необходимо вводить различные параметры через командную строку, которые можно анализировать непосредственно с помощью связанного с процессом API-интерфейса nodejs, но более рекомендуется использовать пакет commandr npm, который может значительно упростить процесс анализа.npm i commander
Установите, затем измените файл сценария перед добавлением
const program = require('commander');
program
.command('create <type> [name] [otherParams...]')
.alias('c')
.description('Generates new code')
.action(function (type, name, otherParams) {
console.log('type', type);
console.log('name', name);
console.log('other', otherParams);
// 在这里执行具体的操作
});
program.parse(process.argv);
Теперь выполните его в терминалеnode bin/jsm.js c component myComponent state=1 title=HelloCLI
Вы должны иметь возможность видеть различную введенную информацию. Пока часть разбора команды в основном в порядке, другие варианты использования могут ссылаться на официальныйпример
详解:command第一个参数为命令名称,alias为命令的别称, 其中<>包裹的为必选参数 []为选填参数 带有...的参数为剩余参数的集合。
3. Загрузите шаблон для создания файла
Далее нужно что-то сделать по команде, введенной на предыдущем шаге. В частности, интерфейс командной строки скаффолдинга обычно делает две вещи: быстро создает новый проект и быстро создает соответствующие шаблонные файлы. Поскольку необходимо создавать файлы, использование модуля fs узла nodejs является обязательным.Здесь используется расширенная версия.fs-extra
Ниже приведены две часто используемые функции обработки файлов.
//写入文件
function write(path, str) {
fs.writeFileSync(path, str);
}
//拷贝文件
function copyTemplate(from, to) {
from = path.join(__dirname, from);
write(to, fs.readFileSync(from, 'utf-8'));
}
3.1 Создать новый проект
Команда выглядит следующим образом
program
.command('new [name]')
.alias('n')
.description('Creates a new project')
.action(function (name) {
const projectName = name || 'myApp';
init({ app: projectName })
});
Функция init в основном делает две вещи:
- Загрузите шаблон скаффолдинга с github. (Если вы используете локальный шаблон лесов, вы можете пропустить этот шаг)
- Скопируйте файл скаффолда в каталог, указанный командой, и установите соответствующие зависимости.
const fs = require('fs-extra');
const chalk = require('chalk');
const {basename, join} = require('path');
const readline = require('readline');
const download = require('download-git-repo');
const ora = require('ora');
const vfs = require('vinyl-fs');
const map = require('map-stream');
const template = 'stmu1320/Jsm-boilerplate';
// 创建函数
function createProject(dest) {
const spinner = ora('downloading template')
spinner.start()
if (fs.existsSync(boilerplatePath)) fs.emptyDirSync(boilerplatePath)
download(template, 'boilerplate', function (err) {
spinner.stop()
if (err) {
console.log(err)
process.exit()
}
fs
.ensureDir(dest)
.then(() => {
vfs
.src(['**/*', '!node_modules/**/*'], {
cwd: boilerplatePath,
cwdbase: true,
dot: true,
})
.pipe(map(copyLog))
.pipe(vfs.dest(dest))
.on('end', function() {
const app = basename(dest);
const configPath = `${dest}/config.json`;
const configFile = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
configFile.dist = `../build/${app}`;
configFile.title = app;
configFile.description = `${app}-project`;
write(configPath, JSON.stringify(configFile, null, 2));
// 这一部分执行依赖包安装,具体代码请查看文末链接
message.info('run install packages');
require('./install')({
success: initComplete.bind(null, app),
cwd: dest,
});
})
.resume();
})
.catch(err => {
console.log(err);
process.exit();
});
})
}
function init({app}) {
const dest = process.cwd();
const appDir = join(dest, `./${app}`);
createProject(appDir);
}
3.2 Быстрое создание файлов шаблонов
Часть создания файла шаблона на самом деле просто копирует файл в указанное место.Конечно, конкретное содержимое файла должно быть изменено в соответствии с параметрами.
program
.command('create <type> [name] [otherParams...]')
.alias('c')
.description('Generates new code')
.action(function (type, name, otherParams) {
const acceptList = ['component', 'route']
if (!acceptList.find(item => item === type)) {
message.light('create type must one of [component | route]')
process.exit()
}
const params = paramsToObj(otherParams)
params.name = name || 'example'
generate({
type,
params
})
});
//生成文件入口函数
function generate({type, params}) {
const pkgPath = findPkgPath(process.cwd())
if (!pkgPath) {
message.error('No \'package.json\' file was found for the project.')
process.exit()
}
const dist = path.join(pkgPath, `./src/${type}s`);
fs
.ensureDir(dist)
.then(() => {
switch (type) {
case 'component':
// 具体代码请查看文末链接
createComponent(dist, params);
break;
case 'route':
createRoute(dist, params);
break;
default:
break;
}
})
.catch(err => {
console.log(err);
process.exit(1);
});
}
Базовый интерфейс командной строки скаффолдинга здесь почти готов, а остальное — это дружественные подсказки, такие как справочная информация. Весь исходный код статьикликните сюда
Вы также можете установить и попробоватьnpm i -g jsm-cli
.