# 应该知道的 NPM 知识

# npm init

npm init 命令用来初始化一个简单的 package.json 文件

npm init --yes 跳过输入,使用默认配置生成 package.json
1

# 自定义npm init行为(mac)

  1. cd ~
  2. touch .npm-init.js 创建npm-init.js
const desc = prompt('description?', 'A new package...')
const bar = prompt('bar?', '')
const count = prompt('count?', '42')

module.exports = {
  key: 'value',
  foo: {
    bar: bar,
    count: count
  },
  name: prompt('name?', process.cwd().split('/').pop()),
  version: prompt('version?', '0.1.0'),
  description: desc,
  main: 'index.js',
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# dependenices 生成环境依赖

下列安装方式会把依赖加入dependenices

  1. npm install packageName
  2. npm i packageName
  3. npm i packageName -S
  4. npm i packageName -save
  5. npm i vue@3.0.1 -S 安装指导版本的vue

# devDependenices 开发环境依赖

下列安装方式会把依赖加入devDependenices

  1. npm install packageName -D
  2. npm i packageName -D
  3. npm i packageName --save-dev

# bin

bin 字段指定了各个内部命令对应的可执行文件的位置。

如果全局安装模块,npm 会使用符号链接把可执行文件链接到 /usr/local/bin,

如果项目中安装,会链接到 ./node_modules/.bin/。

"bin": {
    "vm2": "./bin/vm2"
},
1
2
3

# main

main 属性指定程序的主入口文件,其他项目在引用这个 npm 包时,实际上引入的是 lib/index 中暴露出去的模块。

{
  "main": "lib/index.js",
}
1
2
3

# npm script

在生成的 package.json 文件中,npm 允许使用 scripts 字段定义脚本命令。

npm run不加参数可以查看当前项目的package.json 文件中的scripts脚本有哪些

我们每次在运行npm run xxx 的时候,系统会自动开始一个shell,然后在shell里执行脚本。所有shell能执行的都可以写到 scripts

比如终端输入 npm run whoiam, 会输出当前用户名 zepeng

node_modules/.bin目录下的脚本可以直接放在 scripts里面, 比如改目录下有 browserslist, 则可以直接把这个browserslist加入scripts,然后直接 npm run browserslist

node_modules/.bin下的脚本是从哪里来的呢?

npm install 安装的某个模块,如果模块在 package.json 中配置了 bin 属性,在安装时候会自动软链接到 node_modules/.bin 中

"scripts": {
  "dev": "vuepress dev",  
  "build": "vuepress build",
  "whoiam": "whoami",
  "ls": "ls",
  "browserslist": "browserslist"


}
npm run dev 会执行 vuepress dev

直接执行 npm 会输出npm的可执行命令

执行 npm run 会显示 当前的scripts的可执行脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 脚本默认值

  1. npm run start 默认执行的是 node server.js 。 前提是根目录下有server.js
  2. npm run install 默认执行的是 node-gyp rebuild。前提是根目录下有 binding.gyp 文件

# 钩子(生命周期)

npm 脚本有两个钩子,pre 和 post,当我们执行start脚本时候,start 的钩子就是 prestart 和 poststart。

当我们执行 npm run build 的时候,npm 会自动按照下面的顺序执行

npm run prebuild && npm run build && npm run postbuild

{
  scripts: {
    "prebuild": "echo I run before the build script",
    "build": "node index.js",
    "postbuild": "echo I run after the build script"
  }
}
1
2
3
4
5
6
7

# env 环境变量

我们在执行 npm run 脚本时候, npm 会设置一些特殊的env环境变量。

package.json中的所有字段,都会被设置为以npm_package_开头的环境变量。看个简单的例子

package.json内容如下
{
  "name": "gittest",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "prebuild": "echo I run before the build script",
    "build": "node index.js --mode=pro",
    "postbuild": "echo I run after the build script"
  },
  "files": ["src","public"]
}
// 参数打印如下

