Recently, I found that there was a lot of repetitive work and a lot of time wasted in writing admin pages. Think of using Node to automate the process, but also to avoid manual operations may occur some mistakes. This article only for my own project to make some optimization, but provide some ideas you can refer to, flexible use of their own projects to go.

Whenever I want to create a new page, there will be a series of operations: Create a vue file > Add route > Add a submenu in el-Menu > Add page permissions. All I need to do is hand this over to Node and write a CLI to implement it.

Know the cli

The CLI is a command line interface. First create package.json using NPM init, then add key code to it

"bin": {"test": "./index.js"
}
Copy the code

Test is the command name, for example, test XXX. Use NPM link to link the bin instructions in the global, convenient debugging.

Next, index.js must be executable, so we add #! To the header. /usr/bin/env node

//index.js
#! /usr/bin/env node
console.log('Test executed');
Copy the code

Executing test on the command line will print “test executed”

Commander works with inquirer’s command line interaction

program
  .version('1.0.0')
  .command(`add`)
  .action(() => {
    inquirer.prompt([
      {
        type: 'list',
        name: 'page',
        message: 'Please select page level',
        default: '2',
        choices: ['tier 1'.'2'] {},type: 'input',
        name: 'parent',
        message: 'Please enter English name of level 1 module',
        when: answers => answers.page === '2',
        validate: val=>{
          if(! val) {return 'Input cannot be null'
          }
          return true}}, {type: 'input',
        name: 'en',
        message: 'Please enter English module name',
        validate: val=>{
          if(! val) {return 'Input cannot be null'
          }
          return true}}, {type: 'input',
        name: 'cn',
        message: 'Please enter Chinese name of module',
        validate: val=>{
          if(! val) {return 'Input cannot be null'
          }
          return true}}, {type: 'input',
        name: 'code',
        message: 'Please enter module code (for permissions)',
        validate: val => {
          if(! val) {return 'Input cannot be null'
          }
          return true}}, {type: 'input',
        name: 'route',
        message: 'Please enter the page path (corresponding page name and route name)',
        when: answers => answers.page === '2',
        validate: val => {
          if(! val) {return 'Input cannot be null'
          }
          return true}}]). Then (async Answers => {// Perform the corresponding operation // The answers to the questions are listed in the answers property with the name field of each question console.log(chalk. Green ()'Operation successful'))})})Copy the code

After collecting some of the parameters I need to use, it’s time to generate the corresponding content.

Use node’s fsPromise module to read and write files

const fs = require('fs').promises
const path = require('path')

const fileHandle = await fs.open(path.resolve(yourpath), 'r')
let content = await readHandle.readFile('utf-8')... A series of operations on content... Const writeHandle = await fs.open(path.resolve(yourpath),'w') await writehandle.writefile (content) // Write new content to await writehandle.close ()Copy the code

The file identifier “R +” on the document is” open file for read and write “, but I can only read, and finally I can only read and write by opening r and W twice.

Operations on content

Replace (reg, yourString). YourString is the String that is concatenated after receiving the parameters. For example, my route:

const reg = new RegExp('}\\s*]')
const route = `},
   { path: '/${routeName}', component: () => import('@/page/${routePath}') }
]`
routerContent = routerContent.replace(reg, `${route}`)
Copy the code

Here I’ve chosen to replace the router.js}] with the above code. There are many places to replace it, but it’s all the same. And regular forward and backward are good positioning means.

A new page

Write a string to a file, nothing to say, when the file does not exist call writeFile will automatically create the file.

  const content = `<template>
  <div></div>
</template>

<script>
export default {
  data () {
    return{}},created () {},
  methods: {}
}
</script>

<style lang="scss" scoped>

</style>
`
  await fs.writeFile(path.resolve(`./src/page/${routePath}.vue`), content)
Copy the code

Formatting code

The resulting code is all stuck together and the format is messy, so we’ll use ESLint to fix it automatically. Node’s child_process module can execute shell commands:

child_process.exec(command, [options], callback)
Copy the code

Spawn a shell and command in that shell. Note that the esLint execution directory must be added to the shell’s environment variable:

const SEPARATOR = process.platform === 'win32' ? '; ' : ':'
const env = Object.assign({}, process.env)

env.Path = path.resolve('./node_modules/.bin') + SEPARATOR + process.env.PATH

const option = {
  env: env
}
child_process.exec('eslint --fix --ext .js,.vue src', option, callback)
Copy the code

Finally the completed code will be uploaded to the NPM. At this point, you’re done! Just run test Add to see what happens!

conclusion

We have moved all manual modification to the command line so handy that if you find it useful click (•̀ ω •́)✧