仿vue的前端自定義cmd命令拉取項目腳手架

原文地址:https://github.com/screetBloo...
含純node或者commander實現本身的前端腳手架
文章碼字分享不易,但願若是幫到您的話,幫忙github點個starhtml

腳手架

這裏主要講的是如何自定義node命令,拉取項目前端

snowcat init
// 用戶安裝咱們的命令,就能夠一行代碼拉取對應項目,可擴展成根據不一樣命令拉取不一樣終端模板

1.腳手架的實現

腳手架做用: 快速搭建一個咱們預約義好的模板項目結構
咱們這裏就作了兩件事(已經知足了我目前的需求,能夠繼續拓展):vue

  • 1.自定義nodejs命令
  • 2.在nodejs中執行shell命令(通俗說的命令行命令),拉取模板項目到本地

1.1 導言

咱們平時常常會使用vue、angular、react等的腳手架,均可以達到以下效果node

// 1. 全局安裝對應的腳手架  "xxx-cli"  (不全局安裝的話,只能在當前安裝包下使用)
npm install -g xxx-cli

// 2. 接下來直接就如"vue init"就能夠直接拉取一個模板項目到咱們的當前文件夾
vue init

這個效果挺好用的,假如我積累了一套框架,我不想每次重開項目都拷貝到其餘文件夾來用;當別人須要的時候,別人又要從我這拷貝一份;或者是我每次都給別人一串別人基本記不住的git的url連接,這個太麻煩了
我但願能有一套腳手架,能像這些成熟的框架的腳手架同樣直接把我想要的模板項目用最簡短而有效的命令拉取到任何我想要獲取的電腦的文件夾中,再有須要了,我還能繼續拓展react

// 全局安裝腳手架
npm install -g snowcat
// 拉取預約義模板
snowcat init

本地效果演示:


git

其它機器上演示:



github

1.2 腳手架具體實現過程

先上組織結構和代碼(結合思路和代碼若是你已經懂了,省的還向下看),再從零開始講實現方式和原理shell

1.1.1 0.0.1版本腳手架組織結構

1.1.2 實現0.0.1版本腳手架的完整代碼

snowcat.js ==> 腳手架定義的全部命令的入口,這裏暫時只有init命令npm

#!/usr/bin/env node
'use strict'
const program = require('commander')
program
    .version(require('../package').version )

program
    .command('init')
    .description('pull a new project')
    .alias('i')
    .action(() => {
        require('../command/init')()
    })

program.parse(process.argv)

if(!program.args.length){
    program.help()
}

init.js ==> init 命令的定義文件json

'use strict'
const exec = require('child_process').exec
const projectUrl = 'https://github.com/screetBloom/wecat.js.git'

module.exports = () => {
    console.log('this is my first commander >>>>>> ')
    let cmdStr = `git clone `+projectUrl

    exec(cmdStr, (error, stdout, stderr) => {
        if (error) {
            console.log(error)
            process.exit()
        }
        console.log('pull咱們的項目已經成功了')
        process.exit()
    })

}

package.json ==> 在package.json文件中聲明整個文件包的可執行文件的位置

"bin": {
    "snowcat": "bin/snowcat.js"
  }

1.1.3 實現思路

上述的3個文件主要完成了2個最基本的事情

  • 1.自定義nodejs命令。在nodejs本來確定是沒有"snowcat"這種命令的,這個是咱們自定義的
  • 2.用nodejs執行shell命令(通俗講的命令行命令),這裏主要是執行了git clone

那麼咱們如今先來嘗試一下,如何自定義nodejs命令
在這裏咱們須要引入一個"commander.js"的npm包
先說明:不引入任何包都是能夠完成咱們上述的兩件事,引入的主要緣由有2個

  • 1.有了這個npm包,能夠簡化咱們命令行的開發,把咱們主要精力仍是迴歸到框架開發上
  • 2.commander有大量的api,咱們目前只是0.0.1版本,不依賴任何包來實現都是沒有問題的,之後高版本1.0.0的拓展仍是要用它的,這裏我直接和你們說一下,也能夠熟悉一下它的使用

我在這裏補充一下不用任何依賴包的實現方式:

