01 preface

It’s just that you’re in front-end development and programmers of all levels have used vue or React scaffolding. In today’s post, let’s build our own scaffolding from scratch.

What is a scaffold for?

In the case of VUE, every time we initialize a project using scaffolding, there is already a lot of code in it. This is the standard project that scaffolding initializes for us. In other words, scaffolding does repetitive, standardized things for us.

Why do we build our own scaffolding when we already have the official one?

1. Scaffolding will customize a standardized project for us, so we may have our own customization requirements in the actual business line. If it’s ok to occasionally customize a project, if the company adopts the standard for several projects, then the customized standard project can be understood internally as standardization. Since it is standardized, it is necessary to make a standard (scaffolding). 2. Study. The best way to know your enemy is to join him. The best way to learn how to use a technology is to implement it.

Don’t say more, do it!!

02 Function Description

Know yourself and know your enemy, and you can win a hundred battles. We realize a scaffold, first to know what he can have what functions, to try to do these functions:

1. Identify the console input

2. Console interaction

3. Download our template project

Identify the console input

Similar to what we typed –help on the console, the console needs to understand what we typed

Console interaction

When we create a project using vue Create Name, we are given the choice between default creation and configuration creation. If you choose to create a configuration version, you will also be given the option to configure vuex, VUE-Router, ESLint, etc.

Download our template project

When we finish the selection, we will download, download failure judgment, disconnection operation and so on.

03 Project Structure

Create a directory cuteXuan-cli

NPM init -y create bin, lib folders

Create file Xuan in bin and write the following information

#! /usr/bin/env node 
console.log("hello cuteXuan-cli")
Copy the code

At this point we can modify our package.json file by adding the bin property to it

"Name" : "cuteXuan - cli", "version" : "1.0.0", "description" : ""," main ":" index. Js ", "bin" : {" cuteXuan - cli ": "./bin/xuan", "xuan": "./bin/xuan" },Copy the code

At this point our basic structure is set up, and it’s time to perform the most important step: open our console, or terminal. Execute the following command

NPM link --force NPM link --force if you have done this beforeCopy the code

If your console is anything like mine, congratulations, you’ve made the most important step. We have put our own package (scaffolding) into the global NPM. That is, at this point, you can manipulate its commands globally, just as you can with the Vue and React scaffolding. Note: The command is the bin property we configured in the package.json file. CuteXuan – CLI and Xuan are available.

If you make it this far, congratulations, your scaffolding is half done.

04 Use Commander to resolve input parameters

npm i commander
Copy the code

We usually use vue create XXX

Vue –version vue –help commands. If you want to perform further operations, you need to parse the user’s input parameters. Of course, abbreviations such as -v and -h should also be considered. Of course, we can do all of this with Commader.

#! /usr/bin/env node const program = require('commander') // Program.command ('create <app-name').description('create a new project').option('-f, --force','overwrite target directory if it exists') .action((name,cmd) => { console.log(anme,cmd) }) // xuan -v program .version(`cuteXuan-cli @${require('.. /package.json').version} ').usage(' <command> [option] ') // Parse (process.argv)Copy the code

Xuan Create XXX Description Some descriptors Option Some parameter configurations and short form Action What will be done after the correct command is entered

In action, name is the command and CMD is the parameter, but it is not only our parameter 🈶️, but also various default parameters. This requires parameter cleaning:

const clearArgs = (cmd) => {
    const args = {}
    cmd.options.forEach(element => {
        const key = element.long.slice(2)
        if (cmd[key]) {
            args[key] =cmd[key]
        }
    });
    return args
}

Copy the code

At this point, we can get the correct name and CMD in our action.

Of course, a scaffold will have a lot of these kinds of commands, the rest is basically drudgery. Here we only write the most important Xuan Create name and Xuan –version

Use Inquirer to interact with users

NPM I Inquirer We will encounter downloading different versions in real projects. For example, we will use different versions of Node. This is where the configuration is needed. Another example is that we need to advance some libraries for our new project, such as vuex and VuE-Router.

Of course, as mentioned earlier, we also need to make a version selection, this time we need to go to our code management address, get our version library list. Making an example: api.github.com/users/haimi…

async getTags() { let tags = await fetchTagList() if (! tags) { return } tags = tags.map(item => item.name) let {tag} = await Inquirer.prompt({ name: "tag", type: 'list', choices: tags, message: "please choose a tag to create project" }) return tag }Copy the code

Type: ‘list’ in the above code will display our tags as a list. And returns the tags of your choice.

Of course, the configuration (vuex, vue-Router) list also means the same thing, except that it becomes multi-choice, so consider giving it a try yourself!!

At this point, we have selected the project version, and we have also selected the project configuration. Next, you can monetize your choice by downloading it locally. NPM install download-git-repo It is worth mentioning that download-git-repo itself does not support Promises.

const downloadGitRepo = require('download-git-repo')
const util = require('util')
const newDownloadGitRepo util.promisify(downloadGitRepo)
Copy the code

With this approach, you can make download-Git-repo support the Promise form.

/** ** @param {*} repo template * @param {*} Tag template version */ async Download (repo,tag) {let requestUrl = `zhu-cli/${repo}${tag? '#'+tag:''}` await this.downloadGitRepo(requestUrl,path.resolve(process.cwd),`${repo}@{tag}`) return this.target }Copy the code

At this point, the scaffolding for a simple version is set up, posted on NPM, and ready to be used by others inside and outside the company. Of course, real scaffolding is much more complicated than that, and we’ve just implemented a very simple scaffold.

07 summary

At the beginning of the feature introduction, you may have been a little confused by reading this. Let’s review the CLI. Initialize the project and use the NPM link to link the scaffolding we developed to the global NPM. Use Commander to parse user input so that you can react to user input and interact with the user using Inquirer. If there is no interaction and there is no need for us to build scaffolding, isn’t it convenient to give a link directly? Use download-git-repo to download the selected content locally

If you find this article helpful, please like 👍 and follow it!!