每一個項目的根目錄都有一個package.json
文件,定義了這個項目所須要的各類模塊,以及項目的配置信息,下面是一個比較完整的package.json文件
vue
{
"name": "vue-cli",
"version": "2.9.3",
"description": "A simple CLI for scaffolding Vue.js projects.",
"preferGlobal": true,
"bin": {
"vue": "bin/vue",
"vue-init": "bin/vue-init",
"vue-list": "bin/vue-list"
},
"repository": {
"type": "",
"url": ""
},
"keywords": [
],
"author": "litongqian",
"license": "MIT",
"bugs": {
"url": ""
},
"homepage": "",
"scripts": {
"test": "npm run lint && npm run e2e",
"start": "node index.js"
},
"dependencies": {
"async": "^2.4.0",
"chalk": "^2.1.0",
},
"devDependencies": {
"chai": "^4.1.2",
"eslint": "^3.19.0",
},
"engines": {
"node": ">=6.0.0"
}
}
複製代碼
1. 其中scripts字段
指定了運行腳本命令的npm命令行縮寫,好比start指定了運行npm run start
時,所要執行的命令。
node
2. bin字段vue-cli
bin項用來指定各個內部命令對應的可執行文件的位置shell
"bin": {
"vue": "bin/vue",
"vue-init": "bin/vue-init",
"vue-list": "bin/vue-list"
},複製代碼
上面代碼指定,vue 命令對應的可執行文件爲 bin 子目錄下的vue。npm
3. npm linkjson
項目目錄:數組
本身開發模塊的時候,好比上面的mymodule模塊,若是想在hello中使用,咱們能夠採用相對路徑require('./mymodule')
加載模塊。bash
也可使用自定義模塊標識require('mymodule'),
Node加載自定義模塊須要將其安裝到全局的或項目的node_modules
目錄之中。對於上述模塊,解決方法就是在全局的node_modules
目錄之中,生成一個符號連接,指向模塊的本地目錄。async
npm link
就能起到這個做用,會自動創建這個符號連接。函數
mymodule
,目錄爲hello/mymodule
,你本身的項目要用到這個模塊,首先,在模塊目錄(src/mymodule
)下運行npm link
命令。hello/mymodule$ npm link
複製代碼
上面的命令會在NPM的全局模塊目錄內,生成一個符號連接文件,該文件的名字就是package.json
文件中指定的模塊名。
/usr/local/lib/node_modules/mymodule -> /Users/tongqianli/Desktop/work/hello/mymodule複製代碼
這個時候,已經可使用mymodule
模塊了。
這時能夠經過添加path解決:
操做系統中都會有一個PATH
環境變量,系統調用一個命令的時候,就會在PATH變量中註冊的路徑中尋找,若是註冊的路徑中有就調用,不然就提示命令沒找到。
-> export PATH=$PATH: # 將 /usr/bin 追加到 PATH 變量中
-> export NODE_PATH="/usr/lib/node_modules;/usr/local/lib/node_modules" #指定 NODE_PATH 變量
複製代碼
那 NODE_PATH
就是NODE
中用來尋找模塊所提供的路徑註冊環境變量
。咱們可使用上面的方法指定NODE_PATH環境變量。
更好的辦法:
切換到項目目錄,再次運行npm link
命令,並指定模塊名。
hello tongqianli$ npm link mymodule複製代碼
上面命令生成了本地node_modules/mymodule模塊映射到全局的node_modules/mymodule ,全局,全局的映射到本地hello/mymodule。
/Users/tongqianli/Desktop/work/hello/node_modules/mymodule
-> /usr/local/lib/node_modules/mymodule
-> /Users/tongqianli/Desktop/work/hello/mymodule複製代碼
而後,就能夠在你的項目中,加載該模塊了。
var myModule = require('myModule');
複製代碼
這樣一來,mymodule
的任何變化,均可以直接反映在項目之中。可是,這樣也出現了風險,任何在目錄中對mymodule
的修改,都會反映到模塊的源碼中。
若是你的項目再也不須要該模塊,能夠在項目目錄內使用npm unlink
命令,刪除符號連接。
hello tongqianli$ npm unlink mymodule複製代碼
寫一個簡單的腳本hello
$ mkdir
hello
#建立一個文件夾
$
cd
hello && touch
hello #建立命令文件
#!/usr/bin/env node
console.log('hello world');
複製代碼
文件的頭部加入#!/usr/bin/env node這行代碼,這裏表示使用node做爲腳本的解釋程序,能夠省略node ./hello,直接運行./hello, node的路徑經過env來查找,能夠避免node安裝的路徑不同帶來找不到的問題。
打開/usr/bin/env,能夠查看到PATH,操做系統經過路徑找到node
而後,修改 hello 的權限。
$ chmod 755 hello
$./hello複製代碼
若是想把 hello 前面的路徑去除,能夠將 hello 的路徑加入環境變量 PATH。可是,另外一種更好的作法,是在當前目錄下新建 package.json ,寫入下面的內容。
{
"name": "hello",
"bin": {
"hello": "./hello"
}
}複製代碼
而後執行 npm link 命令。不明白的看上面
$ npm link複製代碼
執行後會產生一個全局的映射關係,可執行腳本bin/hello映射到全局node_modules/hello/hello,全局的node_modules/hello映射到本地hello,這樣就可使用hello了
命令行參數能夠用系統變量 process.argv 獲取。
修改hello腳本
#!/usr/bin/env node
console.log('hello ', process.argv);複製代碼
其中process爲node進程中的全局變量,process.argv爲一數組,數組內存儲着命令行的各個部分,argv[0]爲node的安裝路徑,argv[1]爲主模塊文件路勁,剩下爲子命令或參數,以下:
$ hello a b c
# process.argv的值爲[ '/usr/local/bin/node', '/usr/local/bin/hello', 'a', 'b', 'c' ]
|
腳本能夠經過 child_process 模塊新建子進程,從而執行 Unix 系統命令,修改hello
exec
方法用於執行bash命令,exec
方法最多能夠接受兩個參數,第一個參數是所要執行的shell命令,第二個參數是回調函數,該函數接受三個參數,分別是發生的錯誤、標準輸出的顯示結果、標準錯誤的顯示結果。
#!/usr/bin/env node
var name = process.argv[2];
var exec = require('child_process').exec;
var child = exec('echo hello ' + name, function(err, stdout, stderr) {
if (err) throw err;
console.log(stdout);
});複製代碼
執行$ hello litongqian
若是咱們想查看全部文件,修改hello
var name = process.argv[2];
var exec = require('child_process').exec;
var child = exec(name, function(err, stdout, stderr) {
if (err) throw err;
console.log(stdout);
});複製代碼
執行$ hello ls
hello目錄下有三個文件
shell.js 模塊從新包裝了 child_process,調用系統命令更加方便。它須要安裝後使用。
npm install --save shelljs
複製代碼
而後,改寫腳本。
#!/usr/bin/env node
var name = process.argv[2];
var shell = require("shelljs");
shell.exec("echo hello " + name);複製代碼
shelljs 只解決了如何調用 shell 命令,而 yargs 模塊可以解決如何處理命令行參數。它也須要安裝。
$ npm install --save yargs
複製代碼
yargs 模塊提供 argv 對象,用來讀取命令行參數。請看改寫後的 hello 。
#!/usr/bin/env node
var argv = require('yargs').argv;
console.log('hello ', argv.name);
複製代碼
使用時,下面兩種用法均可以。
$ hello --name=tom
hello tom
$ hello --name tom
hello tom
複製代碼
也就是說,process.argv 的原始返回值以下。
$ node hello --name=tom
[ 'node',
'/usr/local/bin/hell',
'--name=tom' ]
複製代碼
yargs 能夠上面的結果改成一個對象,每一個參數項就是一個鍵值對。
經過npm publish進行發佈,前提是有npm賬號。如何操做能夠查看npm 官方文檔。
本文是經過原生node.js來開發命令工具,而vue-cli是採用commander.js來簡化命令工具開發,
瞭解了執行流程,學習對應的模塊,就能夠了!,本文拋個磚頭
bin項用來指定各個內部命令對應的可執行文件的位置。
"name":"someTool",
"bin": {
"someTool": "./bin/someTool.js"
}
複製代碼
上面代碼指定,someTool 命令對應的可執行文件爲 bin 子目錄下的 someTool.js。
當一個項目依賴上面的someTool工具時,同時只是本地安裝
{
"name": "myproject",
"devDependencies": {
"someTool": "latest"
},
"scripts": {
start: 'someTool build' //等同於start: './node_modules/someTool/someTool.js build'
}
}複製代碼
npm會尋找這個文件,在node_modules/.bin/
目錄下創建符號連接。在上面的例子中,someTool.js會創建符號連接npm_modules/.bin/someTool
。因爲node_modules/.bin/
目錄會在運行時加入系統的PATH變量,所以在運行npm時,就能夠不帶路徑,直接經過命令來調用這些腳本。
所以,像上面這樣的寫法能夠採用簡寫。
scripts: {
start: './node_modules/someTool/someTool.js build'
}
// 簡寫爲
scripts: {
start: 'someTool build'
}
複製代碼
全部node_modules/.bin/
目錄下的命令,均可以用npm run [命令]
的格式運行。在命令行下,鍵入npm run
,而後按tab鍵,就會顯示全部可使用的命令。
上面代碼中,scripts
字段指定了兩項命令
npm run-script start
或者
npm run start
,就會執行
someTool build。
npm run
是
npm run-script
的縮寫,通常都使用前者,可是後者能夠更好地反應這個命令的本質。
npm run
命令會自動在環境變量$PATH
添加node_modules/.bin
目錄,因此scripts
字段裏面調用命令時不用加上路徑,這就避免了全局安裝NPM模塊。
npm run
若是不加任何參數,直接運行,會列出package.json
裏面全部能夠執行的腳本命令。
npm內置了兩個命令簡寫,npm test
等同於執行npm run test
,npm start
等同於執行npm run start
。
npm run
會建立一個Shell,執行指定的命令,並臨時將node_modules/.bin
加入PATH變量,這意味着本地模塊能夠直接運行。
舉例來講,你執行ESLint的安裝命令。
$ npm i eslint --save-dev
複製代碼
運行上面的命令之後,會產生兩個結果。首先,ESLint被安裝到當前目錄的node_modules
子目錄;其次,node_modules/.bin
目錄會生成一個符號連接node_modules/.bin/eslint
,指向ESLint模塊的可執行腳本。
而後,你就能夠在package.json
的script
屬性裏面,不帶路徑的引用eslint
這個腳本。
{
"name": "Test Project",
"devDependencies": {
"eslint": "^1.10.3"
},
"scripts": {
"lint": "eslint ."
}
}
複製代碼
等到運行npm run lint
的時候,它會自動執行./node_modules/.bin/eslint .
。
若是直接運行npm run
不給出任何參數,就會列出scripts
屬性下全部命令。
$ npm run
Available scripts in the user-service package:
lint
jshint **.js
test
mocha test/複製代碼