current position:Home>[Youth Camp Pro] - implement a front-end agreed routing project scaffolding tool from 0 to 1~

[Youth Camp Pro] - implement a front-end agreed routing project scaffolding tool from 0 to 1~

2022-01-29 15:24:12 YK bacteria

Little knowledge , Great challenge ! This article is participating in “ A programmer must have a little knowledge ” Creative activities .

This article has participated in 「 Digging force Star Program 」, Win a creative gift bag , Challenge creation incentive fund .

Preface

Today, let's review & Summarize the course of the first day of the youth training camp practical class , That is to say Uncle ran of the whole stack It brings Node Basics Api And CLI actual combat Course .

I recently studied the blogs of various leaders in the Nuggets community , I found that some diggers blog with some expression , I'll try it, too , Some digging friends will add some in front of boring knowledge Little story , Why don't I try ?️ Yes, see here, today's little story is over , Let's start with the text ~

Today, I will learn how to create my own scaffolding tool ️, This can avoid writing small letters every time demo Various repeated configurations shall be carried out during the ️. Finally, we publish to npm Warehouse , Let the friends around you also use the tools you write ~ In fact, what we need to learn today is a kind of automation Thought , This is also Front-end engineering An important part .

This paper starts from ① Node Basics To ② Scaffolding To ③ npm Warehouse upload , Completely from 0 To 1 To build the wheels , A small partner without foundation can understand ~ PS: This is the first one , There is another article later We use it happy-path The coding method of small steps is to write another koa Scaffolding tools , You'll get more ~~ give the thumbs-up The more updates, the faster ️

The relevant code is here gitee.com/ykang2020/y…

PS: My nonsense is really much .......

One 、Node Basics API

In the basic class of youth training camp , We learned some Node.js The basic concept of , Today, let's learn about Node.js Some of the foundations of API, Pave the way for our later practice ‍*️ ‍ ~

PS: The course notes of the basic class are posted here :

node.jsAPI Official documents chinese :nodejs.cn/api/ english :nodejs.org/dist/latest…

The core API - There is no need to require

  • buffer
  • module
  • process

built-in API - need require There is no need to install

  • os
  • fs
  • path
  • http
  • event

1. fs And asynchronous IO

Reference resources :nodejs.cn/api/fs.html as well as nodejs.org/dist/latest…

First introduce fs File module

const fs = require("fs");
 Copy code 

① Read files synchronously

//  Synchronous read 
const data = fs.readFileSync("./04_buffer.js");
console.log("data", data.toString());
 Copy code 

Here, if you don't call data Of toString() Method , The result will return a buffer , Because for computers , All the files it stores are binary files

Use data Of toString() The method is to press the binary file by default utf-8 Convert to text , That is, the default call toString('utf-8')

② Asynchronous read file

Error first callback function , File processing in callback function

fs.readFile("./04_buffer.js", (err, data) => {
  if (err) throw err;
  console.log(data.toString());
})
 Copy code 

We know that asynchronous operation in the form of callback is not good , We all use promise 了 , So it's natural to think about whether asynchronous files can be read promise Style API have access to , And then you can use it async/await To use asynchronous file operations

Node.js Provides Promise Style fs File operations API, Documents available

image.png

③ promisify

stay Node.js Of util A method is provided in promisify , You can modify the callback method to promise Style API, You can use async/await The grammar

(async () => {
  const fs = require("fs");
  const { promisify } = require("util");
  const readFile = promisify(fs.readFile);
  
  const data = await readFile("./04_buffer.js");
  console.log(data.toString());
})();
 Copy code 

2. buffer And character set

buffer Which translates as buffer

Allocate one 10 Bytes of buffer

const buf1 = Buffer.alloc(10)
console.log(buf1) // <Buffer 00 00 00 00 00 00 00 00 00 00>
 Copy code 

Print out and see , Easy to display and read , Converted to hexadecimal , Of course, the bottom layer is binary storage

Use buffer Store an English text , One letter, one byte

const buf2 = Buffer.from('yk')
console.log(buf2) //<Buffer 79 6b>
 Copy code 

Use buffer Store a Chinese character , A text has three bytes (utf-8)

const buf3 = Buffer.from(' bacteria ')
console.log(buf3) // <Buffer e8 8f 8c> utf-8/16/32
 Copy code 

You can connect two buffer

const buf4 = Buffer.concat([buf2, buf3])
console.log(buf4, buf4.toString()) // <Buffer 79 6b e8 8f 8c> yk bacteria 
 Copy code 

I've said before , Use toString Method to display text

3. http

Use http Module quickly write a http The server

const http = require("http");

