npm和package.json那些不爲常人所知的小祕密

此文已由做者黃鍇受權網易雲社區發佈。
javascript

歡迎訪問網易雲社區,瞭解更多網易技術產品運營經驗。css


強大的命令功能

若是你沒使用過script,那你可算是歷來沒手動編輯過package.json。script做爲package.json裏最強大的功能,它賦予你新增腳本的能力。特別是從npm@2.0.0 以後,你能夠用自定義參數執行腳本。甚至有人宣言,有了npm你能夠中止使用Grunt和Gulp了html

查詢腳本

你能夠經過輸入npm run查看全部的命令列表(雖然你也能夠直接查看package.json)java

image-20181023103906319

自定義腳本

例如咱們最經常使用的npm start,npm run dev ……,這些腳本都是能夠用戶自定義的,只用在scripts中寫相應的shell腳本,能夠快速的幫助咱們編寫打包,啓動腳本。node

"scripts": {    "build": "webpack --config build.js",    "start": "node index.js",    "test": "tap test/*.js"}

而後你能夠經過npm run ...執行 注意,start命令能夠不用run,後面會講react

同時,執行腳本的時,npm會臨時自動將目錄的node_modules/.bin加入PATH變量。這意味着,可使用node_modules中任何腳本,而無需添加node_modules/.bin前綴。好比,當前項目的依賴裏面有 Mocha,只要直接寫mocha test就能夠了。linux

例如執行tap命令,你能夠直接寫:webpack

"scripts": {"test": "tap test/\*.js"}

而不是git

"scripts": {"test": "node_modules/.bin/tap test/\*.js"}

傳遞參數

若是咱們在執行npm run xxx 操做的時候想給裏面的腳本傳參數可使用—,以下所示:github

 "scripts": {    "test": "mocha test/",    "test:xunit": "npm run test -- --reporter xunit"
  }

這種設置對於組合一些高級配置的命令是很是有用的。

「scripts」: {    "lint": "jshint **.js",    "lint:checkstyle": "npm run lint -- --reporter checkstyle > checkstyle.xml"}

生命週期鉤子

這裏借用不少框架的生命週期鉤子的概念,其實npm也在不一樣的生命週期 提供了一些鉤子,能夠方便你在項目運行的不一樣時間點進行一些腳本的編寫。

它的鉤子分爲兩類:pre- 和 post- ,前者是在腳本運行前,後者是在腳本運行後執行。全部的命令腳本均可以使用鉤子(包括自定義的腳本)。

例如:運行npm run build,會按如下順序執行:

npm run prebuild -->  npm run build -->  npm run postbuild

pre腳本和post腳本也是出口代碼敏感(exit-code-sensitive) 的,這意味着若是您的pre腳本以非零出口代碼退出,那麼NPM將當即中止,而且不運行後續腳本。

一般你能夠在pre腳本上執行一些準備工做,在post腳本上執行一些後續操做。

"clean": "rimraf ./dist && mkdir dist","prebuild": "npm run clean","build": "cross-env NODE_ENV=production webpack"

另外,還有不少額外的生命週期鉤子,能夠方便使用,例如husky  和 pre-commit 包提供了有關git的commit的生命週期鉤子。

使用環境變量

根據官網的介紹 ,在"scripts"中編寫的腳本還能夠方便使用一些內置變量,這些內置變量會在Node運行的時候放在process.env下,若是是shell腳本,就直接使用環境變量$…,  這對你編寫一些腳本工具特別有用。

package.json

package.json內的全部的配置項均可以經過npm_package_前綴拿到,例如

"show": "echo $npm_package_name && echo $npm_package_version"

若是是使用node:

"show": "node ./show.js"
// show.jsconst { log } = console;
log(process.env.npm_package_name);
log(process.env.npm_package_version);

image-20181024114103465

嵌套的屬性也能夠經過_代替.進行嵌套顯示:**$npm_package_scripts_start**

configuration

配置參數放在**npm_config_**前綴的環境中(你能夠經過 npm config set 設置一些配置變量,下面介紹config的時候會介紹)

例如:

image-20181030105015315

一些經常使用的腳本配置

這裏引用阮老師的一些配置,能夠看到配合必定的插件,npm但是實現一些很實用的功能

// 刪除目錄"clean": "rimraf dist/*",// 本地搭建一個 HTTP 服務"serve": "http-server -p 9090 dist/",// 打開瀏覽器"open:dev": "opener http://localhost:9090",// 實時刷新
 "livereload": "live-reload --port 9091 dist/",// 構建 HTML 文件"build:html": "jade index.jade > dist/index.html",// 只要 CSS 文件有變更,就從新執行構建"watch:css": "watch 'npm run build:css' assets/styles/",// 只要 HTML 文件有變更,就從新執行構建"watch:html": "watch 'npm run build:html' assets/html",// 部署到 Amazon S3"deploy:prod": "s3-cli sync ./dist/ s3://example-com/prod-site/",// 構建 favicon"build:favicon": "node scripts/favicon.js",