{
  npm_package_gitHead: '4aa504dab2de8b156c0a31a7b53c5513065cda2d',
  npm_package_scripts_prebuild: 'echo I run before the build script',
  npm_package_name: 'gittest',
  npm_package_scripts_build: 'node index.js --mode=pro',
  npm_package_version: '',
  npm_package_scripts_test: 'echo "Error: no test specified" && exit 1',
  npm_package_scripts_postbuild: 'echo I run after the build script',
  npm_package_files_0: 'src',
  npm_package_files_1: 'public'
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

npm 相关的所有配置也会被设置为以npm_config_

{
  npm_config_send_metrics: '',
  npm_config_save_bundle: '',
  npm_config_umask: '0022',
  npm_config_node_options: '',
  npm_config_init_version: '1.0.0',
  npm_config_init_author_name: '',
  npm_config_git: 'git',
  ....
}

1
2
3
4
5
6
7
8
9
10
11

node 处理 scripts 中的参数,除了属性后面的第一个命令,以空格分割的任何字符串(除特别shell语法)都是参数,并且都能通过 process.argv 属性访问。process.argv 属性返回一个数组,数组包含了启动 node 进程时的命令行参数。第一个元素为启动 node 进程的可执行文件的绝对路径名 process.execPath,第二个元素为当前执行的 jacascript 文件路径。剩余的元素为其他命令行参数。

"scripts":{
  "serve": "vue-cli-service serve --mode=dev --mobile -config build/example.js"
}
执行
npm run serve

打印 process.argv 为:
[ '/usr/local/Cellar/node/12.14.1/bin/node',
  '/Users/mac/Vue-projects/hao-cli/node_modules/.bin/vue-cli-service',
  'serve',
  '--mode=dev',
  '--mobile',
  '-config',
  'build/example.js']

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

再列举几个传参可能有的方式

npm run serve --params  // 参数params将转化成process.env.npm_config_params = true
npm run serve --params=123 // 参数params将转化成process.env.npm_config_params = 123
npm run serve -params  // 等同于--params参数

npm run serve -- --params  // 将--params参数添加到process.env.argv数组中
npm run serve params  // 将params参数添加到process.env.argv数组中
npm run serve -- params  // 将params参数添加到process.env.argv数组中
1
2
3
4
5
6
7

# 执行顺序

 npm run script1.js & npm run script2.js 并行任务(同时的平行执行),使用&符号
 npm run script1.js && npm run script2.js 串行任务(前一个任务成功,才执行下一个任务),使用 && 符号

1
2
3

# npm config

npm cli 提供了 npm config 命令进行 npm 相关配置,通过 npm config ls -l 可查看 npm 的所有配置,包括默认配置。npm 文档页为每个配置项提供了详细的说明 https://docs.npmjs.com/misc/config . 修改配置的命令为 npm config set, 我们使用相关的常见重要配置:

npm config set registry https://registry.npm.taobao.org
npm config set registry https://registry.npmjs.org
npm config ls
1
2
3

# npmrc 文件

除了使用 CLI 的 npm config 命令显示更改 npm 配置,还可以通过 npmrc 文件直接修改配置。 这样的 npmrc 文件优先级由高到低包括:

  • 工程内配置文件: /path/to/my/project/.npmrc
  • 用户级配置文件: ~/.npmrc
  • 全局配置文件: $PREFIX/etc/npmrc (即npm config get globalconfig 输出的路径)
  • npm内置配置文件:/path/to/npm/npmrc

# npm 包发布

# 规范的 npm 模块目录

一个 node.js 模块是基于 CommonJS 模块化规范实现的,严格按照 CommonJS 规范,模块目录下除了必须包含包描述文件 package.json 以外,还需要包含以下目录:

  • bin:存放可执行二进制文件的目录
  • lib:存放js代码的目录
  • doc:存放文档的目录
  • test:存放单元测试用例代码的目录

# 如何写好一个模块的 README 文件 (opens new window)

# 如何发布自己的 npm 包

  1. 先去 npm 注册个账号,然后在命令行使用,然后npm adduser #根据提示输入用户名密码即可
  2. 使用命令发布你的包,在推送之前,可以通过配置一个 .npmignore 文件来排除一些文件, 防止大量的垃圾文件推送到 npm, 规则上和你用的 .gitignore 是一样的。.gitignore 文件也可以充当 .npmignore 文件
  3. 发布成功之后,你就可以像下载安装其他包一样使用你自己的开发工具了

# 关于 npm 包的更新

更新 npm 包也是使用 npm publish 命令发布,不过必须更改 npm 包的版本号,即 package.json 的 version 字段,否则会报错,同时我们应该遵 Semver(语义化版本号) 规范,npm 提供了 npm version 给我们升级版本

# 升级补丁版本号
$ npm version patch

# 升级小版本号
$ npm version minor

# 升级大版本号
$ npm version major
1
2
3
4
5
6
7
8

# 本地开发的 npm 包如何调试

在本地开发的模块包的时候,可以使用 npm link 调试,将模块链接到对应的运行项目中去,方便地对模块进行调试和测试。具体使用步骤如下

  1. 假如我的项目是 koalaNpmStudy,假如我的 npm 模块包名称是 npm-ikoala
  2. 进入到 模块包 npm-ikoala 目录中,执行 npm link
  3. 在自己的项目 koalaNpmStudy 中创建连接执行 npm link npm-ikoala
  4. 在自己项目的 node_module 中会看到链接过来的模块包,然后就可以像使用其他的模块包一样使用它了。
  5. 调试结束后可以使用 npm unlink 取消关联

npm link 主要做了两件事:

为目标 npm 模块创建软链接,将其链接到全局 node 模块安装路径 /usr/local/lib/node_modules/。

为目标 npm 模块的可执行 bin 文件创建软链接,将其链接到全局 node 命令安装路径 /usr/local/bin/。