1. 程式人生 > >前端學習 node 快速入門 系列 —— npm

前端學習 node 快速入門 系列 —— npm

>其他章節請看: > >[前端學習 node 快速入門 系列][1] ## npm ### npm 是什麼 npm 是 node 的**包管理器**,絕大多數 javascript 相關的包都放在 npm 上。 所謂**包**,就是別人提供出來供他人使用的專案。可以是簡單的幾行程式碼,可以是 jQuery 這種類庫,也可以是框架 express ,還可以是 webpack 這樣的工具。 npm 用於解決**前端共享**問題。 以前我們需要使用 jQuery、bootstrap 等其他庫,需要這麼做: 1. 進入 jQuery 和 bootstrap 等其他庫的官網 1. 將庫下載到本地 1. 本地引入庫 npm 的作者希望**簡化**這個過程,比如只需要執行一條命令 `npm install jquery`,就能將 jquery 下載到本地。 實現的思路大概是這樣: 1. npm 作者發郵件給 jQuery 和 bootstrap 的作者,讓他們把專案放到 npm 上 1. jQuery 和 bootstrap 的作者由於不認識發郵件的人,當然會拒絕 1. node 的作者缺少一個包管理器,而 npm 作者有一個包管理器,於是兩人抱團取暖,node 內建了 npm 1. 後來 node 火了,npm 也出名了,於是 jQuery 和 bootstrap 的作者主動把專案放到 npm 上 1. 現在基於 node 開發的環境,如果需要引入什麼包,只需要一個命令 在[初步認識 node][初步認識 node]一文中,我們已經成功安裝了 node,而 node 內建了 npm,現在我們就可以用 npm **下載**一個包體驗一下: ```javascript $ node --version // 檢視 node 是否已成功安裝 v12.18.1 $ npm --version // 檢視 npm 版本 6.14.5 $ npm install jquery // {1} npm WARN saveError ENOENT: no such file or directory, open 'D:\package.json' ... ... + [email protected] added 1 package from 1 contributor and audited 1 package in 1.692s found 0 vulnerabilities ``` 執行 `npm install jquery`(行{1})會將 jquery 下載到專案根目錄的 **node_modules** 資料夾中。 npm 另一個意思就是 [npm 網站][npm 網站],npm 的包就存在那裡。如果可以在該網站中搜索到相應的包名(PackageName),那我們就可以通過 `npm install PackageName` 下載。 輸入 `npm install hello-world` ,看看會發生什麼... ### package.json Node專案中 **package.json** 就是專案的核心。 執行 `npm init` 能建立一個 package.json 檔案。請看示例: ```javascript // 輸入 npm init 回車,會依次讓你輸入關於專案的配置資訊,這裡一路回車 $ npm init ... package name: (test2) version: (1.0.0) description: entry point: (index.js) test command: git repository: keywords: author: license: (ISC) About to write to D:\test2\package.json: { "name": "test2", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } Is this OK? (yes) yes ``` 輸入完 yes 後,會在專案根目錄下生成一個 package.json 的檔案。內容如下: ```javascript { "name": "test2", // 名稱 "version": "1.0.0", // 版本 "description": "", // 描述 "main": "index.js", // 入口檔案 "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } ``` 如果你打算髮布軟體包,package.json 中最重要的欄位是 name 和 version,因為它們是必填;如果你不打算髮布,name 和 version 則是可選的。 main 欄位是程式**主入口點**。如果我安裝了一個包(xx),然後執行 require(xx),將返回入口檔案的匯出模組。請看示例: ```javascript // 下載包 $ npm install underscore // 建立檔案 1.js let _ = require('underscore') console.log(_) // 執行 1.js - 輸出匯出模組 $ node 1 [Function: _] { VERSION: '1.12.0', toPath: [Function: toPath], iteratee: [Function: iteratee], templateSettings: { evaluate: /<%([\s\S]+?)%>/g, ... ... // 修改 underscore 的主入口檔案 node_modules\underscore\package.json { "main": "underscore.js", // 改為 "main": "underscore2.js", // {1} } // 建立 node_modules\underscore\underscore2.js,內容如下: exports.name = 'aaron' // 執行 - 匯出模組變成 { name: 'aaron' } $ node 1 { name: 'aaron' } // {2} ``` 通過修改 underscore 的主入口檔案(行{1}),最終 underscore 匯出的模組是 `{ name: 'aaron' }`(行{2}) 我們也可以通過 `npm init -y` 跳過嚮導,快速生成 package.json。 ### npm install 執行 `npm init -y` 快速生成 package.json 檔案後,再執行 `npm install jquery` 來安裝 jquery,會在 package.json 中增加 **dependencies** 欄位。內容如下: ```javascript { ... "license": "ISC", "dependencies": { "jquery": "^3.6.0" } } ``` dependencies 欄位聲明瞭此專案**依賴的包**。 *注*:網上有的文章說執行 `npm install jquery`,不會在 package.json 中增加 dependencies 項,可能以前的 npm 不會。筆者的 npm 是 6.14.5,參考的文件是 [npm-install V6][npm-install V6],裡面說 `npm install` 預設將軟體包儲存到 dependencies 中。 此外還可以控制儲存軟體包的**位置**和方式,請看示例: ```javascript // 不儲存在 dependencies $ npm install jquery --no-save // 儲存在 devDependencies $ npm i jquery --save-dev ``` 執行 `npm install` (不帶任何引數)將安裝 package.json 中列出的所有依賴包。請看示例: ```javascript { ... "license": "ISC", "dependencies": { "jquery": "^3.6.0" }, "devDependencies": { "underscore": "^1.12.0" } } ``` package.json 中列出了兩個依賴,執行 `npm install` 將會把 jquery 和 underscore 下載到專案根目錄的 node_modules 資料夾中。 當安裝包或刪除包,npm 都會生成或更新 **package-lock.json** 檔案。npm 5 以前沒有 package-lock.json 這個檔案。筆者的 npm 是 6.14.5,執行 `npm install jquery`,package.json 和 package-lock.json 的內容如下: ```javascript // package.json { "dependencies": { "jquery": "^3.6.0" // {1} } } // package-lock.json { "dependencies": { "jquery": { "version": "3.6.0", // {2} "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" } } } ``` package-lock.json 最重要的作用是**鎖定版本**。在 package-lock.json 中明確寫明 jquery 的版本是 3.6.0,而 package.json 中的是 ^3.6.0。 其次,package-lock.json 能提升下次執行 `npm install` 的速度。通常一個包會依賴其他很多包(jquery是特列),以 express 為例: ```javascript $ npm install express // package.json { "dependencies": { "express": "^4.17.1" } } // package-lock.json { // dependencies 中的都是 express 依賴的包 "dependencies": { "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", }, "array-flatten": { "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", }, "body-parser": { "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", }, ... "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "requires": { ... } } ... // express 依賴的包還有很多 } } ``` 執行 `npm install express` 花費 12s。因為需要先下載 express,解析 express 中的 package.json,下載裡面依賴的包,接著分析依賴包並下載,如此反覆執行,所以花費時間較長。而再次執行 `npm install`,只需找到 package-lock.json 檔案,無需迴圈下載、解析,而是直接從 resolved 指向的地址下載包即可。 ### npm uninstall 執行 `npm uninstall express`,會從 package.json 檔案、package-lock.json 檔案,以及 node_modules 資料夾,這三個方面刪除 express 相關的依賴包。 安裝(`npm install`)有儲存軟體包的位置和方式(--save、--save-dev),解除安裝(`npm uninstall`)時也有(--save、--save-dev)。請看示例。 ```javascript // 最初安裝了兩個包 { ... "license": "ISC", "dependencies": { "jquery": "^3.6.0" }, "devDependencies": { "underscore": "^1.12.0" } } // 解除安裝 jquery,dependencies 物件被刪除 $ npm uninstall jquery { ... "license": "ISC", "devDependencies": { "underscore": "^1.12.0" } } // 解除安裝 underscore,devDependencies 物件被刪除 $ npm uninstall underscore --save-dev { ... "license": "ISC" } ``` 執行 `npm uninstall jquery` 與 `npm uninstall jquery --save` 的效果相同(npm 以前的版本需要指定 --save) *注*:如果上面例子中執行 `npm uninstall jquery --save-dev`,效果與 `npm uninstall jquery` 類似,也能達到解除安裝的目的。建議不要這樣,如果要刪除 devDependencies 中的包,那就使用 `--save-dev`。 ### npm --help 通過 `npm --help` 可以檢視 npm 命令。請看示例: ```javascript $ npm --help Usa