Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

npm学习笔记

5
Dec
2014

npm学习笔记

By Alex
/ in JavaScript
/ tags Node.js, 学习笔记
0 Comments
基础知识
简介

npm是一个JavaScript软件包的管理工具,让代码共享、重用更加简单。 

术语列表
术语 说明
package 所谓包,就是一个文件或者目录,它由一个名为 package.json 的元数据文件来描述。包和模块有交集但互不包含
module

是指任何可以通过Node.js的 require() 来加载的文件或者目录,例如:

  1. 一个包含了package.json的目录,package.json中包含main字段
  2. 一个包含了index.js的目录
  3. 一个JavaScript文件

大部分的npm包都属于模块,因为一般情况下,npm包都是供Node.js程序通过require()来加载的

几乎所有的npm包,都包含多个模块,这是因为其中JS文件可以通过require()来加载

在Node.js程序中,模块还可能指通过require()调用得到的变量:

JavaScript
1
2
// req是模块
var req = require('request')

之所以node_modules目录如此命名,是因为它是用来寻找模块(而不是包) 的,对于文件node_modules/request.js,可以通过上面的require()代码加载

入门
安装Node.js和npm

可以到Node.js官网下载Node.js运行时,完毕后解压到某个目录,设置好环境变量。然后,执行:

Shell
1
npm install npm@latest -g

安装最新版本npm。

解决权限问题

尝试安装全局模块时,可能会遇到 EACCES 错误,这意味着你没有权限对npm用来存放全局模块/命令的目录进行写操作。此时你可以设置默认全局模块目录的权限,或者转移全局模块存放目录。

修改权限

执行下面的命令获取npm安装位置的前缀: npm config get prefix ,如果输出的位置是/user/local,你可以选择修改文件权限:

Shell
1
2
# 获取几个目录的所有权
sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
转移目录

如果你不希望改变文件所有权,可以转移npm全局模块安装目录:

Shell
1
2
3
4
# 创建一个作为npm全局目录
mkdir ~/.npm-global
# 设置npm前缀
npm config set prefix '~/.npm-global'

然后,修改你的环境变量,添加PATH: export PATH=~/.npm-global/bin:$PATH  

现在你可以通过npm安装软件包,不需要sudo前缀了。

安装模块

安装npm包有两种方式:全局安装、本地安传。根据需要,选择其中的一种:

  1. 如果你希望在自己正在开发的工程中依赖(例如通过Node.js的require)一个包,使用本地安装,本地安装是npm的默认行为
  2. 如果你希望将npm作为某种命令行工具,例如cordova,则应该进行全局安装
本地安装

执行下面的命令进行本地安装:

Shell
1
npm install package_name

上述命令会在当前目录下,创建一个 node_modules  子目录,然后下载软件包到此目录中。

被安装的软件包的版本,按如下规则确定:

  1. 如果本地目录中存在package.json,则根据其中声明的semver规则来确定安装的版本,例如:
    JavaScript
    1
    2
    3
    4
    {
      "name": "package_name",
      "version": "1.0.0"  // 该字段支持semver规范
    } 
  2. 如果没有package.json文件,则安装最新版本

一旦安装,你就可以在工程中使用这些软件包了:

index.js
JavaScript
1
var pkg = require('package_name');
全局安装

添加-g选项,则自动执行全局安装:

Shell
1
2
3
4
5
6
7
8
9
10
# 安装
npm install -g package_name
# 更新
npm update -g package_name
# 更新所有全局包
npm update -g
# 查找过期的软件包
npm outdated -g --depth=0
# 移除
npm uninstall -g package_name
使用package.json

要为你自己编写的包初始化包描述符,可以在包的根目录下执行:

Shell
1
2
3
4
5
6
# 你可以设置字段默认值:
npm set init.author.email "i@gmem.cc"
npm set init.author.name "i"
npm set init.license "MIT"
# 指定 --yes 则仅仅提问author字段
npm init --yes

生成的package.json内容如下:

