Why you want to build your own scaffolding for a project

Let me give you an example:

  1. When colleague A was building a new project, he directly pulled the project template that he had pre-configured in the remote warehouse
  2. Colleague B is an experienced worker. He just copied the project he wrote and deleted some useless code, so he also built a new project
  3. Colleague c front-end novice players, chose vue-CLI and then step by step began to download the plug-in, add write configuration

Comparatively speaking, A’s method saves more time, but if there are some differences between the new project and the remote warehouse project, he still needs to manually modify these differences. B’s way, although not slow, but will lead to the new project in the residue of the old project residual code (to know how the new era will exist to carry the old era residual party ship – salute – white beard); However, the construction method of C can be imagined, which is very time-consuming.

Therefore, I wonder if there is a technical solution to solve the above problems, which is easy to operate and save time, but also make the new project more standardized. This is what you call a team booster. When I think about it, I feel like a fucking genius.

For this reason I named it the YWC – CLI Scaffolding solution. Yes, it’s a combination of my initials and CLI! The design ideas are as follows:

The simplest version: To optionally pull the preset template of the remote warehouse, you only need to install YWC-cli and run CMD script command yWC-cli create XXX to directly select the project template to be installed. Now I simply provide the initialization template of VUe2 and vue3, and I will improve these two templates later. I would also like to add the React project template.

Since I didn’t have much time left, I just implemented this version of the code.

Blow a wave benefit: This should be the most common and simplest level of scaffolding, only need to have a remote repository of different versions of the project template, after the installation of scaffolding developers can choose to install the version of the project, quickly set up the project. This kind of scaffold is suitable for customized projects, such as customized mall projects or data display projects and the backstage system of the Intranet. The feature of this kind of project is that the code reuse rate between different projects is very high while ensuring that the UI components remain roughly the same. Therefore, the company’s custom projects should have corresponding scaffolding, which can greatly shorten the development cycle of the project and standardize the code

Custom version: Executable to be verified

  1. The project template is preset in the scaffold. When executing the CREATE command, the first step is to select the template type and copy the template to a temporary directory. This step is usually to select the technical framework.

  2. This step involves preparing a mapping between the mapping file storage technology framework and the corresponding plug-in, as well as preparing the corresponding plug-in configuration code. The template in the temporary directory is rendered by the template engine based on the selected plug-in

  3. Generate project templates in temporary directories

The core idea of this most defined version is to render the configuration code of the corresponding plug-in through the template engine, which is not difficult to implement, but if the core of the process can be implemented through a utility class, that is the technical difficulty.

After a brief introduction to the technical solution idea, it is time to introduce the technical implementation. The related tools must be arranged first, of course, this scaffolding is based on Node.js implementation.

Scaffolding related tools


  1. inquirer.js

Provides a command line interface for Node.js that is easy to embed and beautiful. The popular explanation is the query tool, through which we can set up the scaffolding to ask the user some questions, such as whether to install the XXX tool, the project version number and so on

The installation

npm install inquirer
Copy the code

Usage: Call the inquirer. Prompt method. Prompt takes two parameters: qustionArray(array), which sets the question to be asked; The other is answer (object), which defaults to {} and if the answer to a question is set, the question will be skipped. The result of the execution is a Promise object. There are many types of questions, and I’m just showing the common input here.

Add the following code to the cli.js file:

var inquirer = require('inquirer');
inquirer.prompt([
    /* Setup problem */
    {
        type: 'input', 
        name: 'author',
        message: 'author'.default: ' ',
    },
    {
        type: 'input',
        name: 'version',
        message: 'version',
    }
],{version: '1.0.1'})
.then((answers) => {
  // Complete the query, execute the callback, where you can do some operations on the query result, etcconsole.log(answers); }).catch((error) => {
    if (error.isTtyError) {
      // Cannot be rendered in the current environment
        console.log('Cannot render in current environment');
    } else {
      // Other errors
        console.log('Other errors reported',error); }});Copy the code