http
  .createServer((request, response) => {
    console.log("a request");
    response.end("Hi YK bacteria ");  //  This end Not so good , Hard to understand 
  })
  .listen(3000, () => {
    console.log("Server at 3000");
  });
 Copy code 

image.png

Let's take a look at the prototype chain , Let's define a function first , To get the prototype chain of the object

function getPrototypeChain(obj) {
  const protoChain = [];
  while ((obj = Object.getPrototypeOf(obj))) {
    protoChain.push(obj);
  }
  return protoChain;
}
 Copy code 

Let's see request and response Prototype chain of

const http = require("http");

http
  .createServer((request, response) => {
    console.log(
      "a request",
      getPrototypeChain(request),
      getPrototypeChain(response)
    );
    response.end("Hi YK node");
  })
  .listen(3000, () => {
    console.log("Server at 3000");
  });
 Copy code 

request Prototype chain of

image.png

response Prototype chain of

image.png

You can find request And response It's all inherited Stream Of

We'll discuss this later , We continue to use our http Module to build the server

Let's go back to one index.html file , This uses what we said above fs File read API 了

const fs = require("fs");
const http = require("http");

http
  .createServer((request, response) => {
    const { url, method } = request;
    console.log("url:", url);
    if (url === "/" && method === "GET") {
      fs.readFile("index.html", (err, data) => {
        if (err) {
          response.writeHead(500, {
            "Content-Type": "text/plain;charset=utf-8",
          });
          response.end("500  The server is down , brother !!!");
        }
        response.statusCode = 200;
        response.setHeader("Content-Typr", "text/html");
        response.end(data);
      });
    } else {
      response.statusCode = 400;
      response.setHeader("Content-Type", "text/plain;charset=utf-8");
      response.end("404  I can't find it !");
    }
  })
  .listen(3000, () => {
    console.log("Server at 3000");
  });
 Copy code 

practice 1 node Basics fs\buffer\http Building a http service

Write a http The server , return index.html

 Wechat screenshot _20210920104152.png

If our index.html The file added a img label , Introduced a picture , What should we do with ? Direct use readFile Can I read ? Pictures are generally large , This will consume a lot of memory resources , Don't use... Directly readFile Read , Because it needs to load all the picture content into the server .

What should that use ? Let's introduce the following Stream The concept of flow

4. stream

Copy a picture locally

const fs = require("fs");
//  Picture reproduction   Use  fs read+write It's fine too , But you need to read into memory and then write out from memory 

//  Let's do it another way 
const rs = fs.createReadStream("./YK bacteria .jpg");
const ws = fs.createWriteStream("./YK Bacterial separation .jpg");

//  The Conduit , File stream , Flow from one file to another 
rs.pipe(ws);
 Copy code 

File stream , Flow from one file to another

image.png

So we can write code like this

const fs = require("fs");
const http = require("http");

http
  .createServer((request, response) => {
    const { url, method } = request;
    console.log("url:", url);
    if (url === "/" && method === "GET") {
      fs.readFile("index.html", (err, data) => {
        if (err) {
          response.writeHead(500, {
            "Content-Type": "text/plain;charset=utf-8",
          });
          response.end("500  The server is down , brother !!!");
        }
        response.statusCode = 200;
        response.setHeader("Content-Typr", "text/html");
        response.end(data);
      });
    } else if (url === "/users" && method === "GET") {
      response.writeHead(200, { "Content-Type": "application/json" });
      response.end(JSON.stringify({ name: "yk bacteria " }));
    } else if (method === "GET" && headers.accept.indexOf("image/*" !== -1)) {
      //  Get all the pictures 
      //  Don't use... Directly readFile Read ,  Because it needs to load all the picture content into the server 
      //  Use   flow  stream !!!!
      fs.createReadStream("." + url).pipe(response);
    } else {
      response.statusCode = 400;
      response.setHeader("Content-Type", "text/plain;charset=utf-8");
      response.end("404  I can't find it !");
    }
  })
  .listen(3000, () => {
    console.log("Server at 3000");
  });
 Copy code 

stay index.html Add images , Then, when the server returns the picture, it returns it in the form of stream , This saves memory

image.png

5. Subprocesses

child_process The module gives Node You can create subprocesses at will (child_process) The ability of .

It provides 4 Methods for creating child processes .

  • spawn(): Start a subprocess to execute the command .
  • exec(): Start a subprocess to execute the command , And spawn() The difference is that the interface is different , It has a callback function that knows the status of the subprocess .
  • execFile(): Start a subprocess to execute the executable .
  • fork(): And spawn() similar , The difference is that it creates Node The subprocess of only needs to specify the JavaScript File module .

Two 、 actual combat : Realization cli Tools

The goal is : Use what we've learned Node.js Knowledge , Implement a scaffolding tool of your own , Scaffolding is used to quickly create a project , A template project that will automatically generate front-end routes . We call it the Contract route

