Node腳手架編寫初學者教程

Node腳手架編寫初學者教程

完整的腳手架代碼前端

編寫你的第一個腳手架

前言

隨着NodeJs的崛起,現代前端工程已經變得愈來愈複雜。前端框架如雨後春筍。從Backbone,Ember,Knockout,Spine,Batman框架的崛起到Angular,React,Vue平分天下,咱們經歷太多代碼風格的變革。vue

不可避免學習新的框架,複雜的環境又讓初學者很難入手。就拿React來講,咱們要使用Babel,Webpack等模塊輔助編譯,咱們還須要Redux,Immutable,Mocha,Jest,Antd或者其餘第三方包(如eslint,lodash,moment,debug,uuid,request,co,koa等)輔助業務需求。node

目錄結構愈來愈複雜,爲了讓每一個項目使用的統一的技術和目錄結構,各大模塊紛紛推出了本身的腳手架工具,好比redux-cli,create-react-app,vue-cli等。如今就讓咱們以any-cli爲例,編寫本身的腳手架工具吧。react

核心原理

yoeman搭建項目須要提供yoeman-generatoryoeman-generator本質上就是一個具有完整文件結構的模板,用戶須要手動地把這些模板下載到本地,而後yoeman就會根據這些模板自動生成各類不一樣的項目。git

vue-cli提供了至關豐富的選項和設定功能,可是其本質也是從遠程倉庫把不一樣的模版拉取到本地,而並不是是什麼「本地生成」的黑科技。程序員

這樣看來,思路也就有了——首先創建不一樣的模板,而後腳手架根據用戶的指令引用模板生成實際項目。github

模板既能夠內置在腳手架當中,也能夠部署在遠程倉庫。vue-cli

  • 內置在腳手架中,使用node file操做來把模板克隆到本地。npm

    優勢是不用新建倉庫保存模板。尤爲是有多項目模板時候,好比init pcinit mobile分別生成兩個不一樣項目,咱們只須要一個倉庫保存腳手架便可。編程

    第二個優勢:不管腳手架仍是模板變動,只須要提交一次。

  • 部署在遠程倉庫,使用git clone把項目克隆到本地。

    優勢是每次模板有代碼變動時,無需讓用戶本地升級腳手架。

    若是模板內置在腳手架裏,每次模板變動,由於是在同一倉庫,因此用戶須要升級腳手架。而部署在遠程倉庫則不一樣,咱們只須要git clone便可獲取最新模板。

總體流程

按照標準慣例,先看下總體流程(github不支持流程圖flow類型展現,好搓,害的我又把流程代碼改爲這種挫樣式)

添加模板->輸入模板名->是否有重名模板?-添加成功:給出提示

刪除模板->輸入模板名->是否有模板?-刪除成功:給出提示

模板列表->列出全部模板

初始化模板-輸入模板名-是否有模板?-輸入模塊名-克隆遠程倉庫到本地模塊-切換分支:給出提示複製代碼

技術要點

process.cwd()與__dirname

命令都位於腳手架中,而執行命令的地方經常在模板項目中。

好比腳手架路徑是/usr/local/lib/node_modules/any-cli/lib/,執行全局腳手架命令路徑是/Users/admin/test/

想要腳手架代碼想讀腳手架目錄下的a.js文件寫入模板項目(執行全局腳手架命令位置)b.js中,那麼readFile的路徑爲path.resolve(__dirname,'a.js'),writeFile路徑爲path.resolve(process.cwd(),'b.js')。就這麼簡單。

bin

許多npm模塊有可執行文件但願被安裝到全局系統路徑。

須要在package.json中提供一個bin字段,它是一個命令名稱到文件路徑的映射。以下:

"bin": {
    "any": "./bin/any"
},複製代碼

這樣會把any命令和本地可執行文件./bin/any創建映射。也就是說,當你在命令行執行any命令時,會執行./bin/any可執行文件。

  • 全局安裝,npm將會使用符號連接把這些文件連接到/usr/local/bin目錄下,系統的二進制命令所有在這裏。

  • 若是是本地安裝,會連接到./node_modules/.bin目錄下。只有當前目錄運行any命令時,纔會生效。

若是你只有一個可執行文件,那麼它的名字應該和包名相同,此時只須要提供這個文件路徑(字符串),好比:

{
    "name": "any-cli",
    "version": "1.2.5",
    "bin": "./bin/any"
}複製代碼

等同於:

{
    "name": "any-cli",
    "version": "1.2.5",
    "bin": {
        "any-cli": "./bin/any"
    }
}複製代碼
  • 本地目錄連接到全局模塊

    npm link能夠把本地目錄連接到全局模塊下。

    對於開發模塊者而言,這算是最有價值的命令了。好比咱們開發any-cli模塊時,須要在命令行中使用any來測試咱們的代碼(開發中沒有發佈,也就沒法全局安裝模塊)。不要擔憂,使用npm link一切變得很是容易。

    好比咱們any-cli項目package.json裏,有一條命令以下:

    "bin": {
          "any": "./bin/any"
      },複製代碼

    命令行中使用npm link

    $ npm link複製代碼

    獲得如下結果

    /usr/local/bin/any -> /usr/local/lib/node_modules/any-cli/bin/any
      /usr/local/lib/node_modules/any-cli -> /Users/lihongji/work/any-cli複製代碼

    分別進入/usr/local/bin與/usr/local/lib/node_modules目錄下查看。咱們發現裏面分別多了any可執行文件與any-cli目錄。
    這樣,每次本地倉庫有改動時,全局命令也隨之更新。咱們就能夠邊開發邊測試了

  • 本地目錄引用全局模塊

    若是你還有其餘模塊any-cli-test依賴於any-cli模塊,你可使用以下命令把全局any連接到當前模塊下。

    $ cd ~/work/any-cli-test
      $ npm link any-cli # 把全局模式的模塊連接到本地複製代碼

    npm link test 命令會去/usr/local/lib/node_modules目錄下查找 any-cli的模塊,找到這個模塊後把/usr/local/lib/node_modules/any-cli 的目錄連接到當前any-cli-test下的./node_modules/any-cli 目錄上。

    如今任何 test 模塊上的改動都會直接映射到 test-example 上來。