npx

npm v5.2.0 以後還引入了npx,引入這個命令的目的是爲了提高開發者使用包內提供的命令行工具的體驗。(在node_modules中,全部可執行文件,也就是package中帶bin的,都會放在node_modules/.bin中)

舉例:使用create-react-app建立一個react項目。

老方法:

npm install -g create-react-app   // 實際就是把package.json中的bin命令鏈接到了/usr/local/bin中create-react-app my-app

npx方式:

npx create-react-app my-app // 執行本`node_modules/.bin`中的對應命令

這條命令會臨時安裝 create-react-app 包,命令完成後create-react-app 會刪掉,不會出如今 global 中。下次再執行,仍是會從新臨時安裝。

npx 會幫你執行依賴包裏的二進制文件。

舉例來講,以前咱們可能會寫這樣的命令:

npm i -D webpack
./node_modules/.bin/webpack -v

若是你對 bash 比較熟,可能會寫成這樣:

npm i -D webpack
**npm bin**/webpack -v

有了 npx,你只須要這樣:

npm i -D webpack
npx webpack -v

也就是說 npx 會自動查找當前依賴包中的可執行文件,若是找不到,就會去 PATH 裏找。若是依然找不到,就會幫你安裝!

npx 甚至支持運行遠程倉庫的可執行文件:

npx github:piuccio/cowsay hello

再好比 npx http-server 能夠一句話幫你開啓一個靜態服務器!(第一次運行會稍微慢一些)

npx http-server

指定node版原本運行npm scripts:

npx -p node@8 npm run build

主要特色:

一、臨時安裝可執行依賴包,不用全局安裝,不用擔憂長期的污染。 二、能夠執行依賴包中的命令,安裝完成自動運行。 三、自動加載node_modules中依賴包,不用指定$PATH。 四、能夠指定node版本、命令的版本,解決了不一樣項目使用不一樣版本的命令的問題。

內置命令(腳本)

npm自帶了 數十個內置命令,這些命令均可以直接經過npm執行,除了install,還有不少實用的

image-20181023105039767

與script相關

其中有幾條和咱們剛纔說過的script十分相關,咱們能夠經過在scripts中改寫命令執行。

  • start , npm run start的簡寫,若是不在script中配置start,那麼npm start默認執行node server.js

  • test ,npm run test的簡寫,執行自定義test腳本,沒有默認行爲。

  • stop,npm run stop的簡寫

  • restart,npm run stop && npm run restart && npm run start的簡寫

image-20181023110627346

其餘實用的命令

咱們常常用的是install,可是其實還有不少命令很實用:

  • npm -l  列舉全部npm自帶的命令簡介,而後經過npm help能夠詳細查看某個命令

  • npm search 快速查詢npm中的相關包(和咱們去npm官網查是同樣的)

  • npm root 查看全局的node_modules目錄

  • npm audit fix 這個命令很實用,自動掃描您的項目漏洞,並自動安裝任何兼容更新到脆弱的依賴

  • npm restart 從新啓動模塊

  • npm prune 移除當前不在package.json中可是存在node_modules中的依賴

  • npm repo 瀏覽器端打開項目地址(GitHub), 省去打開瀏覽器查找的操做!

  • npm docs 查看項目文檔,同上

  • npm home 在瀏覽器端查看項目(項目主頁),同上

  • npm search 查找包含該字符串的依賴包

  • npm view[field][--json]列出依賴信息,包括歷史版本,能夠指定field來查看某個具體信息,好比(versions) 能夠添加–json參數輸出所有結果

    image-20181023111220672

亂七八糟的版本號

我相信只要打開package.json,第一眼就會被裏面一堆亂七八糟的數字給晃得暈頭轉向,隨便給你晃一眼:

  { "foo" : "1.0.0 - 2.9999.9999"
  , "bar" : ">=1.0.2 <2.1.2"
  , "baz" : ">1.0.2 <=2.3.4"
  , "boo" : "^2.0.1"
  , "qux" : "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0"
  , "lal" : "git://……"
  , "asd" : "http://asdf.com/asdf.tar.gz"
  , "til" : "~1.2"
  , "abc" : "haha/abc"
  , "elf" : "~1.2.3"
  , "two" : "2.x"
  , "thr" : "3.3.x"
  ……  }

光是看到數字就已經暈了,還有~,<>,^這麼多符號。npm官網推薦使用語義化的版本好,通常按以下規則:

首先版本按照大版本.次要版本.小版本,通常來講初始版本是1.0.0:

  • 小版本:修改bug或其餘小的改動

  • 次要版本:增長了新的特性不改變已有特性

  • 大版本:大的變更,可能影響了向後的兼容性