1. initialization

Create a new project directory , And initialization

mkdir vue-auto-router-cli
cd vue-auto-router-cli
npm init -y
 Copy code 

Create a folder bin, And then create a yk.js file , As an entry file

To make the global available yk Instructions , stay package.json Add this configuration item

"bin": {
  "yk": "./bin/yk.js"
},
 Copy code 

stay yk.js Add... To the head , Used to specify that the interpreter type is node

#!/usr/bin/env node
console.log(' Welcome to use YK Bacterial  cli  Tools ');
 Copy code 

Finally, don't forget link once

npm link
 Copy code 

At this time, execute... In the console under any directory yk Instructions You can use it backstage node perform yk.js file

image.png

2. Customize the command line page

Next, let's customize our own command line page

#!/usr/bin/env node
console.log(" Welcome to use YK Bacterial  cli  Tools ");
console.log(process.argv);
 Copy code 

image.png

You can see , The information entered by the user is saved in process.argv in

Let's install all the third-party libraries we need to use next

npm i commander download-git-repo [email protected]5 handlebars figlet clear chalk open -s
 Copy code 

Here we use a third-party library commander To customize our command line

our yk.js Written like this

#!/usr/bin/env node
// console.log(" Welcome to use YK Bacterial  cli  Tools ");
// console.log(process.argv);
const program = require("commander");

program.version(require("../package.json").version);

program
  .command("init <name>")
  .description("init project")
  .action((name) => {
    console.log("init " + name);
  });
program.parse(process.argv);
 Copy code 

Now use our yk Instructions , It's like something ~

image.png

3. Customize the welcome interface of the initialization project

We will program.action It's impossible to print only one sentence in , Let's pull out the logic of initializing the project

program.action(require("../lib/init"))
 Copy code 

Let's create a file lib/init.js

//  Print welcome interface 
const { promisify } = require("util");
const figlet = promisify(require("figlet"));
const clear = require("clear");
const chalk = require("chalk");
//  Encapsulate a that outputs green text API
const log = (content) => console.log(chalk.green(content));

module.exports = async (name) => {
  //  Print welcome interface 
  clear();

  const data = await figlet.textSync("YK!Welcome");
  log(data);
}
 Copy code 

At this time to use yk When initializing a project , The welcome page will appear ~

image.png

Of course, the style of the text here can be customized Look at the documentation www.npmjs.com/package/fig…

Here I'll just configure a font style ~

const data = await figlet.textSync("YK!Welcome",{
  font: "Ghost",
  horizontalLayout: "default",
  verticalLayout: "default",
  width: 200,
  whitespaceBreak: true,
});
 Copy code 

image.png

4. Download the code template

Let's create a new file to handle the logic of downloading the code template

newly build lib/download.js

const { promisify } = require("util");

module.exports.clone = async function (repo, desc) {
  const download = promisify(require("download-git-repo"));

  const ora = require("ora"); //  Progress bar 
  const process = ora(` download .......${repo}`);

  await process.start();
  await download(repo, desc);
  process.succeed();
};
 Copy code 

