При ежедневной разработке внешнего интерфейса вы будете сталкиваться с различными cli, такими как webpack, который помогает упаковывать с помощью одной команды, vue-cli, который помогает создавать шаблоны проектов vue с помощью одной команды, и create-react-app для создание реактивных проектов и т. д. Подождите. Эти инструменты значительно облегчают нашу повседневную работу, позволяют компьютеру выполнять рутинную работу самостоятельно, а мы можем сэкономить массу времени на обучение, общение, развитие,посетить пар.
Но иногда для некоторых особых нужд мы не можем найти подходящий инструмент cli для этого. Например, ваш проект очень большой, вы добавляете в проект новый маршрут, проходите创建目录 -> 创建.vue文件 -> 更新vue-router的路由列表
В этом процессе, даже если вы знакомы с использованием горячих клавиш для создания файлов каталогов, он быстрее, чем ваша однострочная команда, особенно когда каталог маршрутизации глубоко вложен, а шаблон инициализации файла .vue сложен.
Итак, почему бы не написать cli для собственного проекта? Просто делать нудную работу?
0x1 hello world
Клиентская среда nodejs, по сути, запускает скрипты узлов.В принципе, каждый клиент будет:
// index.js
console.log('hello world')
Затем вызывается командная строка
> node index.js
## 输出:
> hello world
Для большей реалистичности добавим имя скрипта в поле scripts в package.json:
{
"scripts":{
"hello":"node index.js"
}
}
Затем вызов командной строки:
> npm run hello
Однако, увидев такое, вы точно скажете, что чужие webpack и vue-cli "именные"! какиеvue-cli init app
,webpack -p
Да как красиво, посмотрите на эту командную строку,node index.js
,Такжеnpm run hello
, Кто бы не хотел, это не некрасиво, боюсь, это не статья от воды? Плохой отзыв! !
Не волнуйтесь, давайте поговорим о том, как назвать этот сценарий узла.
0x2 имя
На данный момент сначала назовите этот cli какhello-cli
, то есть мы можем ввести в командной строкеhello-cli
, затем печатает предложениеhello world
,нетnode
ниnpm
,то есть:
- Среда выполнения объявлена в верхней части файла index.js:
Добавить к// index.js #!/usr/bin/env node console.log('hello world')
#!/usr/bin/env node
или#!/usr/bin/node
, который сообщает системе, что следующий скрипт выполняется с использованием nodejs. Конечно, эта система не включает окна, потому что под окнами находится историческая реликвия JScript, из-за которой ваш скрипт не сможет работать.
#!/usr/bin/env node
Это означает позволить системе самостоятельно найти исполняемую программу узла.
#!/usr/bin/node
Это означает явно указать системе, что исполняемая программа узла находится на пути/usr/bin/node
. - Добавьте поле bin в package.json.
Может выполняться в текущем каталоге index.jsnpm init
Создайте package.json, а затем добавьте в package.json поле bin:
Напишите имя командной строки в поле bin, которое{ "name": "hello-test", "version": "1.0.0", "bin":{ "hello-cli":"index.js" } }
hello-cli
, который сообщает npm, что скрипт js внутри может быть выполнен через командную строку дляhello-cli
командный вызов. Само собой имя командной строки ваше, пишите что хотите, например: - В текущем каталоге package.json откройте инструмент командной строки и выполните
npm link
, оставив ярлык для текущего кода в глобальном каталоге npm.
npm обнаруживает, что в package.json есть поле bin, и одновременно генерирует исполняемый файл в глобальном каталоге пакета npm:Когда мы выполняем непосредственно в системной командной строкеhello-cli
, на самом деле выполнить скрипт здесь.
Потому что при установке узла npm настраивает этот каталог как среду системных переменных.Когда вы выполняете команду, система сначала будет искать системные команды и системные переменные, а затем переходить в среду переменных, чтобы найти имя команды, а затем найти это directory. , найдите исполняемый файл, соответствующий имени команды, и выполните его напрямую. Так выполняется либо vue-cli, либо webpack-cli.
Таким образом, ваш первый cli-скрипт был успешно установлен.Вы можете напрямую ввести имя cli в командной строке и увидеть результат.
Кроме того, если вы хотите, чтобы ваш cli-скрипт исполнялся только в проекте, вам нужно создать новую директорию в вашем проекте и повторить вышеописанную операцию, но на третьем шаге не ссылаться на глобальную, а использоватьnpm i -D file:<你的脚本cli目录路径>
, и установите его в node_modules как зависимость проекта. Если установка прошла успешно, вы увидите дополнительную зависимость в package.json проекта. Значением этой зависимости является не номер версии, а путь вашего скрипта. Затем в node_modules будет каталог .bin, в котором будут храниться ваши исполняемые файлы.
Рекомендуется локальная установка
npm i -D file:xxx
, так что он оставит запись в package.json для других друзей. Естественно, ваши скрипты также лучше всего размещать в каталоге проекта.
Разумеется, скрипт cli, установленный таким образом, должен объявить команду script в поле scripts файла package.json проекта, а затем передатьnpm run
способ выполнения.
Ой? Если вы используете его таким образом, вы не вернетесь к исходному в самом начале.npm run hello
Это то же самое.
Да, но есть качественные различия. использоватьnode index.js
Вызывать таким образом просто и гибко, но сильно зависит от пути к скрипту.После изменения структуры каталогов команды, прописанные в скриптах, нужно менять один раз, но после установки с помощью npm локальный cli-скрипт подтягивается в node_modules и изменения структуры каталогов мало на это влияют. Во-вторых, это не способствует совместному использованию и публикации.Если вы хотите опубликовать свой cli-скрипт, лучше иметь красивое и громкое имя, чем рассказывать пользователям, как найти путь к вашему скрипту в документации и выполнить его с помощью node.10 000 раз больше, не так ли?
Здесь также представлена идея процесса разработки cli:
- Первоначальная разработка может осуществляться через
node index.js
чтобы увидеть эффект. - пройти тест
npm link
способ проверить установку. - выпускать
0x3 Чтение параметра: process.argv
Теперь, когда у нас есть имя, у нас есть вывод Давайте посмотрим, в чем разница между нами и этими знаменитыми инструментами cli по форме? Кстати, люди могут поддерживать различные варианты параметров, а также могут давать разные результаты в зависимости от ввода.
Ну давайте добавим в этот кли функцию, раз уж она называетсяhello-cli
, это не может толькоhello world
Ну, вы должны встретиться с кем-то, чтобы сказатьhello
Просто делать:
> hello-cli older
## 输出
> hello older
Хотя эта функция очень проста, она, по крайней мере, обеспечивает эффект «получения разных результатов в зависимости от разных входных данных».
Аргументы в командной строке, доступ к которым можно получить черезprocess
Эта переменная получает,process
является глобальным объектом, а не пакетом, и его не нужно передаватьrequire
Представлять. пройти черезprocess
С помощью этого объекта мы можем получить ряд сведений, таких как текущая среда выполнения скрипта, включая ввод командной строки.Эта информация сохраняется вprocess.argv
в этом свойстве. Мы можем напечатать это:
//index.js
console.log(process.argv);
распечатать результат:
Видно, что argv — это массив, а первые две цифры фиксированы — это путь к нодовой программе и место хранения скрипта, а третья цифра — это содержимое дополнительного ввода. Тогда очень просто реализовать вышеуказанную функцию, просто прочитайте третий бит массива argv и выведите его.//index.js
console.log(`hello ${process.argv[2]||'world'}`)
В сообществе npm также есть отличные пакеты для разбора параметров командной строки, такие какyargs, т. е.commander.jsтак далее
Если вы хотите использовать более сложные параметры или команды, рекомендуется использовать сторонний пакет, так как рукописный парсинг слишком трудозатратен.
0x4 дочерний процесс
Теперь вы можете писать свои собственные cli-скрипты.
Если вы хотите написать проект и автоматически отправить пакет в git cli или автоматически извлечь шаблон запуска проекта из репозитория git, вам необходимо передать узелchild_process
Модуль запускает подпроцесс и вызывает команду git в подпроцессе:
//test.js
const child_process = require('child_process');
let subProcess=child_process.exec("git version",function(err,stdout){
if(err)console.log(err);
console.log(stdout);
subProcess.kill()
});
Здесь могут быть выполнены не только команды git, но и системные команды и другие команды cli. Особенно системные команды, использование системных команд для работы с файловыми каталогами более эффективно, чем fs, поэтому я не знаю, куда идти.
В сообществе также есть несколько хороших пакетов, например, рекомендованных Ruan Yifeng.shelljs
0x5 украсить вывод
Если вы не хотите, чтобы ваш cli был таким «хардкорным», вы хотите, чтобы он был более удобным для пользователя, например, предоставлял дружественный ввод и подсказки, добавлял некоторые цвета к вашему выводу, чтобы различать ключевые точки, написание простого индикатор выполнения и т. д. Подождите, тогда вам нужно украсить свой вывод.
Кроме цветовой части, это очень громоздко и сложно реализовать без использования сторонних пакетов, остальные функции можно попробовать написать самому.
Цветная часть использует сторонний пакетcolors, что не будет здесь продемонстрировано.
Другие предоставляются nodejsreadlineреализуется модулем.
//index.js
const readline = require('readline');
const unloadChar='-';
const loadedChar='=';
const rl=readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('你想对谁说声hello? ',answer=>{
let i = 0;
let time = setInterval(()=>{
if(i>10){
clearInterval(time);
readline.cursorTo(process.stdout, 0, 0);
readline.clearScreenDown(process.stdout);
console.log(`hello ${answer}`);
process.exit(0)
return
}
readline.cursorTo(process.stdout,0,1);
readline.clearScreenDown(process.stdout);
renderProgress('saying hello',i);
i++
},200);
});
function renderProgress(text,step){
const PERCENT = Math.round(step*10);
const COUNT = 2;
const unloadStr = new Array(COUNT*(10-step)).fill(unloadChar).join('');
const loadedStr = new Array(COUNT*(step)).fill(loadedChar).join('');
process.stdout.write(`${text}:【${loadedStr}${unloadStr}|${PERCENT}%】`)
}
- Во-первых, по
readline.createInterface
метод созданияinterface
Добрый, есть метод ниже этого класса.question
, используйте этот метод, чтобы передать проблему в командную строку и передать функцию для прослушивания во втором параметре. Как только пользователь заканчивает печатать и нажимает Enter, срабатывает функция обратного вызова. - Затем мы написали таймер внутри функции обратного вызова, делая вид, что мы что-то делаем.
- использовать
readline.cursorTo
Этот метод изменяет положение курсора в командной строке.
readline.cursorTo(process.stdout, 0, 0);
это перейти к столбцу 1, строке 1,
readline.cursorTo(process.stdout, 0, 1);
это перейти к столбцу 1 и строке 2. - использовать
readline.clearScreenDown
Этот метод заключается в запуске командной строки с текущей строки до конца последней строки и очистке всего между двумя строками. -
renderProgress
Это метод собственной инкапсуляции, посредствомprocess.stdout.write
Метод выводит в командную строку строку, которая выглядит как индикатор выполнения. - Итак, в таймере, когда счетчик меньше 10, мы перемещаем курсор на первую строку, затем очищаем весь вывод и выводим строку индикатора выполнения; когда счетчик больше 10, мы выключаем таймер, очищаем вывод, Распечатать результат.
- Наконец, не забудьте закрыть процесс, вы можете использовать
interface
этого класса.close
Метод отключает процесс readline, или вы можете вызвать его напрямуюprocess.exit
покидать.
Идея рисования такая же, как анимация рисования холста, за исключением того, что холст очищает холст, а командная строка передается черезreadline.clearScreenDown
Очистить вывод.
Таким образом, написан простой, удобный инструмент командной строки cli с небольшой анимацией индикатора выполнения, и вы также можете использовать свое воображение, чтобы написать еще несколько интересных эффектов.
Ведь в нашем фронтенде мы можем писать анимации с браузером, а можем писать анимации без браузера.