Today we will build a simple Node script plug-in from scratch, easy to operate shell, build your own scripting tools, help you understand some node modules, webpack packaging process and NPM release process.

child_process.exec

To use node to operate a shell, start with child_process.exec. In simple terms, exec starts a shell and executes the input command, just as you would use git bash to execute certain commands, such as NPM init. That’s it. Show code.

File structure

First create a folder with the following structure and execute NPM init -y

├ ─ SRC └ ─ index. JsCopy the code

Plug-in to write

In the index.js file, write the main code.

First introduce the required exec

const util = require('util');
const exec = util.promisify(require('child_process').exec);
Copy the code

Generally, three parameters are required: command to execute, CWD to execute, and timeout

exec(command, { cwd: path || null.timeout: timeout || 0 })
Copy the code

The code for executing the command is as follows:

/** * @name: Command line * @param {Array} CMD/Command execution statement * @param {String} path/ Command execution path * @param {Number} timeout/ Command execution timeout period * @return: {Boolean} Successful */
const shell = async (arr) => {
  for (let i = 0; i < arr.length; i++) {
    const { cmd, path, timeout } = arr[i]
    // Assemble execute command
    const command = cmd.reduce((total, item, index) = > {
      if (index === 0) {
        return total + item
      } else {
        return total + ` && ${item}`}},' ')
    const { error, stdout, stderr } = await exec(command, { cwd: path || null.timeout: timeout || 0 });
    if (error) {
      // Prints error logs
      log(error)
      return false}}console.log("Complete")
  return true
}
Copy the code

CMD in the object is an array of strings, storing the command lines executed. “&&” is used to connect each command line. Path is the path of executing the command.

Errors may occur during execution, so a log is needed to record errors.

The error log

Introduce required functionality

const fs = require('fs');
const path = require('path');
Copy the code

Gets the current time for later use

/** * @name: current time * @param {String} type/date: date, time is accurate to the second * @return: {String} current time */
const timeStr = (type) = > {
  const zeroFill = n= > {
    n = n.toString()
    return n[1]? n :'0' + n
  }
  const date = new Date(a)const year = date.getFullYear()
  const month = zeroFill(date.getMonth() + 1)
  const day = zeroFill(date.getDate())
  const hour = zeroFill(date.getHours())
  const minute = zeroFill(date.getMinutes())
  const second = zeroFill(date.getSeconds())
  if (type === "date") {
    return `${year}-${month}-${day}`
  }
  if (type === "time") {
    return `${year}-${month}-${day} ${hour}:${minute}:${second}`}}// The current date
const date = timeStr("date")
// The current time
const time = timeStr("time")
Copy the code

Outputting error logs

/** * @name: output error log * @param {type} error/ error message * @return: */
const log = error= > {
  const logPath = path.join(__dirname, "log")
  const txtPath = path.join(__dirname, "log".`${date}.txt`)
  if(! fs.existsSync(logPath)) {// The log directory does not exist
    fs.mkdirSync(logPath)
  }
  if(! fs.existsSync(txtPath)) {// If no error log file exists, create one
    fs.writeFileSync(txtPath, `${time}  ${error}; \n`)}else {
    // If yes, an error message is appended
    fs.appendFileSync(txtPath, `${time}  ${error}; \n`)}}Copy the code

Use fs.existssync to check if the log directory exists, and if not, use fs.mkdirsync to create a directory.

If no, use fs.writeFileSync to create a file and write the error information and time. If so, append the error message to the error log file using fs.appendfilesync.

At last,

module.exports = shell
Copy the code

export

Then create an example file in the SRC directory to check that the code just described runs successfully.

const shell = require("./index")

shell([{ cmd: ["mkdir pikaz-shell"].path: "D:\\" }])
Copy the code

This command creates a Pikaz-shell folder on drive D

perform

node src/example
Copy the code

When you see the newly created folder on drive D, the code is ready to run successfully.

Once the code is written, it needs to be packaged, and we use WebPack to do that.

packaging

Install webpack

npm install webpack webpack-cli --save-dev
Copy the code

Create the webpack.config.js configuration file in the project directory as follows:

const path = require('path');

module.exports = {
  mode: 'production'.entry: {
    "pikaz-shell": "./src/index.js",},output: {
    filename: '[name].js'.path: path.resolve(__dirname, 'lib'),
    libraryTarget: 'umd'
  },
  node: {
    fs: 'empty'.child_process: 'empty',}};Copy the code

Mode is the packaging mode and set to production mode, which can automatically compress the code.

Entry is the entry for packaging. Set it to the index file in the SRC directory.

Output is the output file in the lib folder. LibraryTarget is usually set to umD. This exposes your library to work with all module definitions. It will run in CommonJS, AMD environments, or export modules to variables under Global.

Node sets fs and child_process to ’empty’, because the node we are using is a global node installed on the computer, so webPack will not look for these modules, or it will report an error that they cannot be found in the project.

Finally add the package command “build”: “webpack” to the scripts of package.json

release

Publish first need an NPM account, you can go to https://www.npmjs.com/ to register one.

If you have an account, continue with the following operations. Set the package.json file as follows:

{
  "name": "pikaz-shell"."version": "0.1.4"."description": "javascript for manipulating the shell"."main": "lib/pikaz-shell.js"."scripts": {
    "build": "webpack"."example": "node src/example"
  },
  "keywords": [
    "node"."shell"]."files": [
    "lib"]."repository": {
    "type": "git"."url": "https://github.com/pikaz-18/pikaz-shell.git"
  },
  "bugs": {
    "url": "https://github.com/pikaz-18/pikaz-shell/issues"
  },
  "author": "pikaz"."license": "MIT"
}
Copy the code

Name is the name of the project, version is the version of the project, and the version needs to be changed every time the project is released. Description is the introduction of the project, main is the entry address of the project, we specify the pikaz-shell.js file in the packaged lib directory, and keywords are the keywords of the project. Files is the whitelist, only files or folders on the whitelist will be uploaded to NPM, we just need to upload the packaged folder lib to reduce the package size, repository is the address of github project, bugs is the address of github issue, author is the author, The license is an open source agreement. Generally, we can choose MIT to write plug-ins. The provisions of this agreement are the most loose.

The project address

Github.com/pikaz-18/pi…

This plugin has also been uploaded to NPM, if necessary, you can also directly use oh

npm install --save -dev pikaz-shell
Copy the code

The last

The next article will use this plug-in to build a front-end automatic deployment feature on a server without having to look at the back end or manually update the development environment project.

If you think you got something, please give it a thumbs up, Rua