// PS.在nodejs中,能夠直接用nodejs內置的全局變量process獲取到你輸入的命令的參數
// 如今咱們直接就能夠利用 process.argv來獲取,如定義snowcat.js文件以下:
#!/usr/bin/env node
let run= function (para) {
    if(para[0] === '-test'){
        console.log('version is 1.0.0');
    }
    if(para[1] === '-host'){
        console.log('127.0.0.1');
    }
};
 console.log(process.argv)
run(process.argv.slice(2));

頂部的"#!/usr/bin/env node"的意思是 顯式的聲明這個文件用node來執行
執行snowcat.js文件

node snowcat.js
/*
輸出結果以下:
[ '/usr/local/bin/node',
  '/Users/chenwei/WebstormProjects/git_my/deep-in-vue/wim/test.js' ]
*/
node snowcat.js -test -host
/*
輸出結果基本以下:
[ '/usr/local/bin/node',
  '/Users/chenwei/WebstormProjects/git_my/deep-in-vue/wim/test.js',
  '-test',
  '-host' ]
*/

這裏我想告訴你們的就是process.argv,這個東西很關鍵,能夠拿到用戶輸入的命令,而後你就能夠根據輸入執行對應的函數就好了

先把 console.log(process.argv)註釋了, 再來自定義指令試一試

node snowcat.js -test
/*
輸出以下:
version is 1.0.0
*/
node snowcat.js -host
 /*
 輸出以下:
 127.0.0.1
 */

我寫這個demo主要表示如今咱們就能夠直接根據參數來匹配對應執行的函數了,以上面的init.js文件爲例
咱們是先利用process.argv.slice(2) 獲取到輸入的參數,匹配一下執行對應的函數就行;純node.js實現

argv返回的是一個不定長的數組,第一個是node.exe的路徑,第二個是當前文件的路徑,接下來是你命令後面跟的參數

nodejs中的process的官方說明文檔在這
這裏咱們就順着這個繼續了,commander等等再說,對目前的咱們來講也沒到重要要偏說不可的地步

有沒有注意到上面咱們都是在js文件所在目錄下直接"node snowcat.js -test"來執行js文件,咱們該如何直接"snowcat -test"就執行js文件呢 ,也就是上面咱們說的自定義nodejs命令
這個時候package.json就須要登場了

// 初始化一個package.json,相關信息自定義
npm init

在裏面添加一行

"bin": {
    "snowcat": "snowcat.js"
  }

這個是什麼意思呢: 簡單說就是把命令名做爲key,本地文件名做爲value作一個映射。全局安裝的時候,npm會把你定義的這個命令名"snowcat"對應的可執行文件安裝到系統路徑下,達到全局使用該命令的目的;本地安裝的時候,會直接連接到'./node_modules/.bin/'

目前的配置信息應該基本以下:

