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

彭加李發表於2021-03-10

其他章節請看:

前端學習 node 快速入門 系列

npm

npm 是什麼

npm 是 node 的包管理器,絕大多數 javascript 相關的包都放在 npm 上。

所謂,就是別人提供出來供他人使用的專案。可以是簡單的幾行程式碼,可以是 jQuery 這種類庫,也可以是框架 express ,還可以是 webpack 這樣的工具。

npm 用於解決前端共享問題。

以前我們需要使用 jQuery、bootstrap 等其他庫,需要這麼做:

  1. 進入 jQuery 和 bootstrap 等其他庫的官網
  2. 將庫下載到本地
  3. 本地引入庫

npm 的作者希望簡化這個過程,比如只需要執行一條命令 npm install jquery,就能將 jquery 下載到本地。

實現的思路大概是這樣:

  1. npm 作者發郵件給 jQuery 和 bootstrap 的作者,讓他們把專案放到 npm 上
  2. jQuery 和 bootstrap 的作者由於不認識發郵件的人,當然會拒絕
  3. node 的作者缺少一個包管理器,而 npm 作者有一個包管理器,於是兩人抱團取暖,node 內建了 npm
  4. 後來 node 火了,npm 也出名了,於是 jQuery 和 bootstrap 的作者主動把專案放到 npm 上
  5. 現在基於 node 開發的環境,如果需要引入什麼包,只需要一個命令

初步認識 node一文中,我們已經成功安裝了 node,而 node 內建了 npm,現在我們就可以用 npm 下載一個包體驗一下:

$ 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'
...
...
+ jquery@3.6.0
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 的包就存在那裡。如果可以在該網站中搜尋到相應的包名(PackageName),那我們就可以通過 npm install PackageName 下載。

輸入 npm install hello-world ,看看會發生什麼...

package.json

Node專案中 package.json 就是專案的核心。

執行 npm init 能建立一個 package.json 檔案。請看示例:

// 輸入 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 的檔案。內容如下:

{
  "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),將返回入口檔案的匯出模組。請看示例:

// 下載包
$ 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 欄位。內容如下:

{
  ...
  "license": "ISC",
  "dependencies": {
    "jquery": "^3.6.0"
  }
}

dependencies 欄位宣告瞭此專案依賴的包

:網上有的文章說執行 npm install jquery,不會在 package.json 中增加 dependencies 項,可能以前的 npm 不會。筆者的 npm 是 6.14.5,參考的文件是 npm-install V6,裡面說 npm install 預設將軟體包儲存到 dependencies 中。

此外還可以控制儲存軟體包的位置和方式,請看示例:

// 不儲存在 dependencies
$ npm install jquery --no-save 

// 儲存在 devDependencies
$ npm i jquery --save-dev

執行 npm install (不帶任何引數)將安裝 package.json 中列出的所有依賴包。請看示例:

{
  ...
  "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 的內容如下:

// 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 為例:

$ 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)。請看示例。

// 最初安裝了兩個包
{
  ...
  "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 jquerynpm uninstall jquery --save 的效果相同(npm 以前的版本需要指定 --save)

:如果上面例子中執行 npm uninstall jquery --save-dev,效果與 npm uninstall jquery 類似,也能達到解除安裝的目的。建議不要這樣,如果要刪除 devDependencies 中的包,那就使用 --save-dev

npm --help

通過 npm --help 可以檢視 npm 命令。請看示例:

$ npm --help

Usage: npm <command>

npm install        install all the dependencies in your project
npm install <foo>  add the <foo> dependency to your project
npm test           run this project's tests
npm run <foo>      run the script named <foo>
npm <command> -h   quick help on <command>
npm -l             display usage info for all commands
npm help <term>    search for help on <term> (in a browser)
npm help npm       more involved overview (in a browser)

All commands:

    access, adduser, audit, bin, bugs, cache, ci, completion,
    config, dedupe, deprecate, diff, dist-tag, docs, doctor,
    edit, exec, explain, explore, find-dupes, fund, get, help,
    hook, init, install, install-ci-test, install-test, link,
    ll, login, logout, ls, org, outdated, owner, pack, ping,
    prefix, profile, prune, publish, rebuild, repo, restart,
    root, run-script, search, set, set-script, shrinkwrap, star,
    stars, start, stop, team, test, token, uninstall, unpublish,
    unstar, update, version, view, whoami

如果需要檢視特定命令的幫助,可以使用 npm 命令 --help。例如:

$ npm init --help

npm init [--force|-f|--yes|-y|--scope]
npm init <@scope> (same as `npx <@scope>/create`)
npm init [<@scope>/]<name> (same as `npx [<@scope>/]create-<name>`)

aliases: create, innit

有快速建立 package.json 的引數 -y

$ npm install --help
npm install (with no args, in package dir)
npm install [<@scope>/]<pkg>
npm install [<@scope>/]<pkg>@<tag>
npm install [<@scope>/]<pkg>@<version>
npm install [<@scope>/]<pkg>@<version range>
npm install <alias>@npm:<name>
npm install <folder>
npm install <tarball file>
npm install <tarball url>
npm install <git:// url>
npm install <github username>/<github project>

aliases: i, in, ins, inst, insta, instal, isnt, isnta, isntal, add
common options: [--save-prod|--save-dev|--save-optional|--save-peer] [--save-exact] [--no-save]

可以使用 install 的別名,例如要安裝 jquery:npm i jquery

npm 映象

由於 npm 的伺服器是國外的,下載包有時會很慢,所以我們有時會配置映象。比如配置淘寶映象,使用起來也很方便,用 cnpm 代替 npm。例如要通過映象下載: cnpm install jquery

其他章節請看:

前端學習 node 快速入門 系列

相關文章