One interesting thing about setting the problem type to input is that the Node environment will always receive a string, no matter what type of data we input. Therefore, when verifying numbers, you should use parseFloat, parseInt, or re instead of typeof.

Test Execution Result

  1. commander

Instruction tools, we can configure create and so on

The installation

npm install commander
Copy the code

usage

program
  .command('clone <source> [destination]')
  .description('clone a repository into a newly created directory')
  .action((source, destination) => {
    console.log('clone command called');
  });
Copy the code
  1. The handlebars, ejs

Template replacement tool (precompilation tool)

There are many kinds of template tools and you can choose the one you want.

  1. axios

Asynchronous request tool

This doesn’t have to be explained too much, but is often used in VUE. If we want to download the template file in the remote warehouse, it is necessary to request the address first, to obtain the remote template information (template file name/template version information, etc.), and then we can download the file after selecting

  1. download-git-repo

Download the remote file tool

With this tool, you can download the initialization template file you need based on your Git address.

  1. ora

Download tooltip

The installation

npm install ora
Copy the code

use

import ora from 'ora';
const spinner = ora('fetch template...... ');

spinner.start(); // Start loading

spinner.succeed(); // End loading loading
Copy the code

In use, encountered such a problem as follows:

Node.js introduced es6 modules in conflict with the common.js specification. So if you solve this problem, you solve the problem above.

We can check the current Node environment for ES6 support:

Install the es – the checker

npm -g install es-checker
Copy the code

In execution

es-checker
Copy the code

You can see the following results, although ES6 support is high, the ES6 module display is not supported.

Solution a:

Add information in package.json: type: “module”. I tried, but it didn’t work out.

Method 2:

Lower the ORA version and install [email protected]. This is probably the simplest way to do it. Since the latest version is exported as an ES6 module, we can drop the version down to a version that conforms to the common.js specification.

npm install ora@4.04.
Copy the code

In the meantime, we will change the way ORA is introduced.

- import ora from 'ora';
+ const ora = require('ora')

Copy the code

Method 3:

Configure Babel, which is known as a JavaScript compiler that converts code written in ECMAScript 2015+ syntax into a backward compatible JavaScript syntax so it can run in current and older browsers or other environments.

Improper configuration does not take effect to be improved!

I am really upset about this part. I have tried for a long time, but I still can’t deal with it well. At the same time, THERE is no guidance from Daniel

Scaffolding construction process

Scaffolding can be divided into three processes.

The first:

1. Initialize scaffolding 2. Set operation instructions installation project instructions and so on 3. Pulling project templates from remote repositories facilitates timely updates and makes projects more engineering and standardized. Set different templates for different types of projects, such as mobile H5 project and PC project; Or a template for a different front-end framework, like React or Vue 4. Release to NPM installation releases scaffolding to quickly build projects, greatly reducing project setup time.

The second:

1. Initialize scaffolding 2. Set operation instructions 3. Configure initialization information According to user input. 4. Configure functional plug-ins according to the size and type of the project according to the user’s choice. 5. * Expand the functions of scaffolding to achieve front-end automatic testing and other functions 6. Release to NPM

The third kind of

1. Initialize scaffolding 2. Set operation instructions 3. According to the user’s input, configure the initialization information 5. According to the user’s choice, configure the function plug-in 6. Release to NPM

Concrete implementation and code display

1. Initialize scaffolding

  1. Create project folder Yu -cli. Execute NPM init to create package.json file.
  2. Create the entry file cli.js.
type nul>cli.js
Copy the code
  1. Modify the package. The json.
{
  "name": "ywc-cli"./ / custom
  "version": "1.0.0"."description": ""."main": "cli.js",
+  "bin": "cli.js".// Import file
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "ywc"./ / custom
  "license": "ISC"
}

Copy the code
  1. Test whether the initialization scaffolding works.

Add test code to cli.js

#! /usr/bin/env node// This line must be added, otherwise the following execution will report an error. When the system is running on this line, go to env to find the Node configuration, and call the corresponding interpreter to run the subsequent Node program

console.log('my cli is working!!! ');
Copy the code

