When we use VUE to develop projects, we usually generate project templates directly from the command line, eg:
$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev
Copy the code
$ yarn create vite-app <project-name>
/ / is equivalent to
$ yarn global add create-vite-app
$ create-vite-app <project-name>
Copy the code
What if we wanted to create a CLI tool to manage our own project templates? Write a simple CLI tool here to pull defined templates from the command line.
At the beginning of construction projects
Create a directory and initialize it:
mkdir test-cli // Create directory
cd test-cli // Enter the directory
npm init -y // Initialize NPM
Copy the code
Then install any NPM packages you need:
npm install commander download-git-repo ora handlebars figlet clear chalk -s
Copy the code
Register global commands
We need to register a global command on the system environment.
New bin/index.js file:
mkdir bin
cd bin
touch index.js
// bin/index.js
#!/usr/bin/env node
// Specify the file interpreter
// Tell the operating system to call the node interpreter in the system environment when executing this file
console.log('test 111 ... ')
Copy the code
Add bin command to package.json:
{
"bin": {
"tcli": "./bin/index.js"
}
/ /...
}
Copy the code
/bin/index.js file./bin/index.js file./bin/index.js file
NPM link is a temporary global installation of the local package. It is equivalent to NPM install -g XXX, which causes global pollution and may cause global installation failure. Administrator permission is required.
Create node command
#! /usr/bin/env node
// Introduce a custom command component
const program = require('commander')
// Set the version number
program.version(require('.. /package').version)
// Set the init command with name as an argument
program.command('init <name>')
.description('init project') // Sets the description of the init command
.option('-s, --session'.'session param') // Set parameters
.action((name, params) = > { // Execute logic
console.log('params => ', name)
console.log('params.session => ', params.session)
})
// Command execution is actually initiated by commander parsing the process.argv argument
program.parse(process.argv);
Copy the code
Download the template
Modify the program.action method:
program.command('init <name>')
.description('init project')
.option('-s, --session'.'session param')
.action(require('.. /lib/init'))
Copy the code
New lib/init. Js
// lib/init.js
const { promisify } = require('util') // Convert the function to a promise format
const figlet = promisify(require('figlet')) / / font package
const clear = require('clear') // Console clear screen
const chalk = require('chalk') // Modify the style of strings in the console
const log = ctx= > console.log(chalk.green(ctx)) // Encapsulate log output
module.exports = async name => {
clear()
const data = await figlet('Hello ' + name)
log(data)
}
Copy the code
Create a new lib/download.js file to handle the template download logic:
// lib/download.js
const { promisify } = require('util')
/** * repo download path * desc download destination path */
module.exports.clone = async function(repo, desc) {
const download = promisify(require('download-git-repo')) // Download the component
const ora = require('ora')
const process = ora(` ⏳ download...${repo}`) // Display the loading effect, similar to the loading effect of a page
process.start()
await download(repo, desc)
process.succeed()
}
Copy the code
Modify lib/init.js, encapsulate spawn command, add download template in init initialization, install dependency
// Add clone
const { clone } = require('./download')
// Encapsulate the spawn command
// The child output stream imports the main output stream
const spawn = async(... args) => {const { spawn } = require('child_process')
const options = args[args.length - 1]
// If the operating system is Windows, change the shell to true
if (process.platform === 'win32') {
// Set the shell to true to implicitly call CMD
options.shell = true
}
return new Promise(resolve= > {
constproc = spawn(... args)// proc(child) -> process(master)
proc.stdout.pipe(process.stdout) // Standard output
proc.stderr.pipe(process.stderr) // Standard error output
proc.on('close', resolve)
})
}
module.exports = async name => {
// Print the welcome page
clear()
const data = await figlet('Hello ' + name)
log(data)
log('🚀 Create project ' + name)
await clone('github:554246839/project-template', name)
// Install dependencies
log('💣 Installation depends on...... ')
await spawn('yarn'['install'] and {cwd: `. /${name}` })
log('👌 Installation completed To get start ====================== CD${name}
yarn dev
======================
`)}Copy the code
I’m almost done here, so let’s see what it looks like.
Create a new directory somewhere else and perform download install:
If you want to download different templates, there are two ways:
Inquirer components
Inquirer is a tool for users to interact with the command line. New lib/confirm. Js:
// lib/confirm.js
const inquirer = require("inquirer")
module.exports.prompt = () = > {
return inquirer.prompt([
{
type: 'confirm'.name: 'simple'.message: 'use simple'.default: true})}// lib/init.js
/ / new
const { prompt } = require('./confirm')
/ / modify
module.exports = async (name, params) => {
// Print the welcome page
clear()
const data = await figlet('Hello ' + name)
log(data)
log('🚀 Create project ' + name)
const ans = await prompt()
console.log(ans, 'ans')
await clone('github:554246839/project-template', name)
// xxx
Copy the code
The options parameter
Create template.js template management file:
// lib/template.js
module.exports.templates = {
project1: 'github:554246839/project-template'.project2: 'github:554246839/project-template'.project3: 'github:554246839/project-template'
}
// lib/init.js
/ / new
const { templates } = require('./template')
function getParam(params) {
let p = Object.keys(params)
for (let i = 0; i < p.length; i++) {
if (params[p[i]]) {
return p[i]
}
}
}
/ / modify
module.exports = async (name, params) => {
// Print the welcome page
clear()
const data = await figlet('Hello ' + name)
log(data)
log('🚀 Create project ' + name)
await clone(templates[getParam(params) || 'project1'], name) / / modify
// Install dependencies
log('💣 Installation depends on...... ')
await spawn('yarn'['install'] and {cwd: `. /${name}`})
log('👌 Installation completed To get start ====================== CD${name}
yarn dev
======================
`)}Copy the code
GitHub:github.com/554246839/t… The master branch