版本匹配

  • 指定版本:好比1.2.2,安裝時只安裝指定版本。

  • ~次要版本不變:好比~1.2.2,表示安裝1.2.x的最新版本(不低於1.2.2),可是不安裝1.3.x,也就是說安裝時不改變大版本號和次要版本號。

  • ^大版本不變:好比ˆ1.2.2,表示安裝1.x.x的最新版本(不低於1.2.2),可是不安裝2.x.x,也就是說安裝時不改變大版本號。須要注意的是,若是大版本號爲0,則插入號的行爲與波浪號相同,這是由於此時處於開發階段,即便是次要版本號變更,也可能帶來程序的不兼容。

  • latest:安裝最新版本。

node-semver

若是你須要在程序中作版本匹配,手寫是否是很麻煩(我以前還真的本身用正則寫了一個,超麻煩)其實npm提供了一個現成的匹配版本號的工具: https://github.com/npm/node-semver#functions

指定項目運行環境

不少時候,咱們的項目只能在特定的環境下執行,在其餘環境下可能會報錯,所以咱們須要在package.json中限制用戶執行項目的環境:

engines指明瞭該項目所須要的node.js版本

"engines": {"node" : ">= 4.0.0","npm": ">= 3.0.0"}

os指定了用戶執行的操做系統:

"os": [ "darwin", "linux", "!win32" ],

cpu能夠指定包運行的cpu架構

  "cpu": [ "x64", "!arm" ]

config

以前咱們說過npm有個配置文件,裏面的變量能夠經過$npmconfig拿到,而這個配置文件一般在:

  • 項目config file (/path/to/my/project/.npmrc) : 一般要本身建立

  • 用戶config file (~/.npmrc)

  • 全局config file ($PREFIX/etc/npmrc)

  • npm內置config file (/path/to/npm/npmrc)

經過如下命令能夠查看config信息:

npm config ls/list

123

npm有不少默認配置,能夠經過如下命令查看,能夠去官網查看這些命令的詳細信息

npm config ls -l

image-20181030115814087

經過如下命令能夠修改配置

npm config set key valuenpm set key valuenpm config get keynpm get key

固然,也能夠經過$npm_config_key = 來修改,或者在node中經過**process.env.npm_config_key = 來修改,

數組值是經過在鍵名後面添加「[]」來指定的。例如:

key[] = "first value"key[] = "second value"

安裝非NPM上發佈的包

一般,咱們安裝的包都是在npm官網上,經過版本標明。可是,若是我想使用沒上傳到npm上的包怎麼辦?其實你能夠直接加網址或git地址。官網明確瞭如下類型的包都是能夠的:

a) 包含一個由package.json文件描述的程序的文件夾。

b) 包含(a)的gzipped tarball 。

c)解析爲(b)的URL。

d) \@\ : 在registry上發佈的(c)

e)\@\ : 能指向(d)。

f)\:  具備latest標籤,且知足(e)。

g)git url,當clone時,獲得(a)。

只要知足以上條件,你的包不用發佈到npm上都能使用。其中,git url能夠是如下形式:

git://github.com/user/project.git#commit-ishgit+ssh://user@hostname:project.git#commit-ishgit+http://user@hostname/project/blah.git#commit-ishgit+https://user@hostname/project/blah.git#commit-ish

其中,commit-ish 能夠是任意的tag,branch,sha。

dependencies & devDependencies & peerDependencies

衆所周知,package.json裏有一堆dpendencies字段,他們像親兄弟同樣,老是結伴同行。不少人容易弄混他們究竟是什麼關係。

因爲這裏面內容挺多的,會整理在另外一篇文章中,後續這裏會放上連接

更新包

咱們知道npm自帶的npm update能夠根據pacaage.json的版本號更新包,可是你須要手動的更新版本號,所以出現了升級插件npm-check-updates,能夠自動搜索當前包的更新狀況,而且修改pacage.json

安裝npm-check-updates

$ npm install -g npm-check-updates

ncu命令

ncu是npm-check-updates的縮寫命令

$ ncu  -v  #查詢版本號
$ ncu    #直接輸入ncu能夠查看全部須要更新的包

image-20181030113416839

$ ncu -u  # 更新全部的包,並修改package.json文件

image-20181030113457081

$ ncu -f regex # 只匹配特定的正則格式的包
$ ncu -g # 更新全局包

image-20181030113548646

參考文檔:

https://docs.npmjs.com/misc/scripts

https://docs.npmjs.com/cli/run-script

https://docs.npmjs.com/files/package.json

https://stackoverflow.com/questions/18875674/whats-the-difference-between-dependencies-devdependencies-and-peerdependencies

http://javascript.ruanyifeng.com/nodejs/packagejson.html#toc1

https://www.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/


免費體驗雲安全(易盾)內容安全、驗證碼等服務

更多網易技術、產品、運營經驗分享請點擊




相關文章:
【推薦】 流式處理框架storm淺析(下篇)
【推薦】 「貨品未動,數據先行」,德邦快遞與網易雲聯合打造「智能物流」
【推薦】 一文看盡 Raft 一致性協議的關鍵點

相關文章
相關標籤/搜索