package.json
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
    "name": "包名称",
    "version": "版本号,默认1.0.0",
    "main": "入口点,默认index.js",
    // 脚本文件列表
    "scripts": {
        // 测试脚本
        "test": "echo \"Error: no test specified\" && exit 1",
        // 构建脚本
        "build": "babel src -d lib"
    },
    // 关键字,用于搜索
    "keywords": [],
    "author": "包的作者",
    "license": "许可证类型,默认ISC",
    "repository": {
        "type": "仓库类型,例如git",
        "url": "仓库URL,例如https://github.com/author/name"
    },
    "bugs": {
        "url": "https://github.com/author/name/issues"
    },
    "homepage": "https://github.com/author/name"
}
指定依赖

你可以在包描述符中指定当前包的依赖项:

  1. dependencies,在产品环境下,依赖的包
  2. devDependencies,在开发/测试时,依赖的包

示例:

JavaScript
1
2
3
4
5
6
7
8
9
10
{
    "name": "my_package",
    "version": "1.0.0",
    "dependencies": {
        "my_dep": "^1.0.0"
    },
    "devDependencies": {
        "my_test_framework": "^3.1.0"
    }
}

你可以在本地安装软件包的同时,将其自动添加为当前工程的依赖: 

Shell
1
2
3
4
# 安装包,并将其作为当前工程的dependencies
npm install  --save      package_name
# 安装包,并将其作为当前工程的devDependencies
npm install  --save-dev  package_name
更新依赖

在当前工程根目录下执行下面的命令,即可更新依赖到最新的、匹配semver的版本:

Shell
1
npm update
删除依赖
Shell
1
2
3
4
5
# 从本地目录删除一个依赖
npm uninstall package_name
# 删除的同时,从dependencies或者devDependencies移除:
npm uninstall --save     package_name
npm uninstall --save-dev package_name 
发布模块

只要是具有合法包描述符(package.json)的目录,都可以发布到npm官方仓库中:

Shell
1
2
3
4
5
6
7
# 如果没有npm仓库的账号,需要先创建账号
npm adduser
# 执行登录,并把身份信息保存在客户端
npm login
 
# 发布当前包
npm publish

注意,任何文件都作为包的内容被发布,除非在.gitignore或者.npmignore中声明排除模式。

每当你修改了包的版本号,都可以再次进行发布。

Semver

所谓语义版本控制(Semantic versioning),是一种被广泛的使用的版本号规则 ,用来向软件包的用户传递软件包的更新情况。

包发布者

版本号必须符合 1.0.0 这样的模式,即三段版本号:

  1. 补丁版本:当进行缺陷修复、其它小的改动时,递增最低位
  2. 小版本:当引入了新的特性,但是不会影响既有的特性时,递增中间位
  3. 大版本:当破坏了向后兼容性时,递增第一位
包使用者

作为包的使用者,你可以在package.json中声明,那样的版本更新是可以被接受的。假设当前依赖版本是1.0.4,那么:

  1. 允许补丁版本: 1.0 、 1.0.x 或者 ~1.0.4 
  2. 允许小版本: 1 、 1.x 或者 ^1.0.4 
  3. 允许大版本: * 或者 x 
使用标签

标签(Tag)是对Semver的补充,用于组织包的不同版本。

标签可以作为版本号的别名,例如某个项目可能具有多个开发流,并以不同的Tag区分它们——stable、beta、dev、canary等。

添加标签

执行下面的命令,可以为你的包的特定版本添加一个标签:

Shell
1
npm dist-tag add <pkg>@<version> [<tag>]
发布时指定标签

在发布包到npm仓库时,可以指定标签: 

Shell
1
npm publish --tag beta

如果不指定标签,publish子命令自动添加 latest 标签。

安装时指定标签

在安装包时,也可以指定标签: npm install <pkg>@<tag> ,如果不指定,默认使用latest标签。

使用Scoped包

对于npm模块来说,范围(Scope)类似于名字空间。当指定一个包名时,以@开头,则它是一个Scoped包。Scope由@与/之间的字符串限定: @scope/project-name ,每个npm仓库用户,都具有自己的Scope: @username/project-name 。

创建Scoped包

只需要在包描述符中修改包名称,即可创建一个Scoped包:

JavaScript
1
2
3
{
    "name": "@username/project-name"
}

使用npm init生成package.json时,你可以指定 npm init --scope=username  。

发布Scoped包

默认情况下,Scoped包是私有的,你需要付费帐户。如果想将其发布为公共包,可以:

