1. 程式人生 > >npm包的釋出和管理

npm包的釋出和管理

npm包管理

npm其實是Node.js的包管理工具(node package manager)。

為啥我們需要一個包管理工具呢?因為我們在Node.js上開發時,會用到很多別人寫的JavaScript程式碼。如果我們要使用別人寫的某個包,每次都根據名稱搜尋一下官方網站,下載程式碼,解壓,再使用,非常繁瑣。於是一個集中管理的工具應運而生:大家都把自己開發的模組打包後放到npm官網上,如果要使用,直接通過npm安裝就可以直接用,不用管程式碼存在哪,應該從哪下載。

更重要的是,如果我們要使用模組A,而模組A又依賴於模組B,模組B又依賴於模組C和模組D,npm可以根據依賴關係,把所有依賴的包都下載下來並管理起來。否則,靠我們自己手動管理,肯定既麻煩又容易出錯。

npm的基礎使用

npm的指令其實常用的並不多官方文件;列出來如下面:

  • access
    Set access level on published packages
  • adduser

    ``` Add a registry user account ```
  • audit

    ``` Run a security audit ```
  • bin

    ``` Display npm bin folder ```
  • bugs

    ``` Bugs for a package in a web browser maybe ```
  • build

    ``` Build a package ```
  • bundle

    ``` REMOVED *已刪除* ```
  • cache

    ``` Manipulates packages cache ```
  • ci

    ``` Install a project with a clean slate ```
  • completion

    ``` Tab Completion for npm ```
  • config

    ``` Manage the npm configuration files ```
  • dedupe

    ``` Reduce duplication ```
  • deprecate

    ``` Deprecate a version of a package ```
  • dist-tag

    ``` Modify package distribution tags ```
  • docs

    ``` Docs for a package in a web browser maybe ```
  • doctor

    ``` Check your environments ```
  • edit

    ``` Edit an installed package ```
  • explore

    ``` Browse an installed package ```
  • help-search

    ``` Search npm help documentation ```
  • help

    ``` Get help on npm ```
  • hook

    ``` Manage registry hooks ```
  • init

    ``` create a package.json file ```
  • install-ci-test

    ``` Install a project with a clean slate and run tests ```
  • install-test

    ``` Install package(s) and run tests ```
  • install

    ``` Install a package ```
  • link

    ``` Symlink a package folder ```
  • logout

    ``` Log out of the registry ```
  • ls

    ``` List installed packages ```
  • npm

    ``` javascript package manager ```
  • outdated

    ``` Check for outdated packages ```
  • owner

    ``` Manage package owners ```
  • pack

    ``` Create a tarball from a package ```
  • ping

    ``` Ping npm registry ```
  • prefix

    ``` Display prefix ```
  • profile

    ``` Change settings on your registry profile ```
  • prune

    ``` Remove extraneous packages ```
  • publish

    ``` Publish a package ```
  • rebuild

    ``` Rebuild a package ```
  • repo

    ``` Open package repository page in the browser ```
  • restart

    ``` Restart a package ```
  • root

    ``` Display npm root ```
  • run-script

    ``` Run arbitrary package scripts ```
  • search

    ``` Search for packages ```
  • shrinkwrap

    ``` Lock down dependency versions for publication ```
  • star

    ``` Mark your favorite packages ```
  • stars

    ``` View packages marked as favorites ```
  • start

    ``` Start a package ```
  • stop

    ``` Stop a package ```
  • team

    ``` Manage organization teams and team memberships ```
  • test

    ``` Test a package ```
  • token

    ``` Manage your authentication tokens ```
  • uninstall

    ``` Remove a package ```
  • unpublish

    ``` Remove a package from the registry ```
  • update

    ``` Update a package ```
  • version

    ``` Bump a package version ```
  • view

    ``` View registry info ```
  • whoami

    ``` Display npm username ```

init

初始化建立package.json

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>)

search

搜尋檢視遠端npm相關資源包資訊

npm search [-l|--long] [--json] [--parseable] [--no-description] [search terms ...]
aliases: s, se, find

install

可以是說是install是最為常見的命令官方介紹

npm install (with no args, in package dir)
npm install [<@scope>/]<name>
npm install [<@scope>/]<name>@<tag>
npm install [<@scope>/]<name>@<version>
npm install [<@scope>/]<name>@<version range>
npm install <git-host>:<git-user>/<repo-name>
npm install <git repo url>
npm install <tarball file>
npm install <tarball url>
npm install <folder>

alias: npm i
common options: [-P|--save-prod|-D|--save-dev|-O|--save-optional] [-E|--save-exact] [-B|--save-bundle] [--no-save] [--dry-run]

In global mode (ie, with -g or --global appended to the command), it installs the current package context (ie, the current working directory) as a global package. The -g or --global argument will cause npm to install the package globally rather than locally.

The -f or --force argument will force npm to fetch remote resources even if a local copy exists on disk.

上面的還介紹已經很詳細了,所以這裡只是講一下npm install packageName [|--save |--save-prod|--save-dev]的區別;

  • npm install babel
    npm5以前,會把X包安裝到node_modules目錄中,不會修改package.json的dependencies欄位,之後執行npm install命令時,不會自動安裝X
  • npm install babel
    npm5以後,會把X包安裝到node_modules目錄中,會修改package.json的dependencies欄位,之後執行npm install命令時,會自動安裝X, 線上環境時會被安裝
  • npm install babel -P
    -P, --save-prod: Package will appear in your dependencies. This is the default unless -D or -O are present. Package will appear in your dependencies, With the --production flag (or when the NODE_ENV environment variable is set to production), npm will install modules listed in dependencies.
  • npm install babel -D
    Package will appear in your devDependencies,With the --production flag (or when the NODE_ENV environment variable is set to production), npm will not install modules listed in devDependencies. 會把X包安裝到node_modules目錄中,會在package.json的devDependencies屬性下新增X,之後執行npm install命令時,會自動安裝X到node_modules目錄中,之後執行npm install –production或者註明NODE_ENV變數值為production時,不會自動安裝X到node_modules目錄中