其餘字段:engine與engineStrict

node7.6.0開始支持async,如何保證用戶本地安裝node7.6.0以上版本呢複製代碼
  • engine
    你能夠在本地安裝node特定版本:

    "engines": { "install-node": "7.6.0" }複製代碼

    安裝後,在本地node_modules/.bin目錄下會多一個node可執行文件。本地的任何node命令都會使用這個版本的node可執行文件。

    你能夠指定工做的node的版本:

    { "engines" : { "node" : ">=0.10.3 <0.12" }="" }<="" code="">
        
        
        
    
       複製代碼

    而且,像dependensies同樣,若是你不指定版本或者指定「*」做爲版本,那麼全部版本的node均可以。

    若是指定一個engines字段,那麼npm會須要node在裏面,若是「engines」被省略,npm會假定它在node上工做。

    你也能夠用engines字段來指定哪個npm版本能更好地初始化你的程序,如:

    { "engines" : { "npm" : "~1.0.20" } }複製代碼

    除非用戶設置engine-strict標記,這個字段只是建議值。

  • engineStrict
    若是你肯定你的模塊必定不會運行在你指定版本以外的node或者npm上,你能夠在package.json文件中設置engineStrict:true。它會重寫用戶的engine-strict設置。

第三方包:pre-commit/node-config/commander/chalk

這幾個包分別用來處理提交執行腳本,全局配置文件管理與命令行處理。會在代碼中一一講解。

代碼文件

建立any-cli項目

work$mkdir any-cli
work$cd any-cli
any-cli$git init && npm init複製代碼

package.json內容

{
  "name": "any-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "pub": "npm version patch && npm publish",
    "pre-commit": "eslint src"
  },
  "author": "antgod",
  "devDependencies": {
    "eslint": "^3.16.1",
    "eslint-config-airbnb": "^12.0.0",
    "eslint-plugin-babel": "^3.0.0",
    "eslint-plugin-import": "^1.6.1",
    "eslint-plugin-jsx-a11y": "^2.0.1",
    "eslint-plugin-markdown": "*",
    "eslint-plugin-react": "^6.3.0",
    "eslint-tinker": "^0.3.2",
    "pre-commit": "^1.2.2"
  },
  "dependencies": {
    "chalk": "^1.1.3",
    "child_process": "^1.0.2",
    "commander": "^2.9.0",
    "prompt": "^1.0.0"
  },
  "engines": {
    "install-node": "7.6.0"
  },
  "pre-commit": [
    "pre-commit"
  ],
  "bin": {
    "any": "./bin/any"
  },
  "license": "ISC"
}複製代碼
  • 字段bin下面配置被當作命令行可執行命令。指向/bin下面的any文件。
  • 字段engines用來當前目錄安裝7.6.0版本node,可直接使用async函數而無須要再使用co模塊。
  • pre-commit用來作提交前代碼檢查,運行pre-commit腳本,也就是eslint。

    在根目錄下創建/bin 文件夾,建立any文件(無後綴名)。這個 /bin/any是整個腳手架的入口文件,因此咱們首先對它進行編寫。

# !/usr/bin/env node
const add = require('../src/command/add')
const list = require('../src/command/list')
const init = require('../src/command/init')
const del = require('../src/command/del')
const program = require('commander')
const { version } = require('../package')

// 定義當前版本
program
.version(version)

program.parse(process.argv)
if (!program.args.length) {
  program.help()
}複製代碼

運行npm link,把當前項目連接到全局。這樣就能夠直接在命令行使用any命令測試/bin/any下面的代碼

若是沒有權限,請自行百度,使用chmod 777爲usr/local目錄添加權限複製代碼
any-cli@npm link
any-cli@any複製代碼

咱們繼續在/bin/any中添加代碼

// 定義使用方法
program
.command('add')
.description('add template')
.alias('a')
.action(add)

program
.command('del')
.description('Delete a template')
.alias('d')
.action(del)

program
.command('list')
.description('List all the templates')
.alias('l')
.action(list)

 program
.command('init')
.description('Generate a new project')
.alias('i')
.action(init)複製代碼

command用來配置any命令的參數,alias配置縮寫,action配置運行什麼函數。其餘就不用多說了吧,程序員你懂的。

commander 的具體使用方法在這裏就不展開了,能夠直接到 [官網][2] 去看詳細的文檔。複製代碼

使用any命令,看到輸出以下,證實入口文件已經編寫完成了。

Usage: any [options] [command]


  Commands:

    add|a    add template
    del|d    Delete a template
    list|l   List all the templates
    init|i   Generate a new project

  Options:

    -h, --help     output usage information
    -V, --version  output the version number複製代碼

接着,咱們建立src/command目錄,下面分別建立剛纔的4個參數所對應的文件。文件內容是具體業務代碼(分別對應增刪查初始化),在此不作介紹。請參考github連接。代碼使用了函數式編程,須要有點函數式基礎。

相關文章
相關標籤/搜索