Shell
1
npm publish --access=public
依赖Scoped包

在package.json中:

JavaScript
1
2
3
4
5
{
    "dependencies": {
        "@username/project-name": "^1.0.0"
    }
}

在命令行中:

Shell
1
npm install @username/project-name --save

在require调用中:

JavaScript
1
var projectName = require("@username/project-name");  
npm-scripts

npm允许在package.json的scripts字段,以字典的形式声明多个脚本。这些脚本会在包生命周期的不同阶段自动调用:

脚本键(Stage) 何时调用
prepublish

在发布包到仓库之前调用
在进行本地 npm install,不带任何参数时调用

如果你希望在包被使用之前,执行不依赖于目标(安装包的)平台的动作,可以使用该Stage。示例场景包括:

  1. 编译CoffeeScript为JavaScript
  2. 创建JavaScript文件的最小化版本
  3. 下载包需要使用的远程资源

使用该Stage的好处是,目标动作可以在单个地方、一次性的被执行,因此可以降低复杂性和不确定性。使用该Stage还意味着:

  1. 你可以将coffee-script声明为devDependency
  2. 不需要在包中包含JS压缩器(minifiers)
  3. 你不需要在目标系统上调用curl或者wget来下载东西
publish,postpublish 在发布包到仓库之后调用
preinstall 在包被安装之前调用
install, postinstall 在包被安装之后调用
preuninstall, uninstall 在包被删除之前调用
postuninstall 在包被删除之后调用
preversion, version 在Bump包的版本之前调用
postversion 在Bump包的版本之后调用
pretest, test, posttest 由npm test命令调用
prestop, stop, poststop 由npm stop命令调用
prestart, start, poststart 由npm start命令调用
prerestart, restart, postrestart 由 npm restart调用。如果不指定该脚本,npm restart会先调用stop再调用start

此外,不在上述列表的任何Stage,都可以通过 npm run-script <pkg> <stage> 命令来调用。 pre<stage> 、 post<stage> 脚本则会在该命令之前、之后被调用。

注意:

  1. 这些脚本被传递给Shell执行,如果退出码不是0,则会中断当前npm命令
  2. 这些脚本不一定必须是Node.js程序或者JavaScript程序,任意可执行文件都是支持的
  3. -- 可以用来中止从命令行读取npm选项,这样,后续命令行参数被传递给脚本

运行环境

Stage脚本在一个特定的环境中运行,npm的配置、当前进程的状态会影响到该环境

PATH

如果你依赖于定义了Stage脚本的模块,可以:

JavaScript
1
2
3
4
5
6
7
8
9
{
    "name": "foo",
    "dependencies": {
        "bar": "0.1.x"
    },
    "scripts": {
        "start": "bar ./test"
    }
}

由于依赖了bar,因此bar包提供的可执行文件bar被自动添加到node_modules/.bin目录,因此可以直接调用。

package.json变量

package.json的属性被映射到 npm_package_  前缀的环境变量,Stage脚本可以使用npm_package_name来获得当前包的name。

package.json的config属性被映射到 npm_package_config_ 前缀的环境变量

配置参数

npm配置参数被映射到 npm_config_ 前缀的环境变量,Stage脚本可以访问这些变量。例如:

JavaScript
1
2
3
4
5
6
7
8
9
{
    "name": "foo",
    "config": {
        "port": "8080"
    },
    "scripts": {
        "start": "node server.js"
    }
}

声明了一个port变量,Stage脚本可以这样访问:

server.js
JavaScript
1
http.createServer(...).listen(process.env.npm_package_config_port)

而你可以改变port的当前值:

Shell
1
npm config set foo:port 80 
钩子脚本

如果任意包的某个Stage都需要执行同一脚本,可以使用钩子。

在 node_modules/.hooks/{stage} 目录下放置一个可执行文件,它会在所有包的stage阶段自动被执行。

最佳实践
  1. 除非你真的愿意,不要让Stage脚本以非0退出。例外是uninstall脚本。非0会导致npm操作失败,可能导致回滚
  2. 对于npm本身就能够为你做的事情,不要用Stage脚本完成
  3. 根据环境变量来决定安装文件到什么位置,例如npm_config_binroot为/home/user/bin时,你不应该把文件安装到/usr/local/bin
  4. 不要为你的脚本添加sudo前缀
