npm和package.json那些不為常人所知的小秘密


此文已由作者黃鍇授權網易雲社區發布。

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


強大的命令功能

如果你沒使用過script,那你可算是從來沒手動編輯過package.json。script作為package.json里最強大的功能,它賦予你新增腳本的能力。特別是從npm@2.0.0 之后,你可以用自定義參數執行腳本。甚至有人宣言,有了npm你可以停止使用Grunt和Gulp了

查詢腳本

你可以通過輸入npm run查看所有的命令列表(雖然你也可以直接查看package.json)

image-20181023103906319

自定義腳本

例如我們最常用的npm start,npm run dev ……,這些腳本都是可以用戶自定義的,只用在scripts中寫相應的shell腳本,可以快速的幫助我們編寫打包,啟動腳本。

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

然后你可以通過npm run ...執行 注意,start命令可以不用run,后面會講

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

例如執行tap命令,你可以直接寫:

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

而不是

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

傳遞參數

如果我們在執行npm run xxx 操作的時候想給里面的腳本傳參數可以使用—,如下所示:

 "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

主要特點:

1、臨時安裝可執行依賴包,不用全局安裝,不用擔心長期的污染。 2、可以執行依賴包中的命令,安裝完成自動運行。 3、自動加載node_modules中依賴包,不用指定$PATH。 4、可以指定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 一致性協議的關鍵點


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM