随着nodejs的发展,作为 node 自带的包管理工具的 npm 已经成为每个前端开发者必备的工具。但在日常使用中,往往只停留在npm install,遇到无法解决的问题时,只会删除node_modules 目录然后重新 install ,作为世界上最大规模的包管理系统,还有很多特性和方法需要学习。
基本概念
npm(node package manager)node的包管理工具,常见使用场景如下:
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
npm init
npm init 命令用来初始化一个简单的 package.json 文件,package.json 文件是用来定义一个 package 的描述文件,执行该命令后终端会依次询问 name、version,、description 等字段。
如果不想手动去输入这些字段,直接采用默认内容,可以在命令后面追加–yes参数,和一路回车效果一样。
npm init --yes
自定义 npm init 行为
npm init 命令的原理就是调用脚本,输出一个初始化的 package.json 文件。在windows当前用户的目录下创建 .npm-init.js文件
module.exports就是package.json的配置内容,使用prompt()可以获取用户输入
const desc = prompt('description?', 'A custom template...')
const type = prompt('type?', '')
const user = prompt('user?', 'test')
module.exports = {
key: 'value',
project: {
type: type,
user: user
},
name: prompt('name?', process.cwd().split('\\').pop()),
version: prompt('version?', '0.1.0'),
description: desc,
main: 'index.js',
}
在test目录下执行npm init,得到如下package.json文件
{
"key": "value",
"project": {
"type": "",
"user": "test"
},
"name": "test",
"version": "0.1.0",
"description": "A custom template...",
"main": "index.js"
}
除了生成 package.json,还可以执行node 脚本可以执行的任务。例如通过 fs 创建 README、.eslintrc 等项目必需文件,实现项目脚手架的作用。
依赖包安装
npm的核心功能,就是执行 npm install 从 package.json 中的 dependencies、devDependencies 将依赖包安装到当前目录的 ./node_modules 文件夹中。
默认配置下npm会从默认的源 (Registry) 中查找该包名对应的包地址,并下载安装。除了简单的指定包名,package还可以是一个指向有效包名的http、url/git、url/文件夹路径。
引用本地模块
1、在项目根目录创建要引用的模块,customerConfig文件夹,在文件夹内部新建index.js,和package.json文件,package.json文件内容如下:
{
"name": "customerConfig",
"main": "index.js",
"version": "0.1.0"
}
2、在项目的package.json文件中添加依赖项
"dependencies": {
"customerConfig": "file:./customerConfig"
}
3、执行npm install或者npm install file:./customerConfig
查看 node_modules 目录会发现多出来一个名为customerConfig,指向上层customerConfig文件夹的软链接。这是因为npm识别file:协议的url,得知这个包需要直接从文件系统中获取,会自动创建软链接到 node_modules 中,完成“安装”过程。
引用私有 git 共享 package
我们可以把被依赖的包托管在私有的git仓库中,然后将该git url保存到dependencies中,npm会直接调用系统的 git命令从git仓库拉取包的内容到node_modules中。
<protocol>://[<user>[:<password>]@]<hostname>[:<port>][:][/]<path>[#<commit-ish> | #semver:<semver>]
例如:
git+ssh://git@github.com:npm/npm.git#v1.0.27
git+ssh://git@github.com:npm/npm#semver:^5.0
git+https://isaacs@github.com/npm/npm.git
git://github.com/npm/npm.git#v1.0.27
npm script的使用
npm 可以在项目package.json里面自定义脚本命令
// package.json文件
{
"script":{
"dev": "webpack -w"
}
}
package.json文件中的字段script的每一个属性都是一个自定义的脚本命令。
在命令行中可以通过执行npm run dev来执行这段脚本。
执行原理
使用npm run script执行脚本的时候都会创建一个shell,然后在shell中执行指定的脚本。
这个shell会将当前项目的可执行依赖目录(即node_modules/.bin)添加到环境变量path中,当执行之后之后再恢复原样。就是说脚本命令中的依赖名会直接找到node_modules/.bin下面的对应脚本,而不需要加上路径。
传参
向 npm 脚本传入参数,要使用–标明。
npm run test -- --grep="pattern"
可以将 –grep=”pattern” 参数传给 test 命令
执行顺序
一个npm脚本可以执行多个任务,这些任务之间可以指定不同的执行顺序。
// '&' 并行执行顺序,同时执行
"dev":"node test.js & webpack"
// '&&'继发顺序,执行前面之后才可以执行后面
"dev":"node test.js && webpack"
顺序钩子
npm脚本自带两个顺序钩子,’pre’ 和 ‘post’
"predev":"node test_one.js",
"dev":"node test_two.js",
"postdev":"node test_three.js"
当执行npm run dev的时候默认就会执行
npm run predev && npm run dev && npm run postdev
可以缩写的脚本命令
npm start === npm run start
npm stop === npm run stop
npm test === npm run test
npm restart === npm run stop && npm run restart && npm run start
使用package.json内部变量
通过npm_package_前缀,npm脚本可以拿到npm的内部变量
// package.json:
{
"name":"develop",
"script":"node test.js"
}
test.js:
console.log(process.env.npm_package_name) //develop