npm命令
子命令 说明
access

对公共包进行访问控制:

Shell
1
2
3
4
5
6
7
8
9
10
# 设置某个包为公共可见或者受限的
npm access public [<package>]
npm access restricted [<package>]
 
# 授予特定团队/用户以权限
npm access grant <read-only|read-write> <scope:team> [<package>]
npm access revoke <scope:team> [<package>]
 
# 显示一个用户或者团队能够访问的包的列表
npm access ls-packages [<user>|<scope>|<scope:team>]
adduser

为仓库添加一个用户:

Shell
1
npm adduser [--registry=url] [--scope=@orgname] [--always-auth]
bin

打印npm安装可执行文件的目标目录:

Shell
1
npm bin [-g|--global]
bugs

猜测包的缺陷跟踪URL,并用浏览器打开它:

Shell
1
npm bugs [<pkgname>]
build

构建一个包: npm build [<package-folder>] 

该命令是一个底层(Plumbing)的命令,通常你不应该直接调用。它被link或者install子命令调用

如果你需要调用build脚本,可以:

Shell
1
npm run-script build
cache

操控包缓存:

Shell
1
2
3
4
5
6
7
8
9
10
11
# 将指定的包添加到本地缓存
npm cache add <tarball file>
npm cache add <folder>
npm cache add <tarball url>
npm cache add <name>@<version>
 
# 显示缓存中的数据
npm cache ls [<path>]
 
# 清空缓存
npm cache clean [<path>]
config

管理npm的配置文件:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
# 设置配置参数
npm config set <key> <value> [-g|--global]
# 读取配置参数
npm config get <key>
# 删除配置参数
npm config delete <key>
# 列出所有配置参数
npm config list
# 用默认编辑器编辑配置文件,-g则编辑全局配置文件
npm config edit  [-g|--global]
# 别名
npm get <key>
npm set <key> <value> [-g|--global]

npm可以从命令行参数、环境变量、npmrc文件读取配置参数,某些情况下还可以从package.json中读取 

dedupe

减少重复依赖:

Shell
1
2
npm dedupe
npm ddp

该子命令会搜索本地包的依赖树,并尝试像树的根部移动依赖,以便在总体上简化其结构。例如:

1
2
3
4
5
a
+-- b <-- depends on c@1.0.x
|   `-- c@1.0.3
`-- d <-- depends on c@~1.0.9
    `-- c@1.0.10

在执行该子命令后,会被简化为:

1
2
3
4
a
+-- b
+-- d
`-- c@1.0.10
deprecate  

更新包在仓库中的条目,标记某个版本为废弃的:

Shell
1
2
3
npm deprecate <pkg>[@<version>] <message>
# 示例
npm deprecate my-thing@"< 0.2.3" "critical bug fixed in v0.2.3"
dist-tag

修改包的分发标签(distribution tags):

Shell
1
2
3
4
5
6
# 为指定版本的包设置标签
npm dist-tag add <pkg>@<version> [<tag>]
# 删除一个标签
npm dist-tag rm <pkg> <tag>
# 列出所有标签
npm dist-tag ls [<pkg>]
docs

尝试猜测包的文档地址,并在浏览器中打开:

Shell
1
2
3
4
npm docs [<pkgname> [<pkgname> ...]]
npm docs .
npm home [<pkgname> [<pkgname> ...]]
npm home .
edit 编辑一个已经安装的包
explore 浏览一个已经安装的包
help 显示帮助信息: npm help <term> [<terms..>]
help-search 搜索npm帮助文档: npm help-search <text> 
init 交互式的初始化package.json文件: npm init [-f|--force|-y|--yes] 
install

安装一个包:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 子命令别名
npm i ...
 
# 安装依赖到本地的node_modules目录
# 在全局模式下,该命令把当前目录安装为全局包,默认的,所有在package.json中声明的依赖都被安装
# 如果指定--production则不安装devDependencies中的依赖
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 <tarball file>
npm install <tarball url>
# 安装位于本地文件系统中的包
npm install <folder>

该子命令用于安装一个包,以及所有该包的依赖。如果包提供了shrinkwrap文件则依赖的安装由shrinkwrap驱动 

