Node develops npm scaffolding (similar to vue-cli)

Node develops npm scaffolding (similar to vue-cli)

npm install tengyu-cli -g

The source code has been uploaded to code cloud: https://gitee.com/bingtengaoyu/tengyu_cli.git

1. Ideas for building scaffolding

  1. The purpose of building scaffolding

    In order to quickly build projects and modify configuration information to achieve the purpose of automated front-end engineering

  2. Ideas: two ways

    The first method: pull the code from GitHub, modify the configuration, you need to provide a downloadable template on GitHub, complete the initialization, unzip the zip package after downloading, then delete the zip package, modify the configuration file, configure the proxy, download dependencies, and start project;

     

    The second method: put the compressed zip template on the server, the scaffold downloads the corresponding template from the server, enter the configuration information according to the prompt, complete the initialization, unzip the zip package after downloading, delete the zip package, modify the configuration file, and configure the proxy , download dependencies, start the project

2. Initialize the project

npm init

3. Modify the package.json entry file

{
  "name": "tengyu-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",  // 入口文件
  "bin": {
    "tengyu": "index.js"
  },
  "scripts": {
    "serve": "node index.js",
    "dev": "node index.js",
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "gengbingbing",
  "license": "ISC",
  "dependencies": {
    "chalk": "^3.0.0",
    "commander": "^4.1.1",
    "cross-spawn": "^7.0.1",
    "download-git-repo": "^3.0.2",
    "handlebars": "^4.7.3",
    "inquirer": "^7.0.4",
    "log-symbols": "^3.0.0",
    "ora": "^4.0.3",
    "request": "^2.88.2"
  }
}

4. Download dependencies

npm install 

5. Start writing scaffolding (directly upload the source code)

index.js

#!/usr/bin/env node 
​const
program = require('commander'); //design command line 
const download = require('download-git-repo'); //github warehouse download 
const inquirer = require(' inquirer'); //Command line answer 
const handlebars = require('handlebars'); //Modify character 
const ora = require('ora'); //Load state flag in command line 
const chalk = require('chalk' ); //Command line output character color 
const logSymbols = require('log-symbols'); //Command line output symbol 
const fs = require('fs'); 
const request = require('request'); 
const { resolve } = require("path"); 
const install = require("./utils/install"); 
​console.log
(chalk.green(` 
                           tengyu cli commandgreen(`
    ------------------------------------------------------------
       tengyu init <template name> projectName | initialize project 
       tengyu -V | view version number     
       tengyu -h | view help       
       tengyu list | view template list   
       tengyu download | download zip template   
    --------------- --------------------------------------------- 
`)); 
/ / Available 
templates const templates = { 
    'react-npm-template': { 
        url: 'https://gitee.com/bingtengaoyu/reactAntd', 
        downloadUrl: 'https://gitee.com:bingtengaoyu/reactAntd#master', 
        description: 'react basic template' 
        url: 'https://gitee.com/bingtengaoyu/vueTools',
    },
    'vue-tools': { 
        downloadUrl: 'https://gitee.com:bingtengaoyu/vueTools#master', 
        description: 'vue common components' 
    } 
} 
​//
tengyu -V|--version 
program.version('1.0 .0'); // -v|--version output version number 0.1.0 
​//
tengyu init <template> <project> 
program 
    .command('init <template> <project>') 
    .description('initialization Project template') 
    .action((templateName, projectName) => { 
        console.log(templateName, templates); 
        let downloadUrl = templates[templateName].downloadUrl; 
        //Download github project, download wall loading prompt 
        const spinner = ora(' Downloading templates...').start();
        //The first parameter is the github warehouse address, the second parameter is the created project directory name, and the third parameter is clone 
        download(downloadUrl, projectName, { clone: ​​true }, err => { 
            if (err) { 
                console .log(logSymbols.error, chalk.red('Project template download failed\n Only templates in the list list can be downloaded')); console.log 
                (err); 
            } else { 
                spinner.succeed('Project template downloaded successfully '); 
                //Command line query 
                inquirer.prompt([ 
                    { 
                        type: 'input', 
                        name: 'appid', 
                        message: 'Please enter appid', 
                        default: '' 
                    }, 
                    { 
                        type: 'input', 
                        name: ' name', 
                        message: 'Please enter the project name', 
                        default: projectName 
                    },
                    {
                        type: 'input', 
                        name: 'description', 
                        message: 'Please enter a project introduction', 
                        default: '' 
                    }, 
                    { 
                        type: 'input', 
                        name: 'author',  
                        message: 'Please enter the author's name', 
                        default: ''
                    }
                ]).then(answers => { 
                    / / Modify the package.json file according to the command line answer result 
                    let packsgeContent = fs.readFileSync(`${projectName}/package.json`, 'utf8'); 
                    let packageResult = handlebars.compile(packsgeContent)(answers); 
                    fs. writeFileSync(`${projectName}/package.json`, packageResult); 
                    console.log(packageResult ) 
                    fs.writeFileSync(`${projectName}/config.js`, `module.exports = ${JSON.stringify(answers)}`); 
​console.log
                    (logSymbols.success, chalk.green('The project was initialized successfully , start downloading dependencies...')); 
​install
                    ({ cwd: `${resolve('./')}/${projectName}` }).then(data => { 
                        console.log(logSymbols.success , chalk.green('Project dependencies downloaded successfully!')); 
                    });
​//
                    Use chalk and log-symbols to change the command line output style
                }) 
            } 
        }) 
    }) 
​//
Download the zip template 
program.command 
    ('download')
    .description('Initialize project template') 
    .action((templateName, projectName) => { 
        inquirer.prompt([ 
            { 
                type: 'input', 
                name: 'project_name', 
                message: 'Please enter a project name', 
                default: ' tengyu-template' 
            }, 
            { 
                type: 'list', 
                name: 'template_name', 
                message: 'Please select a template to download', 
                choices: [ 
                    'react rapid development template', 
                    'vue toolset' 
                ], 
                default: ' react-npm-template'
            }
        ]).then(answers => {
            let url = ''
            switch (answers.template_name) {
                case 'react快速开发模板':
                    url = templates['react-npm-template'].url;
                    break;
                case 'vue工具集':
                    url = templates['vue-tools'].url;
                    break;
                default:
                    url = templates['react-npm-template'].url
            }
​
            function downloadFile(uri, fileName, callback) {
                var stream = fs.createWriteStream(fileName);
                request(uri).pipe(stream).on('close', callback);
            }
)
​
            downloadFile(url, `${answers.project_name}.zip`, function () {
                console.log(logSymbols.success, chalk.green(`${answers.template_name} downloaded!`)); 
                return 
            }); 
        }) } 
    ) 
​//
tengyu list 
program 
    .command('list') 
    .description( 'View all available templates') 
    .action(() => { 
        console.log(chalk.green(` 
                              tengyu template 
            ------------------------ ----------------------- 
                 react-npm-template react rapid development template   
                 vue-tools vue toolset 
            ------------ ----------------------------------- 
        `)) 
    }) 
program. parse(process. argv);

util-install.js file (for downloading dependencies)

Use the cross-spawn module to write custom cmd commands

const spawn = require("cross-spawn");
​
module.exports = function install(options) {
    const cwd = options.cwd || process.cwd();
    return new Promise((resolve, reject) => {
        const command = options.isYarn ? "yarn" : "npm";
        const args = ["install", "--save", "--save-exact", "--loglevel", "error"];
        const child = spawn(command, args, { cwd, stdio: ["pipe", process.stdout, process.stderr] });
​
        child.once("close", code => {
            if (code !== 0) {
                reject({
                    command: `${command} ${args.join(" ")}`
                });
                return;
            }
            resolve();
        });
        child.once("error", reject);
    });
};

So far a simple scaffold has been developed

After npm link, you can test run locally

6. Publish npm library

  1. Set up your own npm agent, do not set it as a Taobao agent, etc.;

  2. Go to npm to register your own account;

  3. Upload your own npm scaffolding

    npm login // log in 
    npm
    publish // push your own scaffolding to the npm library
  4. You're done, you can download your own npm plugin.

Guess you like

Origin blog.csdn.net/qq_23334071/article/details/105158728