@author ASCE1885的 Github 簡(jiǎn)書 微博 CSDN 知乎
本文由于潛在的商業(yè)目的千扶,不開放全文轉(zhuǎn)載許可踪宠,謝謝!
![image_1akdbc4t86e41r17s2518obtgb13.png-1421.1kB](http://static.zybuluo.com/asce1885/apinko0aqzo3qplp5mkvgraw/image_1akdbc4t86e41r17s2518obtgb13.png)
廣而告之時(shí)間:我的新書《Android 高級(jí)進(jìn)階》(https://item.jd.com/10821975932.html )在京東開始預(yù)售了,歡迎訂購唤冈!
![TB2MnqlXH1J.eBjSszcXXbFzVXa_!!1020536390.png-39kB](http://static.zybuluo.com/asce1885/v2irpmkyhn70ilo1zf0d3sd0/TB2MnqlXH1J.eBjSszcXXbFzVXa_!!1020536390.png)
npm帅容,全稱是 node package manager颇象,顧名思義最開始是作為 Node 的包管理器存在的。不過經(jīng)過不斷的發(fā)展和壯大并徘,現(xiàn)在的 npm 早就不再局限于 Node 的范疇遣钳,已經(jīng)成為 Javascript 的包管理器,看看下面的 npm 官網(wǎng)首頁介紹就知道了:
![image_1ak5a6lts1i7t1taee9t12djb599.png-313.4kB](http://static.zybuluo.com/asce1885/pcndchiqh39tpviwaw7wt6xa/image_1ak5a6lts1i7t1taee9t12djb599.png)
本系列教程假設(shè)你已經(jīng)按照 React Native 官方入門指南安裝好相關(guān)的環(huán)境(尤其是 Node.js)麦乞,并且執(zhí)行 react-native init AwesomeProject
命令生成了 Demo 工程 AwesomeProject蕴茴,工程目錄結(jié)構(gòu)如下圖所示:
![image_1ak5eb3u0h5u1gandlpjle1e1v9.png-151.2kB](http://static.zybuluo.com/asce1885/5oxeuiwjabnc5bk743rnzx2j/image_1ak5eb3u0h5u1gandlpjle1e1v9.png)
package.json 的文件結(jié)構(gòu)
從上圖中可以看到劝评,AwesomeProject 工程的根目錄有一個(gè)名為 package.json
的文件,它是工程的元數(shù)據(jù)集荐开,主要作用有:
- 管理項(xiàng)目中依賴的第三方包付翁,可以很方便的和團(tuán)隊(duì)中其他開發(fā)者共享工程的依賴配置,這樣不需要每個(gè)人都手動(dòng)
npm install
相應(yīng)的依賴包 - 定義 npm 中可以執(zhí)行的腳本
一個(gè)合格的 package.json
文件需要至少包含 name
和 version
兩個(gè)字段晃听,這兩個(gè)字段組成的二元組可以唯一標(biāo)識(shí)一個(gè)包百侧,如下所示:
{
"name": "AwesomeProject",
"version": "0.0.1"
}
當(dāng)然一般情況下,工程的 package.json 不可能這么簡(jiǎn)單能扒,常用的字段和解釋如下表所示佣渴,開發(fā)者需要根據(jù)具體的業(yè)務(wù)需求進(jìn)行選擇:
字段名 | 含義 | 示例 |
---|---|---|
name | 包名需要具備唯一性,而且字母必須全部小寫初斑,如果一個(gè)包缺少這個(gè)字段辛润,使用 npm install 將會(huì)失敗 | "name": "redux" |
version | 包的版本號(hào),遵循語義化版本(http://semver.org/lang/zh-CN/)格式见秤,也就是版本號(hào)包含三位:MAJOR.MINOR.PATCH 砂竖。MAJOR 表示版本發(fā)生大的變化,例如 API 不兼容舊版本鹃答;MINOR 表示版本增加新功能乎澄,但是兼容舊版本的;PATCH 表示兼容舊版本的一些 bug 修復(fù) |
"version": "3.5.2" |
description | 項(xiàng)目的描述测摔,盡量保持言簡(jiǎn)意賅 | "description": "Predictable state container for JavaScript apps" |
author | 項(xiàng)目的作者名字和郵件地址置济,如果有多個(gè),以 JSON 數(shù)組形式表示 | "authors": ["Dan Abramov dan.abramov@me.com(https://github.com/gaearon)","Andrew Clark acdlite@me.com(https://github.com/acdlite)"] |
contributors | 項(xiàng)目的貢獻(xiàn)者名單锋八,以 JSON 數(shù)組的形式表示 | "contributors": [{"name": "asce1885","email": "asce1885@gmail.com"}] |
bin | 項(xiàng)目對(duì)外暴露的 CLI 接口浙于,提供給其他項(xiàng)目使用的腳本 | "bin": {"module-name":"./bin/module-name"} |
scripts | 定義 npm 腳本命令,key 值表示命令名挟纱,value 值表示命令對(duì)應(yīng)的腳本或者腳本的路徑羞酗,通過 npm run 或者 npm run-script 可以執(zhí)行對(duì)應(yīng)的命令 |
"scripts": { "clean": "rimraf lib dist es coverage", "lint": "eslint src test examples build", "start": "node node_modules/react-native/local-cli/cli.js start" |
main | 工程生成的 Package 的主入口點(diǎn),當(dāng)在 node 中調(diào)用 require('{module name}') 時(shí)會(huì) require 到這個(gè)文件 |
"main": "lib/index.js" |
repostitory | 如果我們這個(gè)工程是開源的紊服,這個(gè)字段用來指明工程的倉庫 URL 地址以及版本控制系統(tǒng)的類型檀轨,這可以方便其他開發(fā)者貢獻(xiàn)代碼 | "repository": { "type": "git", "url": "https://github.com/reactjs/redux.git" } |
bugs | 使用者可以提交bugs的 URL 或者郵件地址 | "bugs": {"url": "https://github.com/reactjs/redux/issues"} |
keywords | 描述這個(gè) Package 的關(guān)鍵字信息,方便用戶通過關(guān)鍵字搜索到這個(gè) Package | "keywords": ["redux","reducer","state","predictable","functional","immutable","hot","live","replay","flux","elm"] |
dependencies | 這個(gè) Package 的生產(chǎn)依賴围苫,當(dāng)用戶安裝你的 Package 時(shí)會(huì)自動(dòng)安裝這些依賴 | "dependencies": { "react": "^15.1.0", "react-native": "^0.27.0-rc2" } |
devDependencies | 這個(gè) Package 在開發(fā)或者測(cè)試階段的依賴裤园,不會(huì)打包到最終的生產(chǎn)包中 | "devDependencies": { "babel-eslint": "^5.0.0", "eslint": "^2.1.0", "eslint-plugin-react": "^3.16.1" } |
preferGlobal | 表明這個(gè) Package 希望通過 npm install -g {module-name} 全局安裝撤师,這個(gè)字段是給包含了 CLI 的 Package 使用剂府, 其他情況下不要使用這個(gè)字段 |
"preferGlobal": true |
private | 設(shè)置為 true 時(shí),npm 將不會(huì)發(fā)布這個(gè) Package剃盾,這個(gè)標(biāo)記主要用來防止不小心發(fā)布某個(gè)內(nèi)部使用的私有 Package 到公共的 npm registry | "private": true |
publishConfig | 發(fā)布這個(gè) Package 時(shí)用到的一些配置信息腺占,這些配置信息會(huì)覆蓋默認(rèn)的 npm 配置 | "publishConfig": { "registry": "https://your-private-hosted-npm.registry.nodejitsu.com" } |
subdomain | 指明應(yīng)用的 subdomain淤袜,說明應(yīng)該只包含 subdomain,而不是 root domain | |
analyze | 如果你的 Package 托管在 Nodejitsu(https://www.nodejitsu.com/) 上面衰伯,同時(shí)將這個(gè)字段設(shè)置為 true铡羡,Nodejitsu 將會(huì)自動(dòng)嘗試掃描你的 Package,可以及時(shí)發(fā)現(xiàn)缺少的依賴意鲸,可能存在的 bugs 以及語法錯(cuò)誤等 | "analyze": true |
license | 如果這個(gè) Package 是開源的烦周,此處指定它遵循的許可協(xié)議 | "license": "MIT" |
一個(gè)真實(shí)項(xiàng)目的 Package.json
文件內(nèi)容如下所示(取自 redux-logger[1])
{
"name": "redux-logger",
"version": "2.6.1",
"description": "Logger for Redux",
"main": "lib/index.js",
"scripts": {
"lint": "$(npm bin)/eslint src",
"test": "npm run lint",
"clean": "$(npm bin)/rimraf dist lib",
"build:lib": "$(npm bin)/babel src --out-dir lib",
"build:umd": "LIBRARY_NAME=reduxLogger NODE_ENV=development $(npm bin)/webpack src/index.js dist/index.js --config webpack.build.js",
"build:umd:min": "LIBRARY_NAME=reduxLogger NODE_ENV=production $(npm bin)/webpack -p src/index.js dist/index.min.js --config webpack.build.js",
"build": "npm run build:lib && npm run build:umd && npm run build:umd:min",
"prepublish": "npm run clean && npm run test && npm run build"
},
"files": [
"dist",
"lib",
"src"
],
"repository": {
"type": "git",
"url": "git+https://github.com/theaqua/redux-logger.git"
},
"keywords": [
"redux",
"logger",
"redux-logger",
"redux",
"middleware"
],
"author": "Eugene Rodionov (https://github.com/theaqua)",
"license": "MIT",
"bugs": {
"url": "https://github.com/theaqua/redux-logger/issues"
},
"homepage": "https://github.com/theaqua/redux-logger#readme",
"devDependencies": {
"@dtrussia/eslint-config-dtrussia": "2.2.1",
"babel-cli": "6.3.13",
"babel-core": "6.3.13",
"babel-eslint": "6.0.4",
"babel-loader": "6.2.0",
"babel-plugin-add-module-exports": "0.1.1",
"babel-preset-es2015": "6.3.13",
"babel-preset-react": "6.3.13",
"babel-preset-stage-0": "6.3.13",
"eslint": "2.10.2",
"eslint-plugin-react": "5.1.1",
"rimraf": "2.4.4",
"webpack": "1.12.9"
},
"dependencies": {
"deep-diff": "0.3.4"
}
}
npm 的模塊管理
熟悉 npm 的常用命令,往往能夠使得你的工作事半功倍怎顾。首先我們來介紹最常用的 npm install
命令读慎,它是用來將依賴的模塊安裝到 node_modules
目錄中,依賴分為兩種:生產(chǎn)環(huán)境的依賴和開發(fā)環(huán)境的依賴槐雾,這個(gè)在前面一節(jié)已經(jīng)介紹過了夭委,對(duì)應(yīng)的命令分別如下所示:
npm install redux // 生產(chǎn)環(huán)境的依賴
npm install redux -dev // 開發(fā)環(huán)境的依賴
在安裝之前,npm 會(huì)先檢查 node_modules
目錄中是否已經(jīng)存在指定的模塊募强,如果存在株灸,則不會(huì)重新安裝,即使這個(gè)模塊已經(jīng)有新版本擎值。當(dāng)然慌烧,我們可以通過增加 -f
或者 --force
參數(shù)來強(qiáng)制重新安裝最新版本。上面的命令安裝完成后幅恋,我們可以在 node_modules
目錄中找到 redux 的包杏死,但這時(shí) package.json
文件內(nèi)容并沒有發(fā)生變化,為了在發(fā)布我們這個(gè)包給其他開發(fā)者使用時(shí)捆交,他們可以自動(dòng)安裝這些依賴淑翼,我們需要將依賴寫入 package.json
文件中,當(dāng)然你可以選擇手動(dòng)寫入品追,但更方便的方法是在 npm install
時(shí)增加 --save
參數(shù)玄括,如下所示:
npm install redux --save // 生產(chǎn)環(huán)境的依賴
npm install redux --save-dev // 開發(fā)環(huán)境的依賴
這時(shí) npm 會(huì)自動(dòng)幫我們寫入 package.json
文件,如下所示:
{
...
"dependencies": {
...
"redux": "^3.5.2"
},
"devDependencies": {
"eslint": "^2.11.1"
}
}
有了依賴的安裝肉瓦,當(dāng)然也有卸載的命令遭京,很簡(jiǎn)單就是 npm uninstall
,后面參數(shù)是需要卸載的包名泞莉,例如 npm uninstall redux
哪雕。
前面使用 React Native 提供的 react-native init AwesomeProject
命令生成的 Demo 工程已經(jīng)自動(dòng)幫我們生成了 package.json
文件,如果我們自己手動(dòng)建立一個(gè) React Native 的工程鲫趁,那么可以選擇從其他工程拷貝現(xiàn)成的 package.json
并進(jìn)行修改斯嚎,當(dāng)正確的做法是使用 npm init
命令來生成它。在 Terminal 中輸入 npm init
,npm 將會(huì)一步一步引導(dǎo)我們輸入一些關(guān)鍵的字段堡僻,最終生成的文件內(nèi)容如下所示糠惫,從中看到的字段幾乎是每個(gè)工程必備的:
{
"name": "asce1885",
"version": "1.0.0",
"description": "One Piece",
"main": "index.js",
"scripts": {
"test": "op"
},
"repository": {
"type": "git",
"url": "git+https://github.com/PaicHyperionDev/MobileDevWeekly.git"
},
"keywords": [
"mobile",
"dev"
],
"author": "asce1885",
"license": "MIT",
"bugs": {
"url": "https://github.com/PaicHyperionDev/MobileDevWeekly/issues"
},
"homepage": "https://github.com/PaicHyperionDev/MobileDevWeekly#readme"
}
當(dāng)某個(gè)第三方依賴庫需要發(fā)布新版本,我們項(xiàng)目也需要跟著升級(jí)時(shí)钉疫,可以通過 npm update
命令對(duì)指定的 Package 進(jìn)行升級(jí)硼讽,例如 npm update redux
。同時(shí)牲阁,我們可以通過執(zhí)行命令 npm outdated
來查詢當(dāng)前安裝的所有 npm 包中是否有存在新版本的固阁。
一般來說,掌握上面幾個(gè)命令城菊,對(duì)開發(fā) React Native 來說就已經(jīng)足夠了您炉,對(duì)于不熟悉的命令,我們可以通過 npm help
來查詢對(duì)應(yīng)命令的用法役电,例如輸入 npm help registry
赚爵,會(huì)得到如下結(jié)果:
![image_1akd8q4b8nr8124l1jli1q3sj4im.png-221.9kB](http://static.zybuluo.com/asce1885/yaev6klcai14b38s2ior0jfo/image_1akd8q4b8nr8124l1jli1q3sj4im.png)
npm scripts
上一節(jié)我們介紹了 npm 的模塊管理功能,事實(shí)上法瑟,npm 另外一個(gè)高頻使用的功能就是用來執(zhí)行腳本冀膝。我們?cè)?package.json
文件的 scripts
字段中定義的腳本可以通過 npm run
或者 npm run-script
執(zhí)行,例如在 React Native 工程中霎挟,我們可以定義如下腳本窝剖,分別用來創(chuàng)建,啟動(dòng) Android 模擬器酥夭,啟動(dòng) node 服務(wù)和打包等:
"scripts": {
"avd:create": "android create avd -t 1 -n MuchVote -d 9 -b x86_64 -s 1440x2560",
"avd:start": "emulator -avd MuchVote -gpu on -dpi-device 560 -scale ${SCALE:-0.25}",
"adb:reverse": "adb reverse tcp:8081 tcp:8081",
"android": "npm run adb:reverse && node node_modules/react-native/local-cli/cli.js run-android",
"start": "npm run adb:reverse && node_modules/react-native/packager/packager.sh",
}
定義完成之后赐纱,就可以在 React Native 目錄中像下面這樣執(zhí)行對(duì)應(yīng)的命令:
npm run adb:reverse
npm run android
...
為了方便腳本的執(zhí)行,npm 默認(rèn)定義了一些命令的快捷鍵熬北,例如 npm test
疙描,npm start
,npm stop
等等讶隐,也就是說執(zhí)行這些命令時(shí)起胰,我們省去了 run
的輸入。之所以定義這些快捷鍵巫延,除了可以節(jié)省執(zhí)行命令的時(shí)間效五,更重要的一點(diǎn)是這些命令的命名是通用的約定,很多持續(xù)構(gòu)建平臺(tái)例如 Travis 會(huì)默認(rèn)為 Node.js 工程添加 npm test
命令炉峰;同時(shí)畏妖,這些通用的命令定義也方便其他開發(fā)者使用你的包。
npm 為每一條命令都提供了 pre-
和 -post
這兩個(gè)鉤子疼阔,分別表示在命令執(zhí)行前和執(zhí)行后會(huì)執(zhí)行對(duì)應(yīng)的鉤子命令戒劫。例如下面的腳本适瓦,當(dāng)用戶執(zhí)行 npm run test
命令時(shí),事實(shí)上 npm 會(huì)先執(zhí)行 pretest
命令谱仪,然后才執(zhí)行 test
命令。
"scripts": {
"eslint": "eslint --rulesdir **",
"test": "mocha test/",
"pretest": "npm run eslint"
}
當(dāng)一個(gè)命令比較復(fù)雜時(shí)否彩,我們還可以將這個(gè)命令定義在一個(gè)單獨(dú)的 js
文件中疯攒,然后通過 node
來執(zhí)行,如下所示:
"scripts": {
"build": "node build.js"
}
本系列關(guān)于 npm 的介紹就到這里列荔,基本上對(duì)開發(fā) React Native 已經(jīng)足夠用了敬尺,如果你不滿足于這些基礎(chǔ)知識(shí),可以查閱拓展閱讀部分的文檔贴浙,進(jìn)一步學(xué)習(xí)砂吞。
拓展閱讀
《npm 官方文檔》[2]
《我為何放棄 Gulp 與 Grunt,轉(zhuǎn)投 npm scripts》上[3] 中[4] 下[5]
《Introduction to Using NPM as a Build Tool》[6]
《How to Use npm as a Build Tool》[7]
《package.json》[8]
《玩轉(zhuǎn) npm》[9]
《玩轉(zhuǎn) npm》[10]
《npm 模塊安裝機(jī)制簡(jiǎn)介》[11]
歡迎關(guān)注我的微信公眾號(hào)崎溃,專注與原創(chuàng)或者分享 Android蜻直,iOS,ReactNative袁串,Web 前端移動(dòng)開發(fā)領(lǐng)域高質(zhì)量文章概而,主要包括業(yè)界最新動(dòng)態(tài),前沿技術(shù)趨勢(shì)囱修,開源函數(shù)庫與工具等赎瑰。
-
http://www.infoq.com/cn/news/2016/02/gulp-grunt-npm-scripts-part1 ?
-
http://www.infoq.com/cn/news/2016/02/gulp-grunt-npm-scripts-part2 ?
-
http://www.infoq.com/cn/news/2016/02/gulp-grunt-npm-scripts-part3 ?
-
https://medium.com/@dabit3/introduction-to-using-npm-as-a-build-tool-b41076f488b0#.tylyovxdw ?
-
http://blog.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/ ?