下面是三个常用的、互斥的选项:
-S, --save  把安装的包加入到dependencies
-D, --save-dev  把安装的包加入到devDependencies
-O, --save-optional  把安装的包加入到optionalDependencies

当使用上面三个选项之一时,可以指定:
-E, --save-exact  在package.json的dependencies/devDependencies/optionalDependencies中限定使用精确的依赖版本

install-test 连续执行install、test子命令
link

为一个包的目录创建符号链接:

Shell
1
2
3
4
5
# 子命令别名
npm ln ...
 
npm link (in package dir)
npm link [<@scope>/]<pkg>[@<version>]

从全局安装目录中定位到目标包,并在当前目录中创建该包的符号链接

logout 从仓库退出登录: npm logout [--registry=<url>] [--scope=<@scope>] 
ls

列出已经安装的包: npm ls [[<@scope>/]<pkg> ...] 

可以显示当前工程的依赖树

outdated

检查已经过期的包: npm outdated [[<@scope>/]<pkg> ...] 

输出列如下:
wanted   最高的满足package.json需求的包版本
latest   仓库中被标记为latest的包版本
location  在依赖树的何处定位到此包

注意:该子命令默认使用depth为0,因此只有直接依赖的包过期了才会被检测到

owner

管理包的所有者信息:

Shell
1
2
3
npm owner add <user> [<@scope>/]<pkg>
npm owner rm <user> [<@scope>/]<pkg>
npm owner ls [<@scope>/]<pkg>
pack

为一个包创建压缩文件:

Shell
1
npm pack [[<@scope>/]<pkg>...]

压缩文件会被拷贝到当前工作目录,命名为: <name>-<version>.tgz 

ping Ping指定的仓库并验证身份信息: npm ping [--registry <registry>] 
prefix

打印本地前缀到标准输出——最接近工作目录的、包含package.json的祖代目录

如果指定全局模式,则打印全局安装目录前缀

prune

移除没有使用的依赖: npm prune [[<@scope>/]<pkg>...] [--production] 

该子命令移除没有在父包依赖列表里出现的那些包

如果指定--production,则devDependencies中指定的依赖被移除

publish

发布一个包到仓库:

Shell
1
npm publish [<tarball>|<folder>] [--tag <tag>] [--access <public|restricted>]
rebuild

重新构建一个包: npm rebuild [[<@scope>/<name>]...]  

当你安装了新版本的Node.js,并且需要重新编译所有的C++加载项时,可以使用该命令

 repo 在浏览器中打开包的仓库页面: npm repo [<pkg>] 
restart

重启启动一个包: npm restart [-- <args>]  

该命令会依次执行stop、restart、start脚本,以及相关的pre-*、post-*脚本。具体顺序如下:
prerestart ⇨ prestop ⇨ stop ⇨ poststop ⇨ restart ⇨ prestart ⇨ start ⇨ poststart ⇨ postrestart

root

打印node_modules目录所在位置到标准输出: npm root [-g] 

run-script

运行任意的包脚本:

Shell
1
2
3
4
# 子命令别名
npm run ...
# 格式:
npm run-script <command> [-- <args>...]

这里的command是定义在package.json的scripts属性中的一个键

search

在仓库中搜索指定的包:

Shell
1
2
3
4
5
# 子命令别名
npm s ...
npm se ...
# 格式:
npm search [-l|--long] [search terms ...]
shrinkwrap

锁定依赖的版本: npm shrinkwrap 

该子命令锁定包的依赖的版本,当包被安装时,其依赖的精确版本会被安装

默认情况下,npm install会递归的安装目标包package.json中指定的依赖项,选择满足依赖semver的最新版本。但是有些时候需要避免此行为

该子命令会生成一个 npm-shrinkwrap.json 文件,其中记录依赖的精确版本

star
unstar

标记你最喜欢的包:

Shell
1
2
npm star [<pkg>...]
npm unstar [<pkg>...]
stars 列出被标记为喜欢的包: npm stars [<user>] 
stop 执行包的stop脚本: npm stop [-- <args>] 
team

管理团队和团队成员:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建或者删除团队
npm team create <scope:team>
npm team destroy <scope:team>
 
