1. Scaffolding definition

Scaffolding is to ensure the smooth construction process and set up the work platform. For us front-end programmers, it helps us code better and more efficiently.Copy the code

2. Common commands for scaffolding

  1. First we will create a project: bob_cli, init the bob_cli folder to initialize the project, and create a lib folder and index.js file

  1. Install commander package, used to parse console input commands, go to NPM search, detailed instructions

  1. Custom execution entry file, as shown below. You can use Bob instead of index.js later. NPM Link then enables Bob to do the correlation mapping

4. Write the following code in index.js

                                    index.js
  #!/usr/bin/env node

const { program } = require("commander");
const { helpOptions } = require("./lib/core/help");
// Get the version number
program.version(require("./package.json").version);
helpOptions();
// Parse the console instructions
program.parse(process.argv);
                                ./lib/core/help.js                             
 const { program } = require("commander");
 // Custom options
const helpOptions = () = > {
  program.option("-s, --small"."small pizza size");
  program.option(
    "-d --dest <dest>"."a destination folder, like: -d /src/components"
  );
  // You can also customize event listening
  program.on("--help".function () {
    console.log("");
    console.log("Other:");
    console.log(" other options~");
  });
};
Copy the code
  1. Type Bob –help, Bob –V on the console and see the following output. Some options have not been done, there are needs to be improved later.
Options:
  -V, --version                 output the version number
  -s, --small                   small pizza size
  -d --dest <dest>              a destination folder, like: -d /src/components
  -h, --help                    display help for command
  Other:
  other options~
  commaner -V
1.0. 0
Copy the code

3. What scaffolding does

For example, we often use vue-CLI. When we hit Vue-cli Create Project, what does it do for us?Copy the code
  1. You can select the required configuration items, such as vuE-Router, VUEX, and CSS preprocessor.
  2. Installation requirements depend on the engineering environment.
  3. Enter the NPM Run Serve startup project.
  4. Open your browser and type in the url.

Now let’s configure each of these four steps one by one

  1. Now let’s skip the process of user interaction selection and customize a generic template with the download-Git-repo package installed. Address: gitlab.com/flippidippi…
  2. Parsing console commands, such as Bob Create Demo01, we create a demo01 folder and place the downloaded template files in it
                            bob_cli\lib\core\action.js
                            
  //create project
  program
    .command("create 
      
        [others...] "
      )
    .description("clone a repository into a newly created directory")
    .action(createProjectAction);
    
    
                           bob_cli\lib\core\action.js
                   
  //callBack ==> promisify ===>promise ==> async/await
const createProjectAction = async (project) => {
  //1. Clone project
  await download(vueRepo, project, { clone: true });

  // 2. Run NPM install
  / / compatible with Windows
  const command = process.platform === "win32" ? "npm.cmd" : "npm";
  await commandOptions(command, ["install"] and {cwd: `${project}` });

  / / 3. Serve
  await commandOptions(command, ["run"."serve"] and {cwd: `${project}` });

  //4. Open a browser
  open("http://localhost:8080");
};

                            bob_cli\lib\config\repo-config.js
                            
 Direct +git HTTP address +# branch name
 // Here is a sample of Coderwhy's VUE template
let vueRepo = 'direct:https://github.com/coderwhy/hy-vue-temp.git#master';
module.exports = {
  vueRepo,
};                   

                            bob_cli\lib\utils\terminal.js
/** * Execute terminal command related code */
// Start the child process
const { spawn } = require("child_process");

const commandOptions = (. args) = > {
  return new Promise((resolve, reject) = > {
     console.log("ready to create project ");
    constchildProcess = spawn(... args);// Outputs the child's output to the current console
    childProcess.stdout.pipe(process.stdout);
    childProcess.stderr.pipe(process.stderr);
    // The listener child is finished
    childProcess.on("close".(code) = > {
      console.log(`child process exited with code ${code}`);
      resolve()
    });
  });
};
Copy the code
  1. To open the required package for the browser, run NPM Install Open.
  2. Note to start the serve code, run the same command according to the script in package.json

5. Finally, the demo01 project directory is displayed, and the browser opens automatically

4. Automatically generate component and routing files

4.1 Generating Components

  1. At this point we will use the EJS package to parse ejS syntax. npm i ejs
  2. Prepare the component template vue-component.ejs
                                 bob_cli\lib\templates\vue-component.ejs 
<template>
  <div class="<%= data.lowerName %>">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: '<%= data.name %>'.props: {
    msg: String
  },
  components: {},mixins: [].data: function() {
    return {
      message: "<%= data.name %>"}},created: function() {},mounted: function() {},computed: {},methods: {}}</script>
<style scoped>
  .<%= data.lowerName %> {
    
  }
</style>
                                 bob_cli\lib\core\create.js

program
    .command("addcpn <name>")
    .description(
      "add vue component, like:addcpn HelloWorld [-d src/components]"
    )
    .action((name) = > {
     const options = program.opts();
      addCpnAction(name, options.dest || "src/components");
    });
                                 bob_cli\lib\core\action.js       
    
    const addCpnAction = async (name, dest) => {
  //1. Compile ejS template result
  const result = await compile("vue-component.ejs", {
    name,
    lowerName: name.toLowerCase(),
  });
  console.log(result);

  //2. Write to folder
  // Create one.
  
  if (createDirSync(dest)) {
  const targetPath = path.resolve(dest, `${name}.vue`); writeToFile(targetPath, result); }}; bob_cli\lib\utils\utils.js// Parse the component template into a string and write it to the destination folder
const compile = (templateName, data) = > {
  const fileOption = `.. /templates/${templateName}`;
  const filePath = path.resolve(__dirname, fileOption);

  return new Promise((resolve, reject) = > {
    ejs.renderFile(filePath, { data }, {}, (err, str) = > {
      if (err) {
        reject(err);
        return;
      }
      resolve(str);
    });
  });
};

const writeToFile = (path, content) = > {
  return fs.promises.writeFile(path, content);
};

  /** * Recursively create folders that do not exist *@param {file with suffix in pathname} pathName 
 * @returns * /
const createDirSync = (pathName) = > {
    if (fs.existsSync(pathName)) {
      return true;
    } else {
      if (createDirSync(path.dirname(pathName))) {
        fs.mkdirSync(pathName);
        return true; }}}Copy the code
  1. Go to demo01 and run Bob addcpn goods -d pages/goods. You can see that pages is generated under Demo01 and all ejS templates in demo01 are replaced with component names

4.2 Generate module folders and module routing files

  1. The same idea is used to generate components. Prepare the EJS template for the router
                                bob_cli\lib\templates\vue-router.ejs
                        
// Common load route
// import <%= data.name %> from './<%= data.name %>.vue'
// Lazy route loading
const <%= data.name %> = () = > import('./<%= data.name %>.vue')
export default {
  path: '/<%= data.lowerName %>'.name: '<%= data.name %>'.component: <%= data.name %>,
  children: [
  ]
}
                               bob_cli\lib\core\create.js
                               
program
    .command("addpage <page>")
    .description(
      "add vue page and router config, like: why addpage Home [-d src/pages]"
    )
    .action((page) = > {
    const options = program.opts();
      addPageRouteAction(page, options.dest || "src/pages");
    });
    
                               bob_cli\lib\core\action.js
    
    //b. Create a file and route
const addPageRouteAction = async (name, dest) => {
  //1. Compile ejS template result
  const pageResult = await compile("vue-component.ejs", {
    name,
    lowerName: name.toLowerCase(),
  });

  const routerResult = await compile("vue-router.ejs", {
    name,
    lowerName: name.toLowerCase(),
  });
  // Make a concatenation between the target folder and the component folder.
  const targetPath = path.resolve(dest, name.toLowerCase());
  // Check if there is a folder.
  if (createDirSync(targetPath)) {
    //2. Write to folder
    //program. Dest 
      
    const targetPagePath = path.resolve(targetPath, `${name}.vue`);

    const targetRouterPath = path.resolve(targetPath, "router.js"); writeToFile(targetPagePath, pageResult); writeToFile(targetRouterPath, routerResult); }}; bob_cli\lib\utils\utils.js// Parse the component template into a string and write it to the destination folder
const compile = (templateName, data) = > {
  const fileOption = `.. /templates/${templateName}`;
  const filePath = path.resolve(__dirname, fileOption);

  return new Promise((resolve, reject) = > {
    ejs.renderFile(filePath, { data }, {}, (err, str) = > {
      if (err) {
        reject(err);
        return;
      }
      resolve(str);
    });
  });
};

/** * Recursively create folders that do not exist *@param {file with suffix in pathname} pathName 
 * @returns * /
const createDirSync = (pathName) = > {
    if (fs.existsSync(pathName)) {
      return true;
    } else {
      if (createDirSync(path.dirname(pathName))) {
        fs.mkdirSync(pathName);
        return true; }}}const writeToFile = (path, content) = > {
  return fs.promises.writeFile(path, content);
};
    
Copy the code
  1. Console input command Bob addpage register -d SRC /views/pages to see the output, so that you do not need to manually register routes and components module by module

4.3 Generating a VUEX Module

The procedure is as follows: 4.2 Consistency. I don’t paste code again and again.

5. Package and publish to NPM

  1. First go to the official website to register an NPM account

  1. Configure the published package in vscode
// The package name to publish
"name": "bobvue_cli"."version": "1.0.0"."description": "a "."main": "index.js"."bin": {
  // Scaffolding command
    "bobvue_cli": "index.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "bob".// Calculate the algorithm keyword
  "keywords": ["vue-cli"."vue"."vue-template"."vue3"].// Github is located in the repository
  "homepage": "https://github.com/xiaoboRao/bobvue_cli"."repository": {
    "type": "git"."url": "https://github.com/xiaoboRao/bobvue_cli"
  },
Copy the code
  1. In vscode release package, execute NPM login, input the registered account, password, email, the first login will prompt OTP, NPM will send a verification code to the registered email, input can login

  1. Then go to NPM to download the package and verify that the final result is as expected.

6. Attach GitHub address and NPM address

Making: [https://github.com/xiaoboRao/bobvue_cli] (bobvue_cli) NPM: [https://www.npmjs.com/package/bobvue_cli] (bobvue_cli)Copy the code