1、npm、pnpm、cnpm、npx、yarn
一文了解 pnpm、yarn、cnpm、npx、npm:https://cloud.tencent.com/developer/article/2320612
先说结论:推荐使用 pnpm
- 开源社区的宠儿
- 国内的 Vue / Vite 团队很多都切换到pnpm
npm 简介
官网:https://www.npmjs.com/
教程:https://www.runoob.com/nodejs/nodejs-npm.html
常用命令 npm CLI:https://docs.npmjs.com/cli/v9npm 官方文档:https://docs.npmjs.com/cli/v6/commands/npm-install/
npm 全称 Node Package Manager,是 node.js 的模块依赖管理工具。npm 之于 Node.js ,就像 pip 之于 Python, gem 之于 Ruby, pear 之于 PHP 。
npm 是随同 Node.js 一起安装的包管理工具,它很方便让 JavaScript 开发者下载、安装、上传以及管理已经安装的包,能解决 Node.js 代码部署上的很多问题,常见的场景有以下几种:
- 允许用户从 npm 服务器下载别人编写的第三方包到本地使用。
- 允许用户从 npm 服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到 npm 服务器供别人使用。
npm 的背后,是基于 couchdb 的一个数据库,详细记录了每个包的信息,包括作者、版本、依赖、授权信息等。它的一个很重要的作用就是:将开发者从繁琐的包管理工作(版本、依赖等)中解放出来,更加专注于功能的开发。
npx 简介
npm 从5.25.2 版开始,增加了 npx 命令,npx 的作用:
- npm 只能管理包的依赖,npx 则可以快捷的运用包中的命令行工具和其他可执行文件,让项目内部安装的模块用起来更方便。
- 当执行 npx <command> 相关命令的时候,npx 会先本地找(可以是项目中的也可以是本机的)寻找这个 command。
如果找到:就用本地的版本执行;
如果没找到:意味着尚未安装该软件包,npx将安装其最新版本,然后执行它;
使用完之后就会完全清除,不会在本机或项目留下任何东西
这样就不会污染本机、永远使用最新版本的 dependency
如果 npm 版本 <= 5.25.2,需要手动安装:npm install -g npx
npx 举例常见功能场景,每个案例都有一种常见的用处
场景 1
- npm 是安装第三方包的,但是安装之后,如何快捷的使用这些包?比如,项目内部安装了测试工具 webpack,非全局安装:npm i webpack -D
- 如果要执行 webpack 的命令,要么直接运行下面的命令,要么只能在项目脚本的 package.json 中的 scripts 字段里面按下面这样配置一个新的命令:$ ./node_modules/.bin/webpack -v
- 类似这样的用法就很不方便,有时候一些一次性调试,这个使用可以使用
npx
来做这件事,结果是一样的:$ npx webpack -v
场景 2
- 使用
npx
可以避免全局安装模块,比如:create-react-app
这个模块是全局安装,npx
可以运行它,而且不进行全局安装:npx create-react-app my-react-app - 上面命令运行时,npx 将 create-react-app 下载到一个临时目录,使用以后再删除。所以以后再次执行上面的命令,会重新下载 create-react-app 提供使用后再移除。
- 下载全局模块时,npx 允许指定版本:npx webpack@4.44.1 ./src/index.js -o ./dist/main.js
指定使用 v4.44.1 版本的 webpack 进行打包操作。
场景 3
- 注意:只要 npx 后面的模块无法在本地发现,就会下载同名模块。比如:本地没有安装 webpack-dev-server 模块,下面的命令会自动下载该模块,在当前目录启动一个 Webpack dev 服务:npx webpack-dev-server
- 如果想让 npx 强制使用本地模块,不下载远程模块,可以使用 --no-install 参数,如果本地不存在该模块,就会报错:npx --no-install webpack-dev-server
- 如果本地存在同名的模块,但是还是想使用远程的新版本模块,可以使用 --ignore-existing 参数。比如:本地已经全局安装了 create-react-app,但还是想使用远程模块:npx --ignore-existing create-react-app my-react-app
场景 4
- 利用
npx
指定node
版本运行脚本:npx node@14.15.0 -v 命令会使用 v14.15.0 版本的 node 执行脚本。原理是从 npm 下载这个版本的 node,使用后再删掉。在某些场景下,这个方法用来切换node
版本,要比nvm
那样的版本管理器方便一些。
cnpm 简介
使用 npm 安装包时,需要去 npm 仓库获取,而 npm 仓库在国外,很不稳定,有时获取会失败。淘宝搭建了一个国内npm服务器,会定时拉取国外npm仓库内容,把国外的搬运到国内。这是一个完整 npmjs.org 镜像,可以用此代替官方版本(只读),同步频率目前为 10分钟一次,以保证尽量与官方服务同步。
- 查看当前 npm 仓库地址命令:npm config get registry
- npm 默认仓库地址:http://registry.npmjs.org
- 淘宝镜像:http://npm.taobao.org 和 http://registry.npm.taobao.org 已在 2022.06.30 号正式下线和停止 DNS 解析。新域名为 npmmirror.com
修改域名
http://npm.taobao.org => http://npmmirror.com
http://registry.npm.taobao.org => http://registry.npmmirror.com
使用 淘宝源
npm 使用 淘宝镜像
- 使用 npm install 默认是从国外服务器下载安装,如果不想使用 cnpm,可以临时使用淘宝源。
命令:npm install 模块名 --registry=http://registry.npmmirror.com
示例:安装express:npm --registry=http://registry.npmmirror.com install express - 永久使用淘宝源:npm config set registry http://registry.npmmirror.com
查看是否更改成功:npm config get registry
以后安装时,依然用 npm 命令,但是实际是从淘宝国内服务器下载的。
也可以手动修改文件配置永久源。打开.npmrc 文件(C:\Program Files\nodejs\node_modules\npm\npmrc,没有的话可以使用 git 命令行建一个( touch .npmrc),用cmd命令建会报错)增加 registry=http://registry.npmmirror.com 即可。如果需要恢复成原来的官方地址只需要执行如下命令:npm config set registry https://registry.npmjs.org
安装 cnpm
- cnpm 是阿里开发的命令行工具,可以替换 npm:npm install -g cnpm --registry=http://registry.npmmirror.com 以后安装直接采用 cnpm 替代 npm。例如 npm 命令为:npm install uniq --save,cnpm命 令为:cnpm install uniq --save
检查是否安装成功:cnpm -v 安装成功后,后续用npm还是使用cnpm安装都可以。
示例:cnpm install express
yarn 简介
官网:https://www.npmjs.com/package/yarn
- 快速:Yarn缓存了它下载的每个包,所以它再也不需要下载同一个包了。它还几乎同时执行所有操作,以最大限度地提高资源利用率。这意味着安装速度更快。
- 可靠:使用详细但简洁的锁定文件格式和确定性的安装操作算法,Yarn能够保证在一个系统上运行的任何安装在另一个系统上将完全相同。
- 安全:在执行代码之前,Yarn使用校验和来验证每个安装包的完整性。
安装:npm install --global yarn
查看版本:yarn --versionyarn 是用 yarn add 代替 npm install
yarn remove 代替 npm uninstall
使用方法
使用方法:https://classic.yarnpkg.com/en/docs/usage
安装依赖模块
yarn add [package]
yarn add [package]@[version]
yarn add [package]@[tag]
删除依赖模块:yarn remove [package]
更新依赖模块
yarn upgrade [package]
yarn upgrade [package]@[version]
yarn upgrade [package]@[tag]
配置源。yarn默认的源地址:https://registry.yarnpkg.com ,如果下载太慢,可以修改源
查看镜像源:yarn config get registry
绑定镜像源:yarn config set registry https://registry.npmmirror.com
删除镜像源(注意这里是 delete):yarn config delete registry
pnpm 简介
官网:https://pnpm.io/zh/
Docs:https://pnpm.io/zh/motivation
安装:https://pnpm.io/zh/installation
pnpm 全称 performant npm,意思为 高性能的 npm。pnpm 由 npm/yarn 衍生而来,解决了 npm/yarn 内部潜在的 bug,极大的优化了性能,扩展了使用场景。被誉为 最先进的包管理工具。
使用 npm 时依赖每次被不同的项目使用,都会重复安装一次。 使用 pnpm 时依赖会被存储在内容可寻址的存储中。
所以 使用 pnpm 时:
- 如果你用到了某依赖项的不同版本,pnpm 只会将不同版本间有差异的文件添加到仓库。例如,如果某个包有100个文件,而它的新版本只改变了其中1个文件。那么
pnpm update
时只会向存储中心额外添加1个新文件,而不会因为仅仅一个文件的改变复制整新版本包的内容。 - 所有文件都会存储在硬盘上的某一位置。当软件包被被安装时,包里的文件会硬链接到这一位置,而不会占用额外的磁盘空间。这允许你跨项目地共享同一版本的依赖。
因此,相对 npm 优势
- 包安装速度极快;
- 磁盘空间利用非常高效。
pnpm 分三个阶段执行安装:
- 依赖解析。 仓库中没有的依赖都被识别并获取到仓库。
- 目录结构计算。
node_modules
目录结构是根据依赖计算出来的。 - 链接依赖项。 所有以前安装过的依赖项都会直接从仓库中获取并链接到
node_modules
。
使用 npm 或 Yarn Classic 安装依赖项时,所有的包都被提升到模块目录的根目录。 这样就导致了一个问题,源码可以直接访问和修改依赖,而不是作为只读的项目依赖。默认情况下 pnpm 使用符号链接将项目的直接依赖项添加到模块目录的根目录中。
安装 pnpm
官网 安装文档:https://www.pnpm.cn/installation
- Windows 使用 PowerShell:iwr https://get.pnpm.io/install.ps1 -useb | iex
安装时容易挂,因为需要去github下载包,github国内访问很不稳定,推荐 npm 安装方式。
使用 npm 安装:npm install -g pnpm - linux 安装:
curl -fsSL https://get.pnpm.io/install.sh | sh -
wget -qO- https://get.pnpm.io/install.sh | sh - - 使用 npm 安装,提供了两个 pnpm CLI 包, pnpm 和 @pnpm/exe。pnpm 是 pnpm 的普通版本,需要 Node.js 运行。安装:npm install -g pnpm 或者 npm install -g @pnpm/exe
@pnpm/exe 与 Node.js 一起打包成可执行文件,因此它可以在没有安装 Node.js 的系统上使用。
pnpm 常用命令
CLI命令:https://pnpm.io/zh/cli/add
pnpm add 安装软件包及其依赖的任何软件包。默认情况下,任何新软件包都安装为生产依赖项。
pnpm add sax # 保存到 dependencies
pnpm add -D sax # 保存到 devDependencies
pnpm add -O sax # 保存到 optionalDependencies
pnpm add -g sax # 安装包到全局
pnpm add sax@next #从 next 标签下安装
pnpm add sax@3.0.0 #安装指定版本 3.0.0
pnpm install 用于安装项目所有依赖,别名是小写字母 i
npm 命令 | pnpm 等价命令 |
---|---|
npm install | pnpm install 安装全部依赖 |
npm install 包名 | pnpm add (-D) 包名 安装指定包 |
npm uninstall 包名 | pnpm remove 包名 移除指定包 |
npm run 脚本 | pnpm 脚本 运行脚本 |
升级版本:pnpm add -g pnpm to update
pnpm update 根据指定的范围更新软件包的最新版本。不带参数时将更新所有依赖关系。
pnpm up # 遵循 package.json 指定的范围更新所有的依赖项
pnpm up --latest #更新所有依赖项,此操作会忽略 package.json 指定的范围
pnpm up foo@2 # 将 foo 更新到 v2 上的最新版本
pnpm up "@babel/*" #更新 @babel 范围内的所有依赖项
pnpm remove 别名是 rm, uninstall, un
从 node_modules 和项目的 package.json 中删除相关 packages。
pnpm list 以树形结构输出所有的已安装package的版本及其依赖。如果位置参数是 name-pattern@version-range 标识符,会将输出限制为仅为这样命名的包。例如,pnpm list "babel-*" "eslint-*" semver@5。
pnpm config list # 管理配置文件
pnpm config get registry # 查看当前镜像源
pnpm config set registry https://registry.npmmirror.com # 设置全局镜像源
npm install --registry https://registry.npmmirror.com # 设置项目临时镜像源
pnpm 基本详细使用教程(安装、卸载、使用、可能遇到的问题及解决办法):https://blog.csdn.net/m0_56416743/article/details/136122153
配置PNPM全局安装路径
# 允许设置全局安装包的 bin 文件的目标目录。
pnpm config set global-bin-dir "E:\pnpm-store"
# 包元数据缓存的位置。
pnpm config set cache-dir "E:\pnpm-store\pnpm-cache"
# pnpm 创建的当前仅由更新检查器使用的 pnpm-state.json 文件的目录。
pnpm config set state-dir "E:\pnpm-store\pnpm-state"
# 指定储存全局依赖的目录。
pnpm config set global-dir "E:\pnpm-store\global"
# 所有包被保存在磁盘上的位置。
#(可选,以下这条命令可以选择不执行也是OK的)
pnpm config set store-dir "E:\pnpm-store\pnpm-store"
以上命令中文件夹的路径可以自行切换,根据个人喜好来设置。
2、使用 npm
npm 快速入门
npm 中文文档:https://www.npmrc.cn/
1. npm 是什么?
2. npm 安装和更新
3. npm 防止权限错误
4. npm package.json 文件
5. npm 安装包
6. npm 更新包
7. npm 卸载包
8. npm 创建 Node.js 模块
9. npm 发布和更新包
10. npm 使用语义化版本
11. npm 使用 Dist-tags 标记包
12. npm 包和模块的了解
npm 命令
npm 命令行:https://www.npmrc.cn/commands.html
Configuring npm
Using npm
npm 安装、升级
安装 node 的时候 npm 会一起安装,但 node 附带的 npm 可能不是最新版本,用下面的命令更新到最新版本。
- window 系统升级 nodejs,只能到 nodejs 官网下载 window 安装包来覆盖之前的 nodejs。
- linux 系统升级 nodejs。首先使用 npm 全局安装一个管理 node 版本的管理模板n,就是n,不用怀疑。n 的 github 地址:https://github.com/tj/n
安装命令:npm i -g n 或者 npm i -g n --force
升级 node 版本,管理板块n的命令有很多
n 10.0.0 # "n 版本号" 升级到指定的版本
n latest # 安装最新的版本
n --stable # 安装最近的稳定版本
执行 node -v 查看版本
n 命令 帮助:n help
$ n help
Usage: n [options] [COMMAND] [args]
Commands:
n Display downloaded node versions and install selection
n latest Install the latest node release (downloading if necessary)
n lts Install the latest LTS node release (downloading if necessary)
n <version> Install node <version> (downloading if necessary)
n run <version> [args ...] Execute downloaded node <version> with [args ...]
n which <version> Output path for downloaded node <version>
n exec <vers> <cmd> [args...] Execute command with modified PATH, so downloaded node <version> and npm first
n rm <version ...> Remove the given downloaded version(s)
n prune Remove all downloaded versions except the installed version
n --latest Output the latest node version available
n --lts Output the latest LTS node version available
n ls Output downloaded versions
n ls-remote [version] Output matching versions available for download
n uninstall Remove the installed node and npm
Options:
-V, --version Output version of n
-h, --help Display help information
-p, --preserve Preserve npm and npx during install of node (requires rsync)
-q, --quiet Disable curl output (if available)
-d, --download Download only
-a, --arch Override system architecture
--all ls-remote displays all matches instead of last 20
--insecure Turn off certificate checking for https requests (may be needed from behind a proxy server)
--use-xz/--no-use-xz Override automatic detection of xz support and enable/disable use of xz compressed node downloads.
Aliases:
which: bin
run: use, as
ls: list
lsr: ls-remote
rm: -
lts: stable
latest: current
Versions:
Numeric version numbers can be complete or incomplete, with an optional leading 'v'.
Versions can also be specified by label, or codename,
and other downloadable releases by <remote-folder>/<version>
4.9.1, 8, v6.1 Numeric versions
lts Newest Long Term Support official release
latest, current Newest official release
auto Read version from file: .n-node-version, .node-version, .nvmrc, or package.json
boron, carbon Codenames for release streams
lts_latest node support aliases
and nightly, chakracore-release/latest, rc/10 et al
npm 常用命令
sudo npm install npm@latest -g # Linux 命令
npm install npm -g # Window 系统命令,也就是使用npm安装自己,因为 npm 本身与 Node 的其他模块没有区别。
npm help # 查看 npm 命令列表
npm -l # 查看各个命令的简单用法
npm -v # 查看 npm 的版本
npm config list -l # 查看 npm 的配置npm version # 查看 npm 和 node 的版本
npm list --depth=0 [-g] # 查看[全局]安装的包
npm root [-g] # 查看[全局的]包的安装路径
npm install 安装到指定目录时,需要设置目录。示例:npm config set prefix "f:\node" ,然后再执行:npm install 包名
npm install 到指定目录
默认情况下,在哪个文件夹下运行 npm,npm 就在当前目录创建一个文件夹 node_modules,然后将要安装的程序安装到文件夹 node_modules 里面。 这时候其他路径项目无法引用到该目录下的模块。如果需要自主配置的话
- 1. 在目标目录下建立 "node_global" 及 "node_cache" 两个文件夹。
- 2. 在 cmd 中输入
npm config set prefix "F:\14npm\node_global" // 设置 npm 安装程序时的默认位置
npm config set cache "F:\14npm\node_cache" // 设置 npm 安装程序时的缓存位置
但是这时候还是无法 require 这些模块,需要在环境变量中进行设置!!!!! - 3. 在环境变量中添加 模块保存路径的变量 NODE_PATH(告诉系统 用户下载的全局模块在此处)。新建 NODE_PATH 值为 F:\14npm\node_global\node_modules
- 4. 在 PATH 变量里面,添加 nodejs 路径 ;C:\Program Files\nodejs;
-
5. 最后安装程序命令:$ npm install cheerio -g 需要加上 -g,不加 -g 关键字仍会安装在你运行 npm 的文件夹下
npm init 初始化 package.json 文件
node 项目中都会有一个 package.json 文件,用来保存安装包的信息。npm init 就是用来初始化生成一个新的 package.json 文件。它会向用户提问一系列问题,如果只使用默认配置,一路回车就可以了。如果使用了 -f(代表force)、-y(代表yes),则跳过提问阶段,直接生成一个新的 package.json 文件。
用法: npm init [-f|--force|-y|--yes]
示例:npm init -y指定使用 npm init 时,生成的 package.json 文件的字段默认值。
$ npm config set init.author.name $name
$ npm config set init.author.email $email
package.json 和 package-lock.json 区别
package.json 是在运行 npm init 时生成的,主要记录项目依赖,有以下结构
- name:项目名,也就是在使用npm init 初始化时取的名字,但是如果使用的是npm init -y 快速初始化的话,那这里的名字就是默认存放这个文件的文件名;
- version:版本号;
- private:希不希望授权别人以任何形式使用私有包或未发布的;
- scripts-serve:是vue的项目启动简写配置;
- scripts-build:是vue的打包操作简写配置;
- dependencies:指定了项目运行时所依赖的模块;
- devDependencies:指定项目开发时所需要的模块,也就是在项目开发时才用得上,一旦项目打包上线了,就将移除这里的第三方模块;
package-lock.json 是在运行 npm install 时生成的
- package-lock.json 用于记录当前状态下项目中实际安装的各个 package 的版本号、模块下载地址、及这个模块又依赖了哪些依赖。
为什么有了package.json,还需要 package-lock.json 文件呢?
当项目中已有 package-lock.json 文件,在安装项目依赖时,将以该文件为主进行解析安装指定版本依赖包,而不是使用 package.json 来解析和安装模块。
因为 package 只是指定的版本不够具体,而 package-lock 为每个模块及其每个依赖项指定了版本,位置和完整性哈希,所以它每次创建的安装都是相同的。
无论你使用什么设备,或者将来安装它都无关紧要,每次都应该给你相同的结果。
npm help 查看命令帮助
查看某条命令的详细帮助 。基础语法:npm help <term> [<terms..>]
例如:输入 npm help install,系统在默认的浏览器或者默认的编辑器中打开本地 nodejs 安装包的文件 /nodejs/node_modules/npm/html/doc/cli/npm-install.html
npm root 查看包的安装路径
输出 node_modules 的路径:$ npm root [-g]
npm config 配置相关
npm config set proxy=http://xxx
npm config set <key> <value> [-g|--global]
npm config set prefix my_dir # 将指定的目录作为模块的全局安装目录
npm config set registry="http://r.cnpmjs.org" # 设置 镜像
npm install -g cnpm --registry=https://registry.npm.taobao.org # 临时使用淘宝镜像
npm config get <key>
npm config delete <key>
npm config list
npm config edit
npm get <key>
npm set <key> <value> [-g|--global]
npm cache 管理模块的缓存
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>]
最常用就是清除 npm 本地缓存:npm cache clean
npm start 启动模块
基础语法:npm start [-- <args>]
该命令写在 package.json 文件 scripts 的 start 字段中,可以自定义命令来配置一个服务器环境和安装一系列的必要程序,如
"scripts": {
"start": "gulp -ws" }
此时在 cmd 中输入 npm start 命令相当于执行 gulpfile.js 文件自定义的 watch 和 server 命令。如果 package.json 文件没有设置 start,则将直接启动 node server.js
npm stop 停止模块
基础语法:npm stop [-- <args>]
npm restart 重新启动模块
基础语法:npm restart [-- <args>]
npm test 测试模块
npm test [-- <args>]
npm tst [-- <args>]
该命令写在 package.json 文件 scripts 的 test 字段中,可以自定义该命令来执行一些操作,如
"scripts": {
"test": "gulp release" },
此时在 cmd 中输入 npm test 命令相当于执行 gulpfile.js 文件自定义的 release 命令。
npm version 查看模块版本
查看模块的版本:npm version
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]
npm [-v | --version] to print npm version
npm view <pkg> version to view a package's published version
npm ls to inspect current package/dependency versions
npm view 查看模块的注册信息
基础语法
npm view [<@scope>/]<name>[@<version>] [<field>[.<subfield>]...]
aliases: info, show, v
npm view gulp dependencies 查看模块 gulp 的依赖关系
npm view gulp repository.url 查看模块 gulp 的源文件地址
npm view npm contributors 查看模块 npm 的贡献者,包含邮箱地址
npm adduser 用户登录
基础语法:npm adduser [--registry=url] [--scope=@orgname] [--always-auth]
发布模板到 npm 社区前需要先登录,然后再进入发布的操作
npm publish 发布模块
基础语法
npm publish [<tarball>|<folder>] [--tag <tag>] [--access <public|restricted>]
Publishes '.' if no argument supplied Sets tag 'latest' if no --tag specified
npm access 在发布的包上设置访问级别
基础语法
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>]
npm access ls-collaborators [<package> [<user>]]
npm access edit [<package>]
npm set 用来设置环境变量
npm set
用来设置环境变量
$ npm set init-author-name 'Your name'
$ npm set init-author-email 'Your email'
$ npm set init-author-url 'http://yourdomain.com'
$ npm set init-license 'MIT'
上面命令等于为 npm init
设置了默认值,以后执行 npm init
的时候,package.json 的作者姓名、邮件、主页、许可证字段就会自动写入预设的值。这些信息会存放在用户主目录的 ~/.npmrc文件,使得用户不用每个项目都输入。如果某个项目有不同的设置,可以针对该项目运行 npm config
。
$ npm set save-exact true
上面命令设置加入模块时,package.json
将记录模块的确切版本,而不是一个可选的版本范围。
npm info 查看模块信息
npm info
命令可以查看每个模块的具体信息。比如,查看 underscore 模块的信息。
$ npm info underscore
{ name: 'underscore',
description: 'JavaScript\'s functional programming helper library.',
'dist-tags': { latest: '1.5.2', stable: '1.5.2' },
repository:
{ type: 'git',
url: 'git://github.com/jashkenas/underscore.git' },
homepage: 'http://underscorejs.org',
main: 'underscore.js',
version: '1.5.2',
devDependencies: { phantomjs: '1.9.0-1' },
licenses:
{ type: 'MIT',
url: 'https://raw.github.com/jashkenas/underscore/master/LICENSE' },
files:
[ 'underscore.js',
'underscore-min.js',
'LICENSE' ],
readmeFilename: 'README.md'}
上面命令返回一个 JavaScript 对象,包含了 underscore 模块的详细信息。这个对象的每个成员,都可以直接从 info 命令查询。
$ npm info underscore description
JavaScript's functional programming helper library.
$ npm info underscore homepage
http://underscorejs.org
$ npm info underscore version
1.5.2
npm search 搜索 npm 仓库
npm search
命令用于搜索 npm 仓库,它后面可以跟字符串,也可以跟正则表达式。
$ npm search <搜索词>
$ npm search node-gyp
// NAME DESCRIPTION
// autogypi Autogypi handles dependencies for node-gyp projects.
// grunt-node-gyp Run node-gyp commands from Grunt.
// gyp-io Temporary solution to let node-gyp run `rebuild` under…
// ...
npm list 列出安装的模块
npm list
命令以树形结构列出当前项目安装的所有模块,以及它们依赖的模块。
基础语法
npm ls [[<@scope>/]<pkg> ...]
aliases: list, la, ll
$ npm list # 注意:这个是列出本地( 即当前目录 )安装的模块
$ npm list -global # 加上 global 参数,会列出全局安装的模块
$ npm ls -g # 查看全局安装的模块及依赖
$ npm list underscore # npm list 命令也可以列出单个模块
npm install ( 本地安装、全局安装 )
本地安装:npm install <package name>
全局安装:sudo npm install -global <package name> 或 sudo npm install -g <package name>
npm 安装包的命令格式:npm [install/i] [package_name] 注意:执行 npm install 时会先检查 node_modules 目录中是否已经存在指定模块。如果存在,就不再重新安装了,即使远程仓库已经有了一个新版本,也是如此。
$ npm install <packageName> --force # 使用 -f 或 --force 可以强制重新安装
# 如果想要所有模块都强制重新安装,可以删除node_modules目录,执行 npm install
$ rm -rf node_modules
$ npm 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 <tarball file>
npm install <tarball url>
npm install <folder> alias:
npm i common options: [-S|--save|-D|--save-dev|-O|--save-optional] [-E|--save-exact] [--dry-run]
node 模块采用 npm install 命令安装,每个模块可以 “全局安装”,也可以 “本地安装”。
- 全局安装:将模块下载安装到系统目录中,各个项目都可以调用。一般只适用于工具模块。
全局安装(global),使用 -g 或 --global
示例:sudo npm install -global <package name>
示例:sudo npm install -g <package name> - 本地安装 (默认):将模块下载并安装到当前项目的 node_modules 目录,并且只在当前项目目录中才能调用这个模块。( 本地模式不会注册 PATH 环境变量 )。npm 默认会从 http://npmjs.org 搜索并下载包,然后把包安装到当前目录的 node_modules 目录下。然后只有在项目目录之中,才能调用这个模块。这反映了 npm 不同的设计哲学:如果把包安装到全局,可以提供程序的重复利用程度,避免同样的内容的多分副本,但坏处是难以处理不同的版本依赖。如果把包安装到当前目录,或者说本地,则不会有不同程序依赖不同版本的包的冲突问题,同时还减轻了包作者的 API 兼容性压力,但缺陷则是同一个包可能会被安装许多次。
本地安装(local):npm install <package name> - 安装到指定目录:npm config set prefix 指定的目录
- 通过 github 安装:
npm install 也支持直接输入 Github 代码库地址。
示例:npm install git://github.com/package/path.git
示例:npm install git://github.com/package/path.git#0.1.0 - 安装不同版本:nmp install 命令总是安装模块的最新版本,如果要安装模块的特定版本,可以在模块名后面加上 @ 和 版本号。
npm install sax@latest
npm install sax@0.1.1
npm install sax@">=0.1.0 <0.2.0"
使用 npm install 安装模块的模块的时候 ,一般会使用下面这几种命令形式:
- npm install moduleName # 安装模块到项目目录下
- npm install -g moduleName # -g 的意思是将模块安装到全局,具体安装到磁盘哪个位置,要看 npm config prefix 的位置。
- npm install -save moduleName # -save 的意思是将模块安装到项目目录下,并在package文件的 dependencies 节点写入依赖。
- npm install -save-dev moduleName # -save-dev 的意思是将模块安装到项目目录下,并在package文件的 devDependencies 节点写入依赖。
npm install moduleName 命令
1. 安装模块到项目node_modules目录下。
2. 不会将模块依赖写入devDependencies或dependencies 节点。
3. 运行 npm install 初始化项目时不会下载模块。
npm install -g moduleName 命令
1. 安装模块到全局,不会在项目node_modules目录中保存模块包。
2. 不会将模块依赖写入devDependencies或dependencies 节点。
3. 运行 npm install 初始化项目时不会下载模块。
npm install -save moduleName 命令
1. 安装模块到项目node_modules目录下。
2. 会将模块依赖写入dependencies 节点。
3. 运行 npm install 初始化项目时,会将模块下载到项目目录下。
4. 运行npm install --production或者注明NODE_ENV变量值为production时,会自动下载模块到node_modules目录中。
npm install -save-dev moduleName 命令
1. 安装模块到项目 node_modules 目录下。
2. 会将模块依赖写入devDependencies 节点。
3. 运行 npm install 初始化项目时,会将模块下载到项目目录下。
4. 运行 npm install --production或者注明NODE_ENV变量值为production时,不会自动下载模块到node_modules目录中。
dependencies 依赖
这个对象里面的内容就是项目所依赖的 js 模块包。下面这段代码表示依赖了 markdown-it
这个包,版本是 ^8.1.0
,代表最小依赖版本是 8.1.0
,如果这个包有更新,那么当我们使用 npm install
命令的时候,npm 会帮我们下载最新的包。当别人引用我们这个包的时候,包内的依赖包也会被下载下来。
"dependencies": {
"markdown-it": "^8.1.0"
}
devDependencies 开发依赖
在开发的时候会用到的一些包,只是在开发环境中需要用到,但是在别人引用我们包的时候,不会用到这些内容,放在 devDependencies 的包,在别人引用的时候不会被 npm 下载。
"devDependencies": {
"autoprefixer": "^6.4.0",0",
"babel-preset-es2015": "^6.0.0",
"babel-preset-stage-2": "^6.0.0",
"babel-register": "^6.0.0",
"webpack": "^1.13.2",
"webpack-dev-middleware": "^1.8.3",
"webpack-hot-middleware": "^2.12.2",
"webpack-merge": "^0.14.1",
"highlightjs": "^9.8.0"
}
当有了一个完整的 package.json 文件的时候,就可以让人一眼看出来,这个模块的基本信息,和这个模块所需要依赖的包。通过 npm install 就可以很方便的下载好这个模块所需要的包。
npm install
默认会安装 dependencies 字段和 devDependencies 字段中的所有模块,如果使用 --production
参数,可以只安装 dependencies 字段的模块。
$ npm install --production
# 或者
$ NODE_ENV=production npm install
一旦安装了某个模块,就可以在代码中用 require 命令加载这个模块。
var backbone = require('backbone')
console.log(backbone.VERSION)
# 项目根目录下执行
$ npm bin
./node_modules/.bin
--save、--save-dev、--save-optional、--save-exact
--save 和 --save-dev
- --save 会把依赖包名称添加到 package.json 文件 dependencies 键下,dependencies 下的模块是发布后还需要依赖的模块。--save 可以简化为参数 -S。 示例:npm install sax --save 或 npm install sax -S
- --save-dev 则添加到 package.json 文件 devDependencies 键下,devDependencies 是开发阶段依赖的模块,发布时就不需要依赖了。可以简化为参数 -D。示例:npm install node-tap --save-dev 或 npm install node-tap -D
- -O, --save-optional 安装包信息将加入到 package.json 的 optionalDependencies 键下(可选阶段的依赖)。示例:npm install gulp --save-optional 或 npm install gulp -O
- -E, --save-exact 精确安装指定模块版本。示例:npm install gulp --save-exact 或 npm install gulp -E 。示例:npm install gulp -ES
npm install 默认会安装 dependencies 字段和 devDependencies 字段中的所有模块,如果使用 --production 参数,可以只安装 dependencies 字段的模块。
npm install --production 或者 NODE_ENV=production npm install
一旦安装了某个模块,就可以在代码中用 require 命令加载这个模块。
var backbone = require('backbone')
console.log(backbone.VERSION)
npm uninstall 卸载安装的模块
格式:npm uninstall [<@scope>/]<pkg>[@<version>]... [-S|--save|-D|--save-dev|-O|--save-optional]
别名:remove, rm, r, un, unlink
示例:npm uninstall [package name]
卸载 全局 模块:npm uninstall [package name] -global
卸载 开发版 模块:npm uninstall gulp --save-dev
npm update 更新模块
npm update 命令可以更新本地安装的模块。基础语法:npm update [-g] [<pkg>...] 执行命令时,先到远程仓库查询最新版本,然后查询本地版本。如果本地版本不存在或者远程版本较新就安装。
升级当前项目的指定模块:npm update [package name]
升级全局安装的模块:npm update -global [package name]
使用 -S 或 --save 参数,可以在安装的时候更新 package.json 里面模块的版本号。
// 更新之前的package.json
dependencies: {
dep1: "^1.1.1"
}
// 更新之后的package.json
dependencies: {
dep1: "^1.2.2"
}
注意,从 npm v2.6.1 开始,npm update
只更新顶层模块,而不更新依赖的依赖,以前版本是递归更新的。如果想取到老版本的效果,要使用下面的命令。
$ npm --depth 9999 update
npm outdated 检查模块是否已经过时
基础语法:npm outdated [[<@scope>/]<pkg> ...]
此命令会列出所有已经过时的包,可以及时进行包的更新
避免 系统 权限
默认情况下,Npm 全局模块都安装在系统目录(比如/usr/local/lib/
),普通用户没有写入权限,需要用到sudo
命令。这不是很方便,我们可以在没有root权限的情况下,安装全局模块。
首先,在主目录下新建配置文件.npmrc
,然后在该文件中将 prefix
变量定义到主目录下面。
prefix = /home/yourUsername/npm
然后在主目录下新建 npm
子目录。
$ mkdir ~/npm
此后,全局安装的模块都会安装在这个子目录中,npm也会到~/npm/bin
目录去寻找命令。最后,将这个路径在.bash_profile
文件(或.bashrc
文件)中加入PATH变量。
export PATH=~/npm/bin:$PATH
npm run 执行脚本
npm 不仅可以用于模块管理,还可以用于执行脚本。package.json 文件有一个 scripts 字段,可以用于指定脚本命令,供 npm 直接调用。
{
"name": "myproject",
"devDependencies": {
"jshint": "latest",
"browserify": "latest",
"mocha": "latest"
},
"scripts": {
"lint": "jshint **.js",
"test": "mocha test/"
}
}
上面代码中 scripts 字段指定了两个命令 lint 和 test。命令行输入 npm run-script lint 或者 npm run lint,就会执行 jshint **.js,输入 npm run-script test 或者 npm run test,就会执行 mocha test/。
- npm run 是 npm run-script 的缩写,一般都使用前者。
- npm run 会创建一个 Shell 执行指定的命令,并临时将 node_modules/.bin 加入 PATH 变量,这意味着本地模块可以直接运行。所以 scripts 字段里面调用命令时不用加上路径,这就避免了全局安装 npm 模块。
- npm run 不加任何参数直接运行时会列出 package.json 里面所有可以执行的脚本命令。
- npm 内置了两个缩写命令:npm test 等价于 npm run test,npm start 等价于 npm run start
示例:npm i eslint --save-dev 执行安装 ESLint 包,会产生两个结果。
- 首先,ESLint 被安装到当前目录的 node_modules 子目录;
- 其次 node_modules/.bin 目录会生成一个符号链接 node_modules/.bin/eslint,指向 ESLint 模块的可执行脚本。
- 然后,你就可以在 package.json 的 script 属性里面,不带路径的引用 eslint 这个脚本。
{ "name": "Test Project", "devDependencies": { "eslint": "^1.10.3" }, "scripts": { "lint": "eslint ." } }
- 运行 npm run lint 的时候,它会自动执行 ./node_modules/.bin/eslint 。如果直接运行 npm run 不给出任何参数,就会列出 scripts 属性下所有命令。
$ npm run Available scripts in the user-service package: lint jshint **.js test mocha test/
示例:另一个 package.json
文件的例子。
"scripts": {
"watch": "watchify client/main.js -o public/app.js -v",
"build": "browserify client/main.js -o public/app.js",
"start": "npm run watch & nodemon server.js",
"test": "node test/all.js"
},
上面代码在 scripts
项,定义了四个别名,每个别名都有对应的脚本命令。
$ npm run watch
$ npm run build
$ npm run start
$ npm run test
其中,start
和 test
属于特殊命令,可以省略 run
。
$ npm start
$ npm test
如果希望一个操作的输出,是另一个操作的输入,可以借用 Linux 系统的管道命令,将两个操作连在一起。
"build-js": "browserify browser/main.js | uglifyjs -mc > static/bundle.js"
但是,更方便的写法是引用其他 npm run
命令。
"build": "npm run build-js && npm run build-css"
上面的写法是先运行 npm run build-js
,然后再运行 npm run build-css
,两个命令中间用 &&
连接。如果希望两个命令同时平行执行,它们中间可以用 &
连接。
下面是一个流操作的例子。
"devDependencies": {
"autoprefixer": "latest",
"cssmin": "latest"
},
"scripts": {
"build:css": "autoprefixer -b 'last 2 versions' < assets/styles/main.css | cssmin > dist/main.css"
}
写在 scripts
属性中的命令,也可以在 node_modules/.bin
目录中直接写成bash脚本。下面是一个 bash 脚本。
#!/bin/bash
cd site/main
browserify browser/main.js | uglifyjs -mc > static/bundle.js
假定上面的脚本文件名为 build.sh,并且权限为可执行,就可以在 scripts 属性中引用该文件。
"build-js": "bin/build.sh"
npm run 命令还可以添加参数。
"scripts": {
"test": "mocha test/"
}
上面代码指定 npm test
,实际运行 mocha test/
。如果要通过 npm test
命令,将参数传到 mocha,则参数之前要加上两个连词线。
$ npm run test -- anothertest.js
# 等同于
$ mocha test/ anothertest.js
上面命令表示,mocha 要运行所有test
子目录的测试脚本,以及另外一个测试脚本anothertest.js
。
npm run
本身有一个参数-s
,表示关闭npm本身的输出,只输出脚本产生的结果。
// 输出npm命令头
$ npm run test
// 不输出npm命令头
$ npm run -s test
scripts 脚本命令最佳实践
scripts
字段的脚本命令,有一些最佳实践,可以方便开发。首先,安装npm-run-all
模块。
$ npm install npm-run-all --save-dev
这个模块用于运行多个scripts
脚本命令。
# 继发执行
$ npm-run-all build:html build:js
# 等同于
$ npm run build:html && npm run build:js
# 并行执行
$ npm-run-all --parallel watch:html watch:js
# 等同于
$ npm run watch:html & npm run watch:js
# 混合执行
$ npm-run-all clean lint --parallel watch:html watch:js
# 等同于
$ npm-run-all clean lint
$ npm-run-all --parallel watch:html watch:js
# 通配符
$ npm-run-all --parallel watch:*
(1)start 脚本命令
start 脚本命令,用于启动应用程序:"start": "npm-run-all --parallel dev serve"
上面命令并行执行 dev 脚本命令和 serve 脚本命令,等同于:$ npm run dev & npm run serve
如果 start 脚本没有配置,npm start 命令默认执行下面的脚本,前提是模块的根目录存在一个 server.js 文件:$ node server.js
(2)dev 脚本命令
dev脚本命令,规定开发阶段所要做的处理,比如构建网页资源。:"dev": "npm-run-all dev:*"
上面命令用于继发执行所有dev的子命令。
:"predev:sass": "node-sass --source-map src/css/hoodie.css.map --output-style nested src/sass/base.scss src/css/hoodie.css"
上面命令将 sass 文件编译为 css 文件,并生成 source map文件。
:"dev:sass": "node-sass --source-map src/css/hoodie.css.map --watch --output-style nested src/sass/base.scss src/css/hoodie.css"
上面命令会监视sass文件的变动,只要有变动,就自动将其编译为css文件。
:"dev:autoprefix": "postcss --use autoprefixer --autoprefixer.browsers \"> 5%\" --output src/css/hoodie.css src/css/hoodie.css"
上面命令为css文件加上浏览器前缀,限制条件是只考虑市场份额大于5%的浏览器。
(3)serve 脚本命令
serve
脚本命令用于启动服务。:"serve": "live-server dist/ --port=9090"
上面命令启动服务,用的是 live-server 模块,将服务启动在9090端口,展示dist
子目录。
live-server
模块有三个功能。
- 启动一个HTTP服务器,展示指定目录的
index.html
文件,通过该文件加载各种网络资源,这是file://
协议做不到的。 - 添加自动刷新功能。只要指定目录之中,文件有任何变化,它就会刷新页面。
npm run serve
命令执行以后,自动打开浏览器。、
以前,上面三个功能需要三个模块来完成:http-server
、live-reload
和opener
,现在只要live-server
一个模块就够了。
(4)test 脚本命令
test
脚本命令用于执行测试。
"test": "npm-run-all test:*",
"test:lint": "sass-lint --verbose --config .sass-lint.yml src/sass/*"
上面命令规定,执行测试时,运行lint
脚本,检查脚本之中的语法错误。
(5)prod 脚本命令
prod
脚本命令,规定进入生产环境时需要做的处理。
"prod": "npm-run-all prod:*",
"prod:sass": "node-sass --output-style compressed src/sass/base.scss src/css/prod/hoodie.min.css",
"prod:autoprefix": "postcss --use autoprefixer --autoprefixer.browsers "> 5%" --output src/css/prod/hoodie.min.css src/css/prod/hoodie.min.css"
上面命令将sass文件转为css文件,并加上浏览器前缀。
(6)help 脚本命令
help
脚本命令用于展示帮助信息。
"help": "markdown-chalk --input DEVELOPMENT.md"
上面命令之中,markdown-chalk
模块用于将指定的markdown文件,转为彩色文本显示在终端之中。
(7)docs 脚本命令
docs
脚本命令用于生成文档。
"docs": "kss-node --source src/sass --homepage ../../styleguide.md"
上面命令使用 kss-node
模块,提供源码的注释生成 markdown 格式的文档。
pre- 和 post- 脚本
npm run 为每条命令提供了 pre- 和 post- 两个钩子(hook)。以 npm run lint 为例,执行这条命令之前,npm 会先查看有没有定义 prelint 和 postlint 两个钩子,如果有的话,就会先执行 npm run prelint,然后执行 npm run lint,最后执行 npm run postlint。
{
"name": "myproject",
"devDependencies": {
"eslint": "latest"
"karma": "latest"
},
"scripts": {
"lint": "eslint --cache --ext .js --ext .jsx src",
"test": "karma start --log-leve=error karma.config.js --single-run=true",
"pretest": "npm run lint",
"posttest": "echo 'Finished running tests'"
}
}
上面代码是一个 package.json
文件的例子。如果执行 npm test
,会按下面的顺序执行相应的命令。
pretest
test
posttest
如果执行过程出错,就不会执行排在后面的脚本,即如果 prelint 脚本执行出错,就不会接着执行 lint 和 postlint 脚本。
下面是一个例子。
{
"test": "karma start",
"test:lint": "eslint . --ext .js --ext .jsx",
"pretest": "npm run test:lint"
}
上面代码中,在运行 npm run test
之前,会自动检查代码,即运行 npm run test:lint
命令。
下面是一些常见的 pre-
和 post-
脚本。
prepublish
:发布一个模块前执行。postpublish
:发布一个模块后执行。preinstall
:用户执行npm install
命令时,先执行该脚本。postinstall
:用户执行npm install
命令时,安装结束后执行该脚本,通常用于将下载的源码编译成用户需要的格式,比如有些模块需要在用户机器上跟本地的C++模块一起编译。preuninstall
:卸载一个模块前执行。postuninstall
:卸载一个模块后执行。preversion
:更改模块版本前执行。postversion
:更改模块版本后执行。pretest
:运行npm test
命令前执行。posttest
:运行npm test
命令后执行。prestop
:运行npm stop
命令前执行。poststop
:运行npm stop
命令后执行。prestart
:运行npm start
命令前执行。poststart
:运行npm start
命令后执行。prerestart
:运行npm restart
命令前执行。postrestart
:运行npm restart
命令后执行。
对于最后一个 npm restart
命令,如果没有设置 restart
脚本,prerestart
和 postrestart
会依次执行 stop 和 start 脚本。
另外,不能在 pre
脚本之前再加 pre
,即 prepretest
脚本不起作用。
注意,即使 Npm 可以自动运行 pre
和 post
脚本,也可以手动执行它们。
$ npm run prepublish
下面是 post install
的例子。
{
"postinstall": "node lib/post_install.js"
}
上面的这个命令,主要用于处理从Git仓库拉下来的源码。比如,有些源码是用TypeScript写的,可能需要转换一下。
下面是 publish
钩子的一个例子。
{
"dist:modules": "babel ./src --out-dir ./dist-modules",
"gh-pages": "webpack",
"gh-pages:deploy": "gh-pages -d gh-pages",
"prepublish": "npm run dist:modules",
"postpublish": "npm run gh-pages && npm run gh-pages:deploy"
}
上面命令在运行 npm run publish
时,会先执行 Babel 编译,然后调用 Webpack 构建,最后发到 Github Pages 上面。
以上都是 npm 相关操作的钩子,如果安装某些模块,还能支持Git相关的钩子。下面以husky模块为例。
$ npm install husky --save-dev
安装以后,就能在package.json
添加precommit
、prepush
等钩子。
{
"scripts": {
"lint": "eslint yourJsFiles.js",
"precommit": "npm run test && npm run lint",
"prepush": "npm run test && npm run lint",
"...": "..."
}
}
类似作用的模块还有pre-commit
、precommit-hook
等。
内部变量
scripts 字段可以使用一些内部变量,主要是 package.json 的各种字段。
比如,package.json 的内容是{"name":"foo", "version":"1.2.5"}
,那么变量 npm_package_name
的值是 foo,变量 npm_package_version
的值是1.2.5。
{
"scripts":{
"bundle": "mkdir -p build/$npm_package_version/"
}
}
运行 npm run bundle
以后,将会生成 build/1.2.5/
子目录。
config
字段也可以用于设置内部字段。
"name": "fooproject",
"config": {
"reporter": "xunit"
},
"scripts": {
"test": "mocha test/ --reporter $npm_package_config_reporter"
}
上面代码中,变量 npm_package_config_reporter
对应的就是 reporter。
通配符
npm 的通配符的规则如下。
*
匹配0个或多个字符?
匹配1个字符[...]
匹配某个范围的字符。如果该范围的第一个字符是!
或^
,则匹配不在该范围的字符。!(pattern|pattern|pattern)
匹配任何不符合给定的模式?(pattern|pattern|pattern)
匹配0个或1个给定的模式+(pattern|pattern|pattern)
匹配1个或多个给定的模式*(a|b|c)
匹配0个或多个给定的模式@(pattern|pat*|pat?erN)
只匹配给定模式之一**
如果出现在路径部分,表示0个或多个子目录。
npm link 创建 全局 链接
npm 提供了一个有趣的命令 npm link
,它的功能是在本地包和全局包之间创建符号链接。使用全局模式安装的包不能直接通过 require
使用。但通过 npm link
命令可以打破这一限制。举个例子,我们已经通过 npm install -g express
安装了 express,这时在工程的目录下运行命令:
npm link express ./node_modules/express -> /user/local/lib/node_modules/express
我们可以在 node_modules
子目录中发现一个指向安装到全局的包的符号链接。通过这种方法,我们就可以把全局包当做本地包来使用了。
除了将全局的包链接到本地以外,使用 npm link 命令还可以将本地的包链接到全局。使用方法是在包目录(package.json 所在目录)中运行 npm link 命令。如果我们要开发一个包,利用这种方法可以非常方便地在不同的工程间进行测试。
开发 NPM 模块的时候,有时我们会希望,边开发边试用,比如本地调试的时候,require('myModule')
会自动加载本机开发中的模块。Node 规定,使用一个模块时,需要将其安装到全局的或项目的 node_modules
目录之中。对于开发中的模块,解决方法就是在全局的 node_modules
目录之中,生成一个符号链接,指向模块的本地目录。npm link
就能起到这个作用,会自动建立这个符号链接。
请设想这样一个场景,你开发了一个模块 myModule
,目录为 src/myModule
,你自己的项目 myProject
要用到这个模块,项目目录为 src/myProject
。首先,在模块目录(src/myModule
)下运行 npm link
命令。
src/myModule$ npm link
上面的命令会在 NPM 的全局模块目录内,生成一个符号链接文件,该文件的名字就是 package.json
文件中指定的模块名。
/path/to/global/node_modules/myModule -> src/myModule
这个时候,已经可以全局调用 myModule
模块了。但是,如果我们要让这个模块安装在项目内,还要进行下面的步骤。
切换到项目目录,再次运行 npm link
命令,并指定模块名。
src/myProject$ npm link myModule
上面命令等同于生成了本地模块的符号链接。
src/myProject/node_modules/myModule -> /path/to/global/node_modules/myModule
然后,就可以在你的项目中,加载该模块了。
var myModule = require('myModule');
这样一来,myModule
的任何变化,都可以直接反映在 myProject
项目之中。但是,这样也出现了风险,任何在 myProject
目录中对 myModule
的修改,都会反映到模块的源码中。
如果你的项目不再需要该模块,可以在项目目录内使用 npm unlink
命令,删除符号链接。
src/myProject$ npm unlink myModule
npm bin
npm bin
命令显示相对于当前目录的,Node 模块的可执行脚本所在的目录(即.bin
目录)。
# 项目根目录下执行
$ npm bin
./node_modules/.bin
npm adduser
npm adduser
用于在 npmjs.com 注册一个用户。
$ npm adduser
Username: YOUR_USER_NAME
Password: YOUR_PASSWORD
Email: YOUR_EMAIL@domain.com
npm publish
npm publish
用于将当前模块发布到 npmjs.com
。执行之前,需要向 npmjs.com
申请用户名。
$ npm adduser
如果已经注册过,就使用下面的命令登录。
$ npm login
登录以后,就可以使用 npm publish
命令发布。
$ npm publish
如果当前模块是一个beta版,比如1.3.1-beta.3
,那么发布的时候需要使用tag
参数,将其发布到指定标签,默认的发布标签是latest
。
$ npm publish --tag beta
如果发布私有模块,模块初始化的时候,需要加上scope
参数。只有npm的付费用户才能发布私有模块。
$ npm init --scope=<yourscope>
如果你的模块是用ES6写的,那么发布的时候,最好转成ES5。首先,需要安装Babel。
$ npm install --save-dev babel-cli@6 babel-preset-es2015@6
然后,在package.json
里面写入build
脚本。
"scripts": {
"build": "babel source --presets babel-preset-es2015 --out-dir distribution",
"prepublish": "npm run build"
}
运行上面的脚本,会将source
目录里面的ES6源码文件,转为distribution
目录里面的ES5源码文件。然后,在项目根目录下面创建两个文件.npmignore
和.gitignore
,分别写入以下内容。
// .npmignore
source
// .gitignore
node_modules
distribution
npm deprecate
如果想废弃某个版本的模块,可以使用 npm deprecate
命令。
$ npm deprecate my-thing@"< 0.2.3" "critical bug fixed in v0.2.3"
运行上面的命令以后,小于0.2.3
版本的模块的 package.json
都会写入一行警告,用户安装这些版本时,这行警告就会在命令行显示。
npm owner
模块的维护者可以发布新版本。npm owner
命令用于管理模块的维护者。
# 列出指定模块的维护者
$ npm owner ls <package name>
# 新增维护者
$ npm owner add <user> <package name>
# 删除维护者
$ npm owner rm <user> <package name>
npm home,npm repo
npm home
命令可以打开一个模块的主页,npm repo
命令则是打开一个模块的代码仓库。
$ npm home $package
$ npm repo $package
npm outdated
npm outdated
命令检查当前项目所依赖的模块,是否已经有新版本。
$ npm outdated
它会输出当前版本(current version)、应当安装的版本(wanted version)和最新发布的版本(latest version)。
npm prune
npm prune
检查当前项目的 node_modules
目录中,是否有 package.json
里面没有提到的模块,然后将所有这些模块输出在命令行。
$ npm prune
npm shrinkwrap
npm shrinkwrap
的作用是锁定当前项目的依赖模块的版本。
$ npm shrinkwrap
运行该命令后,会在当前项目的根目录下生成一个npm-shrinkwrap.json
文件,内容是node_modules
目录下所有已经安装的模块,以及它们的精确版本。
下次运行npm install
命令时,npm
发现当前目录下有npm-shrinkwrap.json
文件,就会只安装里面提到的模块,且版本也会保持一致。
创建包
包是在模块基础上更深一步的抽象,Node.js 的包类似于 C/C++ 的函数库或者 Java、.Net 的类库。它将某个独立的功能封装起来,用于发布、更新、依赖管理和版本控制。Node.js 根据 CommonJS 规范实现了包机制,开发了 npm 来解决包的发布和获取需求。
Node.js 的包是一个目录,其中包含了一个 JSON 格式的包说明文件 package.json。严格符合 CommonJS 规范的包应该具备以下特征:
- package.json 必须在包的顶层目录下;
- 二进制文件应该在 bin 目录下;
- JavaScript 代码应该在 lib 目录下;
- 文档应该在 doc 目录下;
- 单元测试应该在 test 目录下。
Node.js 对包的要求并没有这么严格,只要顶层目录下有 package.json,并符合一些规范即可。当然为了提高兼容性,我们还是建议你在制作包的时候,严格遵守 CommonJS 规范。
我们也可以把文件夹封装为一个模块,即所谓的包。包通常是一些模块的集合,在模块的基础上提供了更高层的抽象,相当于提供了一些固定接口的函数库。通过定制 package.json,我们可以创建更复杂,更完善,更符合规范的包用于发布。
Node.js 在调用某个包时,会首先检查包中 packgage.json 文件的 main 字段,将其作为包的接口模块,如果 package.json 或 main 字段不存在,会尝试寻找 index.js 或 index.node 作为包的接口。
npm package.json 的语法
英文原版:https://docs.npmjs.com/files/package.json
这块内容好多,国内有好心人整理:《npm的package.json中文文档》,从这份文档拷贝出一些比较常见的,如下:
默认值
npm 会根据包内容设置一些默认值。
-
"scripts": {"start": "node server.js"}
如果包的根目录有
server.js
文件,npm会默认将start
命令设置为node server.js
。 -
"scripts":{"preinstall": "node-waf clean || true; node-waf configure build"}
如果包的根目录有
wscript
文件,npm会默认将preinstall
命令用node-waf进行编译。 -
"scripts":{"preinstall": "node-gyp rebuild"}
如果包的根目录有
binding.gyp
文件,npm会默认将preinstall
命令用node-gyp进行编译。 -
"contributors": [...]
如果包的根目录有
AUTHORS
文件,npm会默认逐行按Name <email> (url)
格式处理,邮箱和url是可选的。#号和空格开头的行会被忽略。
package.json 是 CommonJS 规定的用来描述包的文件,完全符合规范的 package.json 文件应该含有以下字段:
- name: 包的名字,必须是唯一的,由小写英文字母、数字和下划线组成,不能包含空格。
- description: 包的简要说明。放简介,字符串,方便在
npm search
中搜索 - version: 符合语义化版本识别规范的版本字符串。version 必须能被 node-semver 解析,它被包在npm的依赖中。(要自己用可以执行
npm install semver
)可用的“数字”或者“范围”见semver(7).
- keywords: 关键字,数组、字符串,通常用于搜索。方便在
npm search
中搜索 - maintainers: 维护者数组,每个元素要包含 name 、email(可选)、web(可选)字段。
- contributors: 贡献者数组,格式与 maintainers 相同。包的作者应该是贡献者数组的第一个元素。
- bugs: 提交 bug 的地址,可以是网址或者电子邮件地址。
- licenses: 许可证数组,每个元素要包含 type(许可证的名称)和 url(链接到许可证文本的地址)字段。
- repositories: 仓库托管地址数组,每个元素要包含 type(仓库的类型,如 git)、URL(仓库的地址)和 path(相对于仓库的路径,可选)字段。
- dependencies: 包的依赖,一个关联数组,由包名称和版本号组成。依赖是给一组包名指定版本范围的一个hash。这个版本范围是一个由一个或多个空格分隔的字符串。依赖还可以用tarball或者git URL。请不要将测试或过渡性的依赖放在
dependencies
hash中。见下文的devDependencies
- scripts: “scripts” 是一个由脚本命令组成的hash对象,他们在包不同的生命周期中被执行。key是生命周期事件,value是要运行的命令。参考上面的npm start、npm test命令。更多详细请看 npm-scripts(7)
- config:"config" hash可以用来配置用于包脚本中的跨版本参数。在实例中,如果一个包有下面的配置:{ "name" : "foo", "config" : { "port" : "8080" } },然后有一个 “start” 命令引用了
npm_package_config_port
环境变量,用户可以通过npm config set foo:port 8001
来重写他。参见 npm-config(7) 和 npm-scripts(7)。
需要说明的是:json 文件不能有注释
在 package.json 中最重要的就是 name 和 version 字段。他们都是必须的,如果没有就无法 install。name 和 version 一起组成的标识在假设中是唯一的。改变包应该同时改变version。
name是这个东西的名字。注意:
- 不要把node或者js放在名字中。因为你写了package.json它就被假定成为了js,不过你可以用"engine"字段指定一个引擎(见后文)。
- 这个名字会作为在URL的一部分、命令行的参数或者文件夹的名字。任何non-url-safe的字符都是不能用的。
- 这个名字可能会作为参数被传入require(),所以它应该比较短,但也要意义清晰。
- 在你爱上你的名字之前,你可能要去npm registry查看一下这个名字是否已经被使用了。http://registry.npmjs.org/
详见 semver(7).
version
必须完全和version
一致>version
必须比version
大>=version
同上<version
同上<=version
同上~version
大约一样,见semver(7)1.2.x
1.2.0, 1.2.1, 等,但不包括1.3.0http://...
见下文'依赖URL'*
所有""
空,同*
version1 - version2
同>=version1 <=version2
.range1 || range2
二选一。git...
见下文'依赖Git URL'user/repo
见下文'GitHub URLs'
比如下面都是合法的:
{ "dependencies" :
{ "foo" : "1.0.0 - 2.9999.9999" , "bar" : ">=1.0.2 <2.1.2" , "baz" : ">1.0.2 <=2.3.4" , "boo" : "2.0.1" , "qux" : "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0" , "asd" : "http://asdf.com/asdf.tar.gz" , "til" : "~1.2" , "elf" : "~1.2.3" , "two" : "2.x" , "thr" : "3.3.x" } }
包的发布
通过使用 npm init
可以根据交互式回答产生一个符合标准的 package.json。创建一个 index.js
作为包的接口,一个简单的包就制作完成了。
在发布前,我们还需要获得一个账号用于今后维护自己的包,使用 npm adduser
根据提示完成账号的创建。
完成后可以使用 npm whoami
检测是否已经取得了账号。
接下来,在 package.json 所在目录下运行 npm publish
,稍等片刻就可以完成发布了,打开浏览器,访问 http://search.npmjs.org/ 就可以找到自己刚刚发布的包了。现在我们可以在世界的任意一台计算机上使用 npm install neveryumodule
命令来安装它。
如果你的包将来有更新,只需要在 package.json 文件中修改 version 字段,然后重新使用 npm publish
命令就行了。
如果你对已发布的包不满意,可以使用 npm unpublish
命令来取消发布。