# 添加或者删除成员
npm team add <scope:team> <user>
npm team rm <scope:team> <user>
 
# 列出组织或者团队的成语
npm team ls <scope>|<scope:team>
 
# 编辑团队
npm team edit <scope:team>
test

测试一个包:

Shell
1
2
npm test [-- <args>]
npm tst [-- <args>]

该子命令执行package.json中的test脚本

uninstall

删除一个包:

Shell
1
npm uninstall [<@scope>/]<pkg>[@<version>]... [-S|--save|-D|--save-dev|-O|--save-optional]
unpublish

从仓库中删除一个包: npm unpublish [<@scope>/]<pkg>[@<version>] 

通常不应该删除已经发布的包版本,因为其它用户可能依赖它。可以使用deprecate命令代替

update

更新一个包: npm update [-g] [<pkg>...] 

该命令会更新所有指定的包到尽可能新(semver允许的)的版本

该命令也会安装缺失的软件包,如果指定--dev则devDependencies中的依赖也被处理

whoami

显示当前用户名: npm whoami [--registry <registry>] 

该命令显示username配置参数

package.json

包的根目录下的package.json文件,是包的描述符,它必须标准化的JSON格式。

属性列表
属性 说明
name

包的名称,该字段与version一起,唯一的标识一个包。该字段必须:

  1. 不大于214字符
  2. 不能以点号、下划线开头
  3. 新创建的包,包名不得包含大写字母
  4. 不得包含URL不安全字符
version 包的版本号
description 包的描述信息,该信息显示在npm search的结果中
keywords 包的搜索关键字
homepage 此包的项目主页
bugs

此包的缺陷跟踪地址、电子邮件地址,格式:

JavaScript
1
2
3
4
{
    "url": "https://github.com/owner/project/issues",
    "email": "project@hostname.com"
}
license 包的授权类型
author 包的作者
contributors 包的贡献者列表
files

工程中需要包含在包中的目录、文件列表

如果不指定此字段,可以使用.npmignore、.gitignore设置排除规则

文件package.json、README、CHANGELOG、LICENSE、LICENCE总是包含

文件.git、.svn等总是排除

main 作为程序主入口点的模块的ID(相对于包根目录),当require('pkg')时,该模块的exports对象作为返回值
bin

可以指定一个或者多个需要安装到PATH下的可执行文件,示例:

JavaScript
1
2
3
4
5
6
{
    "bin": {
        // 键为可执行文件名称,值为相对于包根目录的JS文件路径
        "myapp": "./cli.js"
    }
}
man 指定一个文件、或者多个文件的数组,这些文件会被放置到合适的地方,供man程序查看
directories CommonJS包允许通过使用一个directories对象来指定包的详细结构
repository

设置此包的CVS仓库:

JavaScript
1
2
3
4
5
6
7
8
9
"repository": {
    "type": "git",
    "url": "https://github.com/npm/npm.git"
}
 
"repository": {
    "type": "svn",
    "url": "https://v8.googlecode.com/svn/trunk/"
} 
scripts

一个字典,指定在包的生命周期的不同阶段需要被执行的脚本

如果包的根目录下存在一个server.js文件,则默认值为:

JavaScript
1
"scripts": {"start": "node server.js"}

如果包的根目录下存在一个binding.gyp文件,则默认值为:

JavaScript
1
"scripts":{"preinstall": "node-gyp rebuild"}
config 设置包脚本中可以访问的参数
dependencies

指定包的依赖项。这些依赖项必须随着当前包一起安装

一个字典,键为依赖的包的名称,值为包的版本:
version    精确版本
>version  最小版本(不包含)
>=version 最小版本
<version 最大版本(不包含)
<=version 最大版本
~version  允许BUG修复版本变动
^version  允许兼容版本变动
1.2.x  允许1.2下任意BUG修复版本
*  允许所有版本,""等价于"*"
version1 - version2  在两个版本之间(包含)
range1 || range2   匹配range1或者range2
tag  匹配标记了tag的版本

devDependencies 指定包的开发依赖项。当在一个包的根目录下执行npm link、npm install时,这些依赖会被一并安装
bundledDependencies 指定当发布当前包时,需要捆绑到其中的包的名称
optionalDependencies 指定可选依赖,这些依赖会被安装,但是安装失败的情况下,整体安装不会因而失败
peerDependencies

