利用nodejs寫一個自動生成vue元件檔案的cli

發ther發表於2018-04-19

作者:小白君

歡迎訪問個人github倉庫

轉載請標明出處

三體-人列計算機

引言

自從入了vue的坑後,對vue的熱愛猶如滔滔江水,一發不可收拾(哈哈哈哈,騷比一下)。公司開發,編寫元件基本上都用偉大的vue,雖然目前在公司主要從事移動端app開發,雖說vue官網有推薦vue-cli,其提供了init,build,list等命令,但並沒有提供生成新的元件檔案的命令,每次只能手動新增一個新的元件檔案,感覺比較麻煩,於是就想動手寫一個生成新的元件檔案的cli,嗯,可能作用不大,全當熟悉nodejs以及學習怎樣寫一個cli tool.

開發

第一步: 肯定是安裝nodejs了,這步很簡單就不用說了,我電腦安裝的是最新的LTS版本。

第二步: 建立一個vue-generate-cli目錄,npm初始化 命令如下:

npm init
複製程式碼

執行上述命令的時候,可以使用預設值,也可以自定義。此時此目錄下會生成一個package.json檔案,儲存專案資訊。

{
  "name": "vue-generate-cli",
  "version": "1.0.0",
  "description": "A cli tool for auto-generating vue template component",
  "author": "bingrui_yuan0721@163.com",
  "engines": {
    "node": ">=6.0.0"
  },
  "license": "MIT"
}
複製程式碼

第三步: 引入必要的依賴nodejs外掛,我這裡主要用到了以下幾個外掛

"dependencies": {
    "chalk": "^2.4.0",
    "commander": "^2.15.1",
    "ora": "^2.0.0"
  }
複製程式碼

chalk是一個顏色的外掛,可以用來指定回顯的字型顏色,粗細及背景色。

ora主要用來實現node.js命令列環境的loading效果,和顯示各種狀態的圖示等。

commander實現命令列功能。

第四步: 在當前目錄下建立vue和vue-generate檔案,實現cli主要的功能

vue檔案:

#!/usr/bin/env node

require('commander')
  .version(require('../package').version, '-v, --version')
  .description('quick generate vue file')
  .usage('<command> [options]')
  .command('generate', 'generate one new vue component file')
  .alias('g')
  .parse(process.argv)
複製程式碼

注:第一行的#!/usr/bin/env node很重要,表示用node來執行這個檔案

vue-generate檔案:

#!/usr/bin/env node

var program = require('commander');
const chalk = require('chalk');
const ora = require('ora');
const spinnerstyle = require('../libs/spinners.json');
const path = require('path');
const fs = require('fs');

const spinner = ora({
  text: chalk.blue('generate template begin'),
  spinner: spinnerstyle.dots
});

program.on('--help', function() {
  console.log('  Examples:');
  console.log('');
  console.log('    $ vue-g g --help');
  console.log('    $ vue-g g -h');
  console.log('');
  console.log(chalk.gray('    # create a new my-component.vue file with an template in components directory'));
  console.log('    $ vue-g g my-component');
  console.log(chalk.gray('    # create a new my-component.vue file with an template in libs directory'));
  console.log('    $ vue-g g libs my-component');
  console.log(chalk.gray('    # create more new my-component01.vue, my-component02.vue and my-component03.vue files with an template in libs directory'));
  console.log('    $ vue-g g libs my-component01 my-component02 my-component03');
  console.log(chalk.gray('    # create more new my-component01.vue, my-component02.vue and my-component03.vue files with an template in ./components/libs directory'));
  console.log('    $ vue-g g ./components/libs my-component01 my-component02 my-component03');
  console.log('');
});

program.parse(process.argv);

/**
 * Help
 */
(function help () {
  if (program.args.length < 1) return program.help();
})()

/**
 * Generate
 */
const suffix = '.vue';
const baseDir = './src';
const basePath = path.join(process.cwd(), baseDir);

console.log('');
spinner.start('Generating, please wait......');
console.log('');

checkBasePathIsexists(basePath, baseDir);