{
  "name": "snowcat",
  "version": "0.0.1",
  "description": "my cli 0.0.1",
  "main": "init.js",
  "bin": {
    "snowcat": "snowcat.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "wim_chen",
  "license": "ISC"
}

如今咱們來嘗試本地的全局的運行 "snowcat" 命令,這裏須要用到 "npm link",這裏注意:是咱們本身全局使用,給別人全局用能夠發佈到npm倉庫

// 在當前的package.json中輸入該命令
npm link

這個"npm link"主要是在咱們本機的全局的"node_modules"目錄中,生成一個符號連接"a symbolic link"指向咱們當前文件夾

又由於咱們在package.json中定義了"bin",指出了全局安裝的時候命令"snowcat"對應的js文件
如今咱們在本機的任何一個地方輸入"snowcat -test -host"都會輸出下述結果:

[ '/usr/local/bin/node',
  '/Users/chenwei/Desktop/工做與興趣/common_test/command/test_one/snowcat.js',
  '-test',
  '-host' ]
version is 1.0.0
127.0.0.1

想要進一步的達到如

npm install -g snowcat 
// 執行咱們目前的腳手架
snowcat -test -host

如今只須要作以下幾步:

  • 1.註冊一個npm帳號,點擊https://www.npmjs.com/ 直達npm官網
  • 2.給你的package.json裏面的name寫一個你們都沒用過名字(snowcat你是別想了,很明顯已經名花有主了)
  • 3.在你本地的package.json所在的路徑下輸入:"npm adduser",而後輸入你的用戶名、密碼、郵箱
  • 4.輸入 "npm publish"就將你的npm包發送到了npm倉庫
  • 5.找個好朋友,讓他安裝一下你的包"npm install -g xxx",讓他輸入" snowcat -test -host"就能夠打印出你寫好的內容了,好比"我愛你"?

如今咱們來按要求拉取咱們的項目,用一開始的文件結構舉例

先建立一下對應的文件

首先"npm init"咱們的package.json文件,並設置"commander.js"依賴和合適的bin

{
  "name": "snowcat",
  "version": "0.0.1",
  "description": "my js cli 0.0.1",
  "main": "index.js",
  "bin": {
    "snowcat": "bin/snowcat.js"
  },
  "dependencies": {
    "commander": "^2.9.0"
  },
  "author": "wim_chen",
  "license": "ISC"
}

這裏先說明一下 commander.js的語法

program
    .command('init')       // 命令是 init
    .description('pull a new project')    // 命令的描述
    .alias('i')    // 命令別名,用init和i都行
    .action(() => {
      require('../command/init')()  // 執行init命令時要作什麼,這裏是執行init文件裏導出的函數
  })

開始是編寫咱們的命令行入口文件,bin文件夾下的snowcat.js,也很簡單

// 頭部添加顯示聲明:本文件用node來執行
#!/usr/bin/env node
// 嚴格模式
'use strict'
// 引入 commander,用於處理自定義nodejs命令
const program = require('commander')
// 引用package.json裏面的版本號來定義當前版本
program
    .version(require('../package').version )

// 定義init命令,同時定義init命令的簡化命令 i,包括命令的腳本文件所在路徑
program
    .command('init')
    .description('pull a new project')
    .alias('i')
    .action(() => {
        require('../command/init')()
    })

// 這一句必不可少,做用是解析命令行參數argv,這裏的process.argv是nodejs全局對象的屬性
program.parse(process.argv)

// 若是用戶只是輸入了 "snowcat"沒帶參數,就給他展現他能輸入的全部命令
if(!program.args.length){
    program.help()
}

咱們先來試一下,執行snowcat命令

node ./bin/snowcat.js

顯示以下,就是正確的,說明咱們commander.js使用的很順利

編寫咱們的 init.js

'use strict'
// 這個是node自帶調用自窗口執行shell命令的方法,等會用
const exec = require('child_process').exec
module.exports = () => {
    console.log('this is my first commander >>>>>> ')
}

如今咱們輸入

node ./bin/snowcat.js  init

接下來咱們來利用git來拉取咱們的項目
編寫init.js

'use strict'
const exec = require('child_process').exec
const projectUrl = 'https://github.com/screetBloom/wecat.js.git'

module.exports = () => {
    console.log('this is my first commander >>>>>> ')

    // git命令,遠程拉取項目並自定義項目名
    let cmdStr = `git clone `+projectUrl

    // 在nodejs中執行shell命令,第一個參數是命令,第二個是具體的回調函數
    exec(cmdStr, (error, stdout, stderr) => {
        if (error) {
            console.log(error)
            process.exit()
        }
        console.log('pull咱們的項目已經成功了')
        process.exit()
    })

}

如今咱們再輸入

node ./bin/snowcat.js  init

此時項目已經能夠正確的拉取下來了,接下來咱們來進行本地全局安裝,在當前的package.json路徑下輸入"npm link"(能夠本地全局使用了)
在其它路徑下拉取項目

成功,那麼如今咱們把它放到npm倉庫裏,若是上一次你已經放進去0.0.1版本了,此次就須要修改版本號了,操做以下:

// 好比對最後一位進行修改:增1,命令,回車:
npm version patch    
// 好比對第二位進行了修改:增1,命令:
npm version minor    
// 好比對第一位進行了修改:增1,命令:
npm version major  
     
// 查看全部的版本號:
npm view snowcat versions

最後咱們再在其它機器上測試

// 全局安裝腳手架
npm install -g snowcat
// 拉取預約義模板
snowcat init


0.0.1版本的腳手架分享到此結束

相關文章
相關標籤/搜索