当前包的一个依赖,此依赖也会安装该包的用户所依赖。假设当前包是grunt插件,则它依赖于grunt,而此插件的用户也必然依赖于grunt。使用该配置,可以声明插件所要求的宿主包的版本

如果当前包依赖于request 2.x的同时依赖于some-other-library,而some-other-library依赖于request 1.x,则当前包安装后的依赖树如下:

1
2
3
├── request@2.12.0
└─┬ some-other-library@1.2.3
  └── request@1.9.9

感谢模块化机制,通常情况下这不会造成问题, some-other-library使用自己的1.9.9版本,对当前包不会造成冲突。但是在使用插件时,会出现问题,这与插件的运行方式有关

从npm 3.x开始peerDependencies不会自动安装,出现如下警告:

1
2
3
npm WARN peerDependencies The peer dependency mocha@>=1.x.x included from grunt-mocha-istanbul will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
engines

指定兼容的Node.js引擎、npm版本:

JavaScript
1
2
3
4
"engines": {
    "node": ">=0.10.3 <0.12",
    "npm": "~1.0.20"
}
os

指定支持的操作系统,示例:

JavaScript
1
2
"os" : [ "darwin", "linux" ]
"os" : [ "!win32" ] 
cpu

指定支持的CPU架构,示例:

JavaScript
1
2
"cpu" : [ "x64", "ia32" ]
"cpu" : [ "!arm", "!mips" ]
preferGlobal 如果当前包仅仅是为了提供命令行程序,可以设置为true。这样,用户在尝试本地安装时会得到一个警告
private 如果设置为true,则npm拒绝发布此包
publishConfig 指定一系列的nmp配置项,这些配置项在发布包的时候使用
npm配置
配置来源

npm的配置信息,按优先级从高到低,有以下来源:

  1. 命令行标记,例如 --name value 设置配置参数name为value, -- 表示停止继续读取命令行标记,最后一个标记 --flag 如果不提供值则值默认为true
  2. 环境变量,以 npm_config_ 开头的环境变量作为配置参数解析,例如 npm_config_name=value ,这类配置参数的名字,大小写不敏感
  3. npmrc文件,包括:
    1. 工程根目录下的.npmrc文件
    2. 用户的~/.npmrc文件
    3. 全局的$PREFIX/etc/npmrc文件
    4. npm配置的/path/to/npm/npmrc文件
配置项列表
配置项 说明
access 默认restricted,当发布scoped包时,默认访问限制为restricted,如果要改为允许公共访问,设置为public
always-auth 默认false,是否在访问仓库(Regisry)时总是要求身份验证
bin-links 默认true,是否为包中的可执行文件创建符号链接
cache npm缓存位置,默认Windows下为%AppData%\npm-cache,Linux下为~/.npm
cache-max

默认Infinity,再次访问仓库检查之前,缓存有效的最大时间

注意:除非调用 npm cache clean 否则缓存不会消失,缓存仅仅影响GET请求

cache-min 默认10,在此秒数之前,绝不重新访问仓库检查缓存有效性
depth 默认Infinity,执行npm ls、npm cache ls、npm outdated等命令时递归低最大深度
description 默认true,是否显示 npm search结果的描述字段
dry-run 默认false,仅仅查看命令执行结果,不改变现有文件系统
editor npm edit 或者 npm config edit使用的文本编辑器
engine-strict 默认false,如果设置为true则npm拒绝安装声明和当前Node.js版本不兼容的包
force

默认false,有多种效果:

  1. 生命周期脚本执行失败,不影响构建进程
  2. 不使用缓存
fetch-retries 默认2,尝试从仓库获取同一包的次数
fetch-retry-mintimeout 尝试从仓库获取包,超时的最小、最大时间,默认10000、60000
fetch-retry-maxtimeout
git 指定Git命令行所在路径
global

是否在全局模式下运行,全局模式下,包被安装到prefix目录而不是当前目录:

  1. 包被安装到{prefix}/lib/node_modules
  2. 可执行文件被链接到{prefix}/bin
  3. Man手册被连接到{prefix}/share/man