// check basepath
function checkBasePathIsexists(currentPath, currentDir) {
  if (fs.existsSync(currentPath)) {
    generate();
  } else {
    spinner.fail(chalk.red(currentDir + ' directory does not exist'));
  }
}

// check path
function checkPathIsexists(currentDir, filename) {
  let currentPath = path.join(basePath, currentDir);
  if(fs.existsSync(currentPath)) {
    checkVueFileIsexists(currentPath, filename);
  } else {
    console.log(currentPath);
    fs.mkdirSync(currentPath);
    checkVueFileIsexists(currentPath, filename);
  }
}

function checkVueFileIsexists(currentPath, filename) {
  if(Object.prototype.toString.call(filename) === '[object Array]') {
    filename.forEach(function(onefile) {
      onefile = onefile.replace(/([A-Z])/g,"-$1").toLowerCase();
      let file = path.join(currentPath, './' + onefile);
      generateVueFile(file, onefile);
    })
  } else {
    filename = filename.replace(/([A-Z])/g,"-$1").toLowerCase();
    let file = path.join(currentPath, './' + filename);
    generateVueFile(file, filename);
  }
}

function generateVueFile(file, filename) {
  console.log('');
  spinner.start(filename + suffix + ' is generating......');
  if(fs.existsSync(file + suffix)) {
    spinner.fail(chalk.red(filename + suffix + ' exists.'));
  } else {
    fs.writeFileSync(file + suffix, generateTemplate(filename));
    spinner.succeed(filename + suffix + ' generated successfully');
  }
}

function generate() {
  if (program.args.length === 1) {
    checkPathIsexists('./components', program.args[0]);
  } else if(program.args.length === 2) {
    checkPathIsexists(program.args[0], program.args[1]);
  } else {
    checkPathIsexists(program.args.shift(), program.args);
  }
  console.log('');
  spinner.stop();
}

function generateTemplate(filename) {
  return `<template>\n  <div class="${filename}"></div>\n</template>\n\n`
          + `<script>\nexport default {\n  name: '${filename}',\n  data () {\n    return {\n\n    }\n  },\n  created () {},\n  mounted () {},\n  methods: {}\n}\n</script>\n\n`
          + `<style scoped>\n.${filename} {\n\n}\n</style>\n`;
}
複製程式碼

第五步: 編寫可執行檔案

在package.json中有一個"bin"欄位,配置後才可以在控制檯使用你的命令

"bin": {
    "vue-g": "bin/vue"
 }
複製程式碼

第六步: 釋出到npm倉庫

將模組釋出到npm上,首先得有一個npm賬號,註冊賬號npm adduser,如果已有賬號,直接登入npm login

// 註冊
npm adduser
// 登入
npm login
複製程式碼

註冊或登入成功後,直接npm publish釋出

// 釋出
npm publish
複製程式碼

第七步: 安裝測試

使用npm install -g vue-generate-cli全域性安裝,並輸入命令測試 輸入如下命令:

vue-g g -h
複製程式碼

幫助資訊

使用

  1. 安裝
$ npm install -g vue-generate-cli
or
$ yarn global add vue-generate-cli
複製程式碼
  1. 使用
// default generate a new file in components directory
$ vue-g g <filename>
or
// generate a new file in custom directory
$ vue-g g <dirname> <filename>
or
// generate more new files in custom directory
$ vue-g g <dirname> <filename01> <filename02> <filename03> <filename(2N+1)>
or
// generate more new files in custom path
$ vue-g g path <filename01> <filename02> <filename03> <filename(2N+1)>
複製程式碼
  1. 例子
$ vue-g g my-component
or
$ vue-g g libs my-component
or
$ vue-g g libs my-component01 my-component02 my-component03
or
$ vue-g g ./components/libs my-component01 my-component02 my-component03
複製程式碼

總結

通過一天的搗鼓,vue-generate-cli基本上實現了最初設想的功能,程式碼也不是很複雜,而且已釋出到npm上,需要的可以自行安裝使用。 最後,感覺功能還比較簡單,更多高大上的功能還需碼友共同努力。

傳送門:github: vue-generate-cli

相關文章