Execute NPM link. In case of correct operation, we execute yu-CLI on the console and can see the printed information

my cli is working!!!
Copy the code

If I hadn’t added this line #! If /usr/bin/env node generates an error, run NPM link –force to forcibly overwrite the node.

2. Set instructions

Configuration Instruction Information

const mapActions = {
    create: {
        alias: 'c'.description:'create a project'.examples: [
            'ywc-cli create <project-name>']},The '*': {alias: ' '.description: 'command not found'.examples: []}}Copy the code

If the command is executed, command not found is displayed. If the command is executed, the corresponding command is executed

Reflect.ownKeys(mapActions).forEach(action= > {
    program
        .command(action) // Configure the directive name
        .alias(mapActions[action].alias) // Directives alias
        .description(mapActions[action].description) // Command description
        .action(() = > {
            if(action === The '*') {
                console.log(mapActions[action].description);
            } else {
                // ywc-cli create xxx [node, ywc-cli, create, xxx]
                require(path.resolve(__dirname,'lib',action))(... process.argv.slice(3)); }})});Copy the code

3. Set the optional template

Here I know oneself in the remote configuration two template vue2template, vue3template, so can be statically configured, but this new template need to change the source code at a time. You can also use github’s API to get template types asynchronously and dynamically.

// The default template name
let tags = ['vue2template'.'vue3template']
const { tag } = await inquirer.prompt([/* Setup problem */{
    type: 'list'.name: 'tag'.message: 'please choose a template to create project'.choices: tags,
}]) 
Copy the code

4. Download the template

With the template name selected in the previous step, you can download the project template from the remote repository through download-git-repo. Before doing so, encapsulate loading

const ora = require('ora')

/ / encapsulates loading
const waitFnLoading = async(fn,message,... args) => {const spinner = ora(message);
    spinner.start(); // Start loading
    let repos = awaitfn(... args); spinner.succeed('succeed !'); // End loading loading
    return repos
}

module.exports = {
    waitFnLoading: waitFnLoading
}
Copy the code

Download and generate the file

// Download the template from the remote repository
// tag: template name; ProName: Project name; Sign: indicates whether to use it as a temporary file
const downloadTemplate = async(tag, proName ,sign)=>{
    let api = 1842347744 / `${tag}`;
    let pro = sign ? `${downloadDirectory}/${tag}` : proName;
    let repo = await downLoadGitRepo(api,pro);
    // Later versions will use it
    return repo;
}

Copy the code

About the next version

The new feature is to install plug-ins according to the user’s choice

The vuEX installation and configuration is as follows:

Configure the vuex related initialization template file in the scaffold, and write it to the project to be generated after the user decides to install vuex.

  1. Configure the vuex.js template
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {},mutations: {},actions: {},modules: {}})Copy the code
  1. Configure question items and generate vuEX key code:

In this case, the default true means that vuex is approved. Temp /vuex.js template file is read from fs.readfilesync and written to the project using fs.writefile

inquirer.prompt([{
    type: 'confirm'.name: 'vuex'.message: 'Whether to use vuex'.default: true,
}]).then(answer= > {
    if(answer.vuex) {
        // Read the template
        const data = fs.readFileSync(path.resolve(__dirname,'temp/vuex.js'));
        // Create the store folder
        fs.mkdirSync(path.resolve(__dirname, '.. /test/src/store'))
        // Create index.js from the template file
        fs.writeFile(path.resolve(__dirname,'.. /test/src/store/index.js'), data,(err) = >{
            if(err) {
                console.log('failure');
            } else {
                console.log('success'); }})}})Copy the code

Here I just briefly show you how to configure the plugin by reading and writing to FS, but you can also render using the template engine.


This is the end of the article. At present, we can only say that the simplest version of yWC – CLI has come to an end. I will continue to update the version after the new owner is found.

Installation package has been released to NPM, can be directly installed and used, at the same time the source code is also shared to github source code is very simple, interested partners can pull down to have a look, would like to encourage each other! ^_^