globalconfig 全局配置的位置,默认{prefix}/etc/npmrc
group 默认为当前进程的GID,执行包脚本时的使用的GID
heading 默认npm,打印调试信息时的前缀信息
https-proxy 指定对外执行HTTPS请求时使用的代理服务器
if-present 默认false,如果设置为true,则npm run-script调用不会以错误码退出,只要执行的脚本不是在package.json的scripts段定义
ignore-scripts 默认false,如果设置为true,则npm不会运行package.json中声明的脚本
init-module 默认~/.npm-init.js,指定npm init命令需要加载的模块
init-author-name 为npm init命令提供默认值
init-author-email
init-author-url
init-license
init-version
json 默认false,命令是否输出JSON格式的数据
key 访问仓库时使用的客户端Key
link 默认false,如果设置为true,当对应的全局包存在时,本地包仅仅是一个链接
local-address 连接到仓库时,使用哪个本地IP地址
loglevel

默认warn,设置日志级别:"silent", "error", "warn", "http", "info", "verbose", "silly"

日志被输出到当前目录的npm-debug.log文件中

long 让npm ls、npm search命令输出扩展的信息
npat 默认false,是否在安装时执行测试
onload-script 当npm模块加载时,require()的Node.js模块
optional 尝试在optionalDependencies对象中安装包,如果失败,整体的安装过程不会中断
prefix

设置全局安装目录的前缀

如果在命令行参数中指定,用于强制非全局命令在指定的目录中运行

production

默认false,设置为true则运行在产品模式:

  1. 不带任何参数运行npm install时devDependencies不会在顶级安装
  2. 为生命周期脚本设置NODE_ENV="production"
progress 默认true,如果设置为true,执行时间密集型操作时显示进度条
proxy 指定对外执行HTTP请求时使用的代理服务器
registry 使用的仓库的BaseUrl,默认https://registry.npmjs.org/
rollback 默认true,是否移除失败的安装
save 默认false,将安装的包作为 package.json中的依赖项(dependencies)
save-bundle 默认false,如果一个包利用--save, --save-dev, --save-optional来安装时,是否也将其添加到bundleDependencies列表
save-dev 默认false,将安装的包作为 package.json中的开发依赖项(devDependencies)
save-exact 默认false,如果一个包利用--save, --save-dev, --save-optional来安装时,是否在package.json中配置为精确的依赖版本而不是使用Semver
save-optional 默认false,将安装的包作为 package.json中的可选依赖项(optionalDependencies)
save-prefix

默认^,在保存到package.json的某个依赖列表时,被依赖包的版本使用的Semver前缀

scope 对Scoped包进行操作时,使用的scope
searchopts 空格分隔的选项,这些选项总是传递给搜索命令
searchsort 搜索结果排序方式,默认name,可用值"name", "date","description", "keywords",这些值都可以前缀 - 表示逆序排列
tag 默认值latest,当安装包时不指定版本时,默认使用的版本
user 运行包脚本时设置UID为
userconfig 用户配置位置,默认~/.npmrc
umask 创建文件/目录时使用的文件模式
命令行捷径

很多配置项具有对应低命令行捷径:

配置项 捷径
--version -v
--help -h, -?
--usage -H
--loglevel silent -s, --silent
--loglevel warn -q, --quiet
--loglevel info -d
--loglevel verbose -dd, --verbose
--loglevel silly -ddd
--global -g
--prefix -C
--long -l
--message -m
--parseable -p, --porcelain
--registry -reg
--force -f
--description -desc
--save -D
--save-optional -O
--save-bundle -B
--save-exact -E
--yes  -y
--yes false -n
常见问题
~/.npm目录是什么

该目录作为包缓存,可以避免反复下载同一个包。

如何修改npm的全局模块安装目录?

Windows下,修改文件 %NODEJS_HOME%/node_modules/npm/npmrc 中的prefix为期望的安装目录。完毕后修改环境变量PATH,确保其中包含了新设置的全局安装目录。Linux下类似。

← 汪静好
Pi's Lullaby →

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • 基于Eclipse的Node.js开发
  • ExtJS 4常用组件之表单
  • ExtJS 4元素与组件查询
  • 浅析ExtJS 4布局组件
  • SockJS知识集锦

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • Bazel学习笔记 37 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2