Two libraries are used here download-git-repo Library is used to download code templates and ora The library is used to display the download progress bar ( So here's what we installed 5 edition , The latest is 6 edition , Why not use the latest version , Because the latest version only supports ESM Modular Introduction )

stay GitHub Prepare a code template above

image.png

stay init.js Just introduce and use the download module

const { clone } = require("./download");

module.exports = async (name) => {

  log(" Create project " + name);
  //  there git The warehouse can specify itself 
  await clone("github:yk2012/vue-template", name);
};

 Copy code 

image.png

You can see that the file has been downloaded to the current directory

image.png

5. Automatically install project dependencies

stay Node.js Use child processes in child_process Installation dependency

Create a child process to install promise Style interface , Then merge the flow of the child process into the main process

const spawn = async (...args) => {
  //  Sync Promise api
  const { spawn } = require("child_process");
  return new Promise((resolve) => {
    
    // windows System compatibility processing 
    const options = args[args.length - 1];
    if (process.platform === "win32") {
      options.shell = true;
    }

    const proc = spawn(...args);
    //  Output stream   Subprocesses   Merge into   The main process 
    proc.stdout.pipe(process.stdout);
    proc.stderr.pipe(process.stderr);
    proc.on("close", () => {
      resolve();
    });
  });
};
 Copy code 

Note that there is a processing in the middle Windows Code for compatibility problems .

Call subprocess to install dependency ( Is to execute under the project directory npm install

//  Download dependency  npm i
//  Subprocesses 
// spawn("npm", ["install"]);
log(` Installation dependency ....`);
await spawn("npm", ["install"], { cwd: `./${name}` });
 Copy code 

6. Configure auto open service

  log(
    chalk.green(
      `  installation is complete : To get Starat : ================================ cd ${name} npm run serve ================================ `
    )
  );
  open("http://localhost:8080/");
  await spawn("npm", ["run", "serve"], { cwd: `./${name}` });
 Copy code 

A complete demonstration

image.png

Auto jump link , Open the front-end project page

image.png

7. Implement agreed routing

according to views Pages in the directory , Automatically generate routes , in other words , We are views Add a new component under the directory , And then execute the command , The route will be automatically configured on the page , This is also a commonly used function in development ~ No manual configuration , The program is automatically configured, which is not very fragrant ~~

stay lib Create in folder refresh.js file , Write our code logic here

//  Read file list 

//  Spell code . The way of template rendering 

const fs = require("fs");
const handlebars = require("handlebars");
const chalk = require("chalk");

module.exports = async () => {
  //  To obtain a list of 
  const list = fs
    .readdirSync("./src/views")
    .filter((v) => v !== "Home.vue")
    .map((v) => ({
      name: v.replace(".vue", "").toLowerCase(),
      file: v,
    }));

  //  Generate route definition 
  compile({ list }, "./src/router.js", "./template/router.js.hbs");
  //  generate menu 
  compile({ list }, "./src/App.vue", "./template/App.vue.hbs");

  /** * * @param {*} meta  Data definition  * @param {*} filePath  Target file  * @param {*} templatePath  Templates  */
  function compile(meta, filePath, templatePath) {
    if (fs.existsSync(templatePath)) {
      const content = fs.readFileSync(templatePath).toString();
      const result = handlebars.compile(content)(meta);
      fs.writeFileSync(filePath, result);
      console.log(chalk.green(`${filePath} Create success `));
    }
  }
};
 Copy code 

stay yk.js Add this instruction to the file

program
  .command("refresh")
  .description("refresh routers...")
  .action(require("../lib/refresh"));
 Copy code 

We are new in views Create a new component under the folder Yk.vue

And then execute yk refresh

image.png

You can see the effect

image.png

3、 ... and 、 Publish to npm The central warehouse

See my previous blog for details 【npm】 Release Customize JS Tool library To npm The central warehouse

Last time we knocked line by line , This time we also adopt the automatic way , Write a .sh file

publish.sh

#!/usr/bin/env bash
npm config get registry #  Check the warehouse image library 
npm config set registry=https://registry.npmjs.org
echo ' Please log in :'
npm login #  land 
echo "-------publishing-------"
npm publish #  Release 
npm config set registry=https://registry.npm.taobao.org #  Set to Taobao image 
echo " Release complete "
exit
 Copy code 

Let me change the name of my package to vue-auto-router-cli-yk Version is 1.0.0

{
  "name": "vue-auto-router-cli-yk",
  "version": "1.0.0",
  "description": " This is a YK It's written by bacteria vue Scaffold tools ",
  "main": "index.js",
  "bin": {
    "yk": "./bin/yk.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "chalk": "^4.1.2",
    "clear": "^0.1.0",
    "commander": "^8.2.0",
    "download-git-repo": "^3.0.2",
    "figlet": "^1.5.2",
    "handlebars": "^4.7.7",
    "open": "^8.2.1",
    "ora": "^5.4.1"
  }
}

 Copy code 

Finally, we implement sh Script files

Windows Your computer can't directly execute , But I pretended git,git bash Can open , Then go into the folder and find that you can directly double-click to open , ha-ha , Then I'll double-click to open ~

image.png

If you read my previous blog 【npm】 Release Customize JS Tool library To npm The central warehouse , In fact, you don't have to be so troublesome , Change the image directly from the command line, and then npm publish That's it

That's the three steps

npm config set registry=https://registry.npmjs.org
npm publish
npm config set registry=https://registry.npm.taobao.org
 Copy code 

image.png

Last to go npm Look at the official website www.npmjs.com/

image.png

At this time, you can let the little friends around you use the scaffold tool you just wrote ~

npm install vue-auto-router-cli-yk -g
yk init vue_demo
 Copy code 

Four 、 summary

Today we mainly learned Node.js The basis of API, Then we wrote a simple scaffold , And released to npm Warehouse . Next , Let's write a koa The scaffolding of the frame , A little more complicated , And we will use happy-path Write code in small steps . With today flow And Subprocesses The basis of , The content of the next article will also be well understood ~

Last , Can you leave a message and like it ? It would be great to pay attention , There is also a link to the column below , Can focus on a wave , Receive... In time Youth Camp notes The latest blog news of the series .

copyright notice
author[YK bacteria],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/01/202201291524059678.html

Random recommended