update

升級某個資源包或者全部資源包到某一個版本或者匹配的最新版本。

npm update [-g] [<pkg>...]
aliases: up, upgrade

uninstall

移除某個資源包

npm uninstall [<@scope>/]<pkg>[@<version>]... [-S|--save|-D|--save-dev|-O|--save-optional|--no-save]
aliases: remove, rm, r, un, unlink

npm包建立、編寫、測試、維護

Node出現之前,JavaScript是缺少包結構的。CommonJS致力於改變這種現狀,於是定義了包的結構規範。而NPM的出現則是為了在CommonJS規範的基礎上,實現解決包的安裝解除安裝,依賴管理,版本管理等問題。require的查詢機制明瞭之後,我們來看一下包的細節。
一個符合CommonJS規範的包應該是如下這種結構:

  • 一個package.json檔案應該存在於包頂級目錄下
  • 二進位制檔案應該包含在bin目錄下(可選)
  • JavaScript程式碼入庫是index.js,其他包含在lib目錄下
  • 文件應該在doc目錄下(可選)
  • 單元測試應該在test目錄下(可選)

初始化包

  1. 建立包的根目錄

    ``` mkdir testpackage ```
  2. 初始化

    ``` npm init // 需要進行一些基本配置 ```

編寫

  1. 建立入口檔案

    ``` touch index.js ```
  2. 編寫程式碼

    ``` const updateQueryString = function(url, key, value) { let urlParts = url.split('#'), hash = '', uri = urlParts.shift(), re = new RegExp(`([?&])${key}=.*?(&|$)`, 'i'), separator = uri.indexOf('?') !== -1 ? '&' : '?', encodeKey = encodeURIComponent(key), encodeValue = encodeURIComponent(value); urlParts.length > 0 && (hash = `#${urlParts.join('#')}`); if (uri.match(re)) { return uri.replace(re, `$1${encodeKey}=${encodeValue}$2`) + hash; } else { return `${uri}${separator}${encodeKey}=${encodeValue}${hash}`; } }; // 最後的匯出部分 module.exports = { updateQueryString }; ```
  3. 測試

    1. 建立包的根目錄

      ``` npm i mocha -D // 安裝測試庫 npm i chai -D // 安裝斷言庫 mkdir test cd test touch index.test.js ```
    2. 編寫測試程式碼

      ``` const utils = require('./../index.js'); const expect = require('chai').expect; let { updateQueryString } = utils; describe('updateQueryString函式的測試', function() { it('https://test.com/path?test=11 修改test引數為22 應該等於 https://test.com/path?test=22', function() { expect(updateQueryString('https://test.com/path?test=11', 'test', 22)).to.be.equal('https://test.com/path?test=22'); }); }); ```
    3. 執行測試

      ``` cd .. ./node_modules/mocha/bin/mocha ```

npm包的釋出

  1. 註冊賬號npm官網
  2. 終端執行 npm login,輸入使用者名稱和密碼 、郵箱
  3. npm publish 釋出

Organization包

我們經常可以看到@angular@ionic他們的包, 都可以以@開頭,那麼我們的可不可以,原來angular、ionic都屬於一個組織(Organization)只有新建立一個Organization組織之後,才能建立@testorg/testpackname這樣的包!!!

那麼我們就可以去官網上建立我們的Organization,命名之後,官方步驟

  1. 初始化

    ``` npm init --scope=<your_org_name> ```
    npm init foo -> npx create-foo
    npm init @usr/foo -> npx @usr/create-foo
    npm init @usr -> npx @usr/create
  2. 修改package.json裡面的name欄位為@your_org_name/<pkg_name>
  3. 釋出

    ``` npm publish --access public // 公開包釋出 ```

npm包支援esmodule

使用babel來進行一些現代JavaScript的支援,

  1. 建立配置檔案

    ``` touch .babelrc ```
  2. 安裝先關包
  3. 配置babel

    ``` { "presets": [ [ "@babel/preset-env", { "targets": { "browsers": [ "last 2 versions", "safari >= 7" ], "chrome": 52, "node": "6.10.0" }, "modules": "commonjs", "useBuiltIns": "usage" } ] ], "plugins": [ "@babel/plugin-syntax-dynamic-import", "@babel/plugin-syntax-import-meta", "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-json-strings", [ "@babel/plugin-proposal-decorators", { "legacy": true } ], "@babel/plugin-proposal-function-sent", "@babel/plugin-proposal-export-namespace-from", "@babel/plugin-proposal-numeric-separator", "@babel/plugin-proposal-throw-expressions", "@babel/plugin-proposal-export-default-from", "@babel/plugin-proposal-logical-assignment-operators", "@babel/plugin-proposal-optional-chaining", [ "@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" } ], "@babel/plugin-proposal-nullish-coalescing-operator", "@babel/plugin-proposal-do-expressions" ] } ```
  4. 編譯

    ``` ./node_modules/.bin/babel src -d lib ```

最後的測試程式碼地址test-demo-npm