node.jsでcliを作成します(コマンドラインインターフェース)
12548 ワード
node.jsでcliを作成します(コマンドラインインターフェース)
本文はあなたを連れて一歩ずつcliを完成して、本文に従って操作してきます.どうやってコマンドラインツールを作成するかを理解します.仕事で使うなら、自分でコマンドラインツールを書かないでください.nodejsに対して基本的な理解が必要です.
本論文の例は開発においてよく使われているプロジェクトのモデルを作成し、gitと依存インストールを含み、簡単なバージョンのvue-cliとみなすことができる.その中に含まれていますコマンドラインのパラメータ取得、--git-gおよび補足パラメータを提示する を使用します.どのようにjsファイルプログラムを実行可能なコマンドに追加しますか? よく使われるコマンドライン作成npmパッケージ コマンドラインツールと私たちが普段書いているnodeプログラムは全部nodejsプログラムの実行です.の違いは、コマンドラインプログラムは直接カスタムコマンドを入力することによってプログラムの呼び出しを完了することができます.nodejsはnode***またはnpm scriptによって呼び出す必要があります.私たちが作成するコマンドラインは、bashのalias概念と似ています.あるいは実行可能プログラム名を実行可能リストに追加します. の残りの作業は、解析パラメータであり、プログラム自体の機能を完了する です.
直接始めましょう
(まず、プロセス中に関与した新しいアプリとnpmパッケージを管理しなくても、これらは完成したら見られます.)
1.コマンドを作成し、パラメータを受信する
nodejsプロジェクトを作成します.
この場合はesm依存をインストールする必要があります.
コマンドラインに追加するには最後のステップが必要です.一番簡単な方法はnpm linkを使ってプロジェクトで実行します.
上のコマンドのパラメータはもう手に入りました.パラメータを解析します.私たちのコマンドはパラメータとオプションをサポートします. templateは異なるテンプレートをサポートします.もしユーザが入力していないなら、ユーザーにテンプレートの選択を促すことになります. --gitは である.-install自動装着依存 -yesスキップメッセージは、標準オプション を使用します.
私たちのプロジェクトでは
3.業務ロジックの追加
私たちはもうコマンドラインで私たちが必要とするパラメータを得ることができました.次は私たちの実際のプログラムロジックです.テンプレートプロジェクトを作成して、空いているフォルダの中で、プロジェクトファイルをテンプレートからコピーする 実行git initとnpm instal負荷依存性 3.1ファイルをコピーする
まずテンプレートフォルダを作成します.templatesフォルダは、javascriptとtypescriptの2つのプロジェクトテンプレートを含んでいます.中にプロジェクトファイルsrcなどがあります.他の配置(.babelrc lint配置)とpackage.jsonファイルです.
すべてのプログラムロジックをmain.jsファイルに書いて、srcディレクトリの下で、コード:
cli.jsでこの方法を呼び出します.
私達は3つの依存をインストールします.execaは外部の命令pkg-innstallインストールに依存しています.Listr定義のタスクリストには、タスク実行の進捗フィードバックが含まれています.
アプリケーションを本物の他人が使えるモジュールにパッケージするには、srcディレクトリにindex.jsファイルを追加する必要があります.
これまで完全なコマンドラインアプリケーションのパッケージを作成しましたが、自分だけでnpm linkを使ってグローバルに登録してください.あなたのアプリケーションを他の人に共有したい場合は、github npmでリリースするなど、npmで配布する方法を強く推奨します.package.jsonにfilesフィールドを追加して、そのファイルがリリースされることを確認してください.
関連記事 How to build a CLI with Node.js The magic behind npm link
本文はあなたを連れて一歩ずつcliを完成して、本文に従って操作してきます.どうやってコマンドラインツールを作成するかを理解します.仕事で使うなら、自分でコマンドラインツールを書かないでください.nodejsに対して基本的な理解が必要です.
本論文の例は開発においてよく使われているプロジェクトのモデルを作成し、gitと依存インストールを含み、簡単なバージョンのvue-cliとみなすことができる.その中に含まれています
直接始めましょう
(まず、プロセス中に関与した新しいアプリとnpmパッケージを管理しなくても、これらは完成したら見られます.)
1.コマンドを作成し、パラメータを受信する
nodejsプロジェクトを作成します.
mkdir create-project && cd create-project
npm init --yes
ディレクトリの下でsrcディレクトリを作成し、cli.jsファイルを作成します.cli.js内容です.export function cli(args) {
console.log(args);
}
このファイルはパラメータとトラヒックロジックを解析するためのファイルです.次はコマンドラインの入り口を作成します.ルートディレクトリはフォルダbinを作成して、その中に新しいファイルcreat-projectを作成して、内容を書き込みます.#!/usr/bin/env node
require = require('esm')(module /*, options*/);
require('../src/cli').cli(process.argv);
この書類の中では小さな仕事しかしていません.まず、esm
モジュールをロードしました.import
を使って、私達のファイルの中で使用できます.(import方式でrequireを使用しなくてもいいです.本教程はES Moduleを使用しています.esmパッケージはこの方式の互換性を解決できます.)その後、cli.js
ファイルをロードして、cli方法を呼び出します.このパラメータはコマンドラインの呼び出し時に入ってきたコマンドラインパラメータ配列です.この場合はesm依存をインストールする必要があります.
npm install esm
ディレクトリファイル:.
├── bin
│ └── create-project
├── node_modules
│ └── esm
├── package-lock.json
├── package.json
└── src
└── cli.js
次に、パッケージマネージャ(npm)にCLI script(コマンドラインスクリプト)を暴くことをお知らせします.私たちはprocess.argv
に適切なエントリを追加することによって、binフィールドでdescription name keyword mainフィールドを変更します.{
"name": "@pipu11qiao/create-project",
"version": "1.0.0",
"description": "A cli to create project",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"bin": {
"create-project": "bin/create-project",
"@pipu11qiao/create-project": "bin/create-project"
},
"publishConfig": {
"access": "public"
},
"keywords": [
"cli",
"create-project"
],
"author": "",
"license": "ISC",
"dependencies": {
"esm": "^3.2.25"
}
}
binフィールドを通じて、npmにこのコマンドラインのインストールを通知します.私たちはbinフィールドに2つのコマンドを追加します.私たちnpmパッケージを使用すれば、ユーザー名で呼び出すことができます.一般ユーザーなら、直接package.json
コマンドを使用することができます.コマンドラインに追加するには最後のステップが必要です.一番簡単な方法はnpm linkを使ってプロジェクトで実行します.
npm link
これは全体的にソフトリンクを作成します.これを通じてあなたのプロジェクトにアクセスできるので、後続のコードの更新もこの操作を更新する必要がありません.現在登録されているコマンドは呼び出し可能です.入力:create-projet
出力が見えます.args [ '/usr/local/bin/node', '/usr/local/bin/create-project' ]
前の二つのパラメータはnodeのインストール経路の変化によって異なります.コマンドパラメータの変化によって出力結果も多くなります.加えて--yesパラメータcreate-project --yes
結果:args [ '/usr/local/bin/node',
'/usr/local/bin/create-project',
'--yes' ]
2.解析パラメータ処理ユーザ入力上のコマンドのパラメータはもう手に入りました.パラメータを解析します.私たちのコマンドはパラメータとオプションをサポートします.
create-project
を用いてプロジェクト初期化git 私たちのプロジェクトでは
git init
を使用して、ユーザーに確実な入力オプションを提示し、inquirer
パッケージを使ってパラメータを解析し、依存性を追加します.npm i inquirer arg
まず、cli.jsファイルに解析パラメータの機能を追加します.import arg from 'arg';
function parseArgumentsIntoOptions(rawArgs) {
const args = arg(
{
'--git': Boolean,
'--yes': Boolean,
'--install': Boolean,
'-g': '--git',
'-y': '--yes',
'-i': '--install',
},
{
argv: rawArgs.slice(2),
}
);
return {
skipPrompts: args['--yes'] || false,
git: args['--git'] || false,
template: args._[0],
runInstall: args['--install'] || false,
};
}
export function cli(args) {
let options = parseArgumentsIntoOptions(args);
console.log(options);
}
creat-project--yesを実行して、skypProptsオプションがtrueに変わることが見えます.{ skipPrompts: true,
git: false,
template: undefined,
runInstall: false }
次に、ユーザーの入力パラメータによって、不足しているパラメータのヒントを決定します.もしユーザがスキップを選択したら、そのままデフォルトのオプションに戻ります.そうでないと、ユーザに確かなオプションを選択して、promptForMissingOptions方法を追加して、parseArmogments IntoOptionsの後で呼び出します.import arg from 'arg';
import inquirer from 'inquirer';
function parseArgumentsIntoOptions(rawArgs) {
// ...
}
async function promptForMissingOptions(options) {
const defaultTemplate = 'JavaScript';
if (options.skipPrompts) {
return {
...options,
template: options.template || defaultTemplate,
};
}
const questions = [];
if (!options.template) {
questions.push({
type: 'list',
name: 'template',
message: 'Please choose which project template to use',
choices: ['JavaScript', 'TypeScript'],
default: defaultTemplate,
});
}
if (!options.git) {
questions.push({
type: 'confirm',
name: 'git',
message: 'Initialize a git repository?',
default: false,
});
}
const answers = await inquirer.prompt(questions);
return {
...options,
template: options.template || answers.template,
git: options.git || answers.git,
};
}
export async function cli(args) {
let options = parseArgumentsIntoOptions(args);
options = await promptForMissingOptions(options);
console.log(options);
}
今はcreat-projectコマンドを実行しています.入力のヒントが見えます.~/project/create-project create-project
? Please choose which project template to use (Use arrow keys)
❯ JavaScript
TypeScript
テンプレートを選択したら、gitを開くかどうかを選択させます.最後の入力結果:{ skipPrompts: false,
git: false,
template: 'JavaScript',
runInstall: false }
-yパラメータを追加することでヒントをスキップすることもできます.3.業務ロジックの追加
私たちはもうコマンドラインで私たちが必要とするパラメータを得ることができました.次は私たちの実際のプログラムロジックです.テンプレートプロジェクトを作成して、空いているフォルダの中で、
まずテンプレートフォルダを作成します.templatesフォルダは、javascriptとtypescriptの2つのプロジェクトテンプレートを含んでいます.中にプロジェクトファイルsrcなどがあります.他の配置(.babelrc lint配置)とpackage.jsonファイルです.
.
├── javascript
│ ├── package.json
│ └── src
└── typescript
├── package.json
└── src
コピーファイルはarg
パケットを使用して、変更パケットはフォルダに再帰的にコピーすることができます.同名のファイルを強制的に上書きすることもできます.コンソールで色文字を出力することができます.すべてのプログラムロジックをmain.jsファイルに書いて、srcディレクトリの下で、コード:
import chalk from 'chalk';
import fs from 'fs';
import ncp from 'ncp';
import path from 'path';
import { promisify } from 'util';
const access = promisify(fs.access);
const copy = promisify(ncp);
async function copyTemplateFiles(options) {
return copy(options.templateDirectory, options.targetDirectory, {
clobber: false,
});
}
export async function createProject(options) {
options = {
...options,
targetDirectory: options.targetDirectory || process.cwd(),
};
const currentFileUrl = import.meta.url;
const templateDir = path.resolve(
new URL(currentFileUrl).pathname,
'../../templates',
options.template.toLowerCase()
);
options.templateDirectory = templateDir;
try {
await access(templateDir, fs.constants.R_OK);
} catch (err) {
console.error('%s Invalid template name', chalk.red.bold('ERROR'));
process.exit(1);
}
console.log('Copy project files');
await copyTemplateFiles(options);
console.log('%s Project ready', chalk.green.bold('DONE'));
return true;
}
このコードは、まずfs.access法によってテンプレートが存在するかどうかを検出し、ncpによってテンプレートディレクトリをターゲットディレクトリにコピーすると、色付きのヒントが出力され、ファイルのコピーが完了したときにcli.jsでこの方法を呼び出します.
import arg from 'arg';
import inquirer from 'inquirer';
import { createProject } from './main';
function parseArgumentsIntoOptions(rawArgs) {
// ...
}
async function promptForMissingOptions(options) {
// ...
}
export async function cli(args) {
let options = parseArgumentsIntoOptions(args);
options = await promptForMissingOptions(options);
await createProject(options);
}
フォルダtest-dirを新規作成して実行します.create-project TypeScript --git
ヒントが表示されます.これはtypescriptディレクトリのファイルもフォルダにコピーされました./create-project/test-dir tree -L 2
.
├── package.json
└── src
1 directory, 1 file
3.git initとnpm instal負荷依存を実行する私達は3つの依存をインストールします.execaは外部の命令pkg-innstallインストールに依存しています.Listr定義のタスクリストには、タスク実行の進捗フィードバックが含まれています.
npm install execa pkg-install listr
mail.jsにコードを追加します.import chalk from 'chalk';
import fs from 'fs';
import ncp from 'ncp';
import path from 'path';
import { promisify } from 'util';
import execa from 'execa';
import Listr from 'listr';
import { projectInstall } from 'pkg-install';
const access = promisify(fs.access);
const copy = promisify(ncp);
async function copyTemplateFiles(options) {
return copy(options.templateDirectory, options.targetDirectory, {
clobber: false,
});
}
async function initGit(options) {
const result = await execa('git', ['init'], {
cwd: options.targetDirectory,
});
if (result.failed) {
return Promise.reject(new Error('Failed to initialize git'));
}
return;
}
export async function createProject(options) {
options = {
...options,
targetDirectory: options.targetDirectory || process.cwd()
};
const templateDir = path.resolve(
new URL(import.meta.url).pathname,
'../../templates',
options.template
);
options.templateDirectory = templateDir;
try {
await access(templateDir, fs.constants.R_OK);
} catch (err) {
console.error('%s Invalid template name', chalk.red.bold('ERROR'));
process.exit(1);
}
const tasks = new Listr([
{
title: 'Copy project files',
task: () => copyTemplateFiles(options),
},
{
title: 'Initialize git',
task: () => initGit(options),
enabled: () => options.git,
},
{
title: 'Install dependencies',
task: () =>
projectInstall({
cwd: options.targetDirectory,
}),
skip: () =>
!options.runInstall
? 'Pass --install to automatically install dependencies'
: undefined,
},
]);
await tasks.run();
console.log('%s Project ready', chalk.green.bold('DONE'));
return true;
}
ユーザがgit実行を選択すると、プロジェクトでgit initを実行し、負荷依存を選択するとnpm installまたはyarnを実行して依存をロードします./project/create-project rm -rf test-dir
/project/create-project mkdir test-dir
/project/create-project cd test-dir
/project/create-project/test-dir create-project typescript --git --install
✔ Copy project files
✔ Initialize git
✔ Install dependencies
DONE Project ready
wangyong@wangyongdeMacBook-Pro ~/Study/project/create-project/test-dir master
この時カタログで見ます.gitとnode_moduelsディレクトリ.
├── .git
│ ├── HEAD
│ ├── config
│ ├── description
│ ├── hooks
│ ├── info
│ ├── objects
│ └── refs
├── node_modules
│ └── esm
├── package-lock.json
├── package.json
└── src
ご成功おめでとうございます.最初のcliアプリを作成しました.アプリケーションを本物の他人が使えるモジュールにパッケージするには、srcディレクトリにindex.jsファイルを追加する必要があります.
require = require('esm')(module);
require('../src/cli').cli(process.argv);
次のステップこれまで完全なコマンドラインアプリケーションのパッケージを作成しましたが、自分だけでnpm linkを使ってグローバルに登録してください.あなたのアプリケーションを他の人に共有したい場合は、github npmでリリースするなど、npmで配布する方法を強く推奨します.package.jsonにfilesフィールドを追加して、そのファイルがリリースされることを確認してください.
},
"files": [
"bin/",
"src/",
"templates/"
]
}
npm pblishは自分のnpmバッグを発表します.関連記事