Zijue/blog

5.npm 的使用

Zijue opened this issue · 0 comments

Zijue commented

文件模块解析流程

文件目录树如下所示:

.
├── test.js
├── zijue
│   └── index.js
└── zijue.js
// zijue.js
module.exports = 'zijue file'

// zijue/index.js
module.exports = 'zijue package index'

// test.js
const r = require('./zijue');
console.log(r);  // > zijue file

默认会先找文件(如 .js .json),找不到就会找对应的文件夹(zijue 文件夹)下的 index.js 文件。

删除 zijue.js 文件,并在 zijue 文件夹中添加 a.jspackage.json (表示包的描述信息)。文件结构如下:

.
├── test.js
└── zijue
    ├── a.js
    ├── index.js
    └── package.json
// zijue/package.json 
{
    "main": "a.js"
}

// zijue/a.js
module.exports = 'zijue package a'

// test.js
const r = require('./zijue');
console.log(r);  // > zijue package a

默认应该寻找 zijue/index.js 文件,当添加了 zijue/package.json 文件中的 main 属性之后,优先去查找了 a.js 文件。因为 main 的优先级更高

如果引入的模块没有 ./ 或者 ../ 或者绝对路径,会认为此模块是一个第三方模块或者核心模块

第三方模块

  • 第三方模块区分为全局本地
  • 本地代码中第三方模块都会安装到 node_modules 文件夹中
  • 第三方模块查找会根据 module.paths 不停的向上查找,直到找到为止
// module.paths
[
  '/Users/chisinong/Documents/zf/learn_code/my_lesson/node_modules',
  '/Users/chisinong/Documents/zf/learn_code/node_modules',
  '/Users/chisinong/Documents/zf/node_modules',
  '/Users/chisinong/Documents/node_modules',
  '/Users/chisinong/node_modules',
  '/Users/node_modules',
  '/node_modules'
]

全局第三方模块

全局第三方模块就是安装的时候带参数 -g;且全局安装的第三方模块可以在命令行中使用

我们以 nrm 模块为例演示(nrm 模块可以帮助我们快速且方便的切换 node 的源)

  • 全局安装 nrm 模块
$ npm install -g nrm
  • nrm 模块的简单使用
// 查看 node 源
$ nrm ls

* npm -----  https://registry.npmjs.org/
  yarn ----- https://registry.yarnpkg.com
  cnpm ----  http://r.cnpmjs.org/
  taobao --  https://registry.npm.taobao.org/
  nj ------  https://registry.nodejitsu.com/
  skimdb -- https://skimdb.npmjs.com/registry

// 切换 node 源
$ nrm use taobao

Registry has been set to: https://registry.npm.taobao.org/

全局安装的第三方模块为什么可以在命令行中使用?

  • 查看系统环境变量 $PATH
$ echo $PATH

/Users/chisinong/.nvm/versions/node/v12.14.1/bin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/usr/local/go/bin:/Applications/Wireshark.app/Contents/MacOS

可以看到我使用的 node v12.14.1 的 bin 目录被添加到了系统环境 $PATH 中,那么 /Users/chisinong/.nvm/versions/node/v12.14.1/bin 下的所有可执行文件均可在命令行中执行

  • 查看 bin 目录下的内容
-rwxr-xr-x  1 chisinong  staff    40M  1  7  2020 node
lrwxr-xr-x  1 chisinong  staff    38B 10 19 16:59 npm -> ../lib/node_modules/npm/bin/npm-cli.js
lrwxr-xr-x  1 chisinong  staff    40B 10 19 16:41 npm-check -> ../lib/node_modules/npm-check/bin/cli.js
lrwxr-xr-x  1 chisinong  staff    46B 10 19 16:57 npm-upgrade -> ../lib/node_modules/npm-upgrade/lib/bin/cli.js
lrwxr-xr-x  1 chisinong  staff    38B 10 19 16:59 npx -> ../lib/node_modules/npm/bin/npx-cli.js
lrwxr-xr-x  1 chisinong  staff    30B 11 29 16:15 nrm -> ../lib/node_modules/nrm/cli.js

可以看到该目录下 nrm 软连接到具体的可执行文件中,相当于在命令行中执行 nrm 命令,其实是在执行 node_modules/nrm/cli.js 脚本

// cli.js 的行首
#!/usr/bin/env node

表明该文件是一个使用 node 环境的可执行脚本

  • 在命令行中使用 nrm 最终就是执行 /xx/node_modules/nrm/cli.js 路径下的 cli.js 脚本
命令行 nrm ->$PATH 中查找对应的可执行脚本 -> /Users/chisinong/.nvm/versions/node/v12.14.1/bin/nrm -> /Users/chisinong/.nvm/versions/node/v12.14.1/lib/node_modules/nrm/cli.js

如何发布自己的全局包

  • 本地模块初始化 npm init 生成 package.json 文件
$ npm init   

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (my_lesson) 
version: (1.0.0) 
description: 练习项目
entry point: (zijue.js) 
test command: 
git repository: 
keywords: 
author: zijue
license: (ISC) MIT
About to write to /Users/chisinong/Documents/xx/learn_code/my_lesson/package.json:

{
  "name": "my_lesson",
  "version": "1.0.0",
  "description": "练习项目",
  "main": "zijue.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "zijue",
  "license": "MIT"
}


Is this OK? (yes) yes
// package.json
{
  "name": "my_lesson",
  "version": "1.0.0",
  "description": "练习项目",
  "main": "zijue.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "zijue",
  "license": "MIT"
}
  • package.json 中添加 bin 命令
{
  "name": "my_lesson",
  "version": "1.0.0",
  // 此配置在全局安装包时,命令行输入 zijue 命令对应会执行 ./bin/www 文件
  "bin": {
    "zijue": "./bin/www"
  },
  "description": "练习项目",
  "main": "zijue.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "zijue",
  "license": "MIT"
}

./bin/www 需要增加 #!/usr/bin/env node 可执行环境

  • 使用 npm link 命令暂时将本地代码连接到全局下,用于测试
$ npm link

npm WARN my_lesson@1.0.0 No repository field.

up to date in 0.231s
/Users/chisinong/.nvm/versions/node/v12.14.1/bin/zijue -> /Users/chisinong/.nvm/versions/node/v12.14.1/lib/node_modules/my_lesson/bin/www
/Users/chisinong/.nvm/versions/node/v12.14.1/lib/node_modules/my_lesson -> /Users/chisinong/Documents/xx/learn_code/my_lesson
#!/usr/bin/env node

console.log('zijue');
$ zijue

zijue  // 通过 npm link 命令,可以在命令行中执行 zijue 命令,实际连接到 ./bin/www 可执行文件
  • 需要切换到官方 npm 源下
nrm use npm
  • 登录 npm 账户
// 有 npm 账户
npm login

// 无 npm 账户,可以通过 npmjs.com 网站注册,或下面命令
npm addUser
  • 发布包,发布前添加 .npmignore 文件剔除不需要发包的文件
npm publish  // 发包命令
npm install  // 包发布之后,就可以使用 npm 命令在任意位置安装
// 如果升级包,需要更新包的版本号,且 24 小时内不能重新发布

本地第三方模块

本地第三方模块表示在项目中使用,命令行中使用就用全局第三方模块。

如果像 webpack 这样的模块一般放项目依赖中使用,npm install webpack -D

  • --save-dev(-D) 表示该模块只在开发时使用
  • --save(-s 或者不写) 表示该模块开发上线时都需要

依赖分为:开发依赖、项目依赖、同版本依赖、捆绑依赖(打包依赖 npm pack)、可选依赖

版本问题:

  • ^^2.0.0 2 版本以上,3 版本以下
  • ~~1.2.0 1.2 版本及以上,但必须低于 1.3 版本

package.json 中的 scripts 字段

  ...
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  ...

npm run 命令时会将当前文件夹 node_modules 下的 .bin 目录暂时添加到环境变量 PATH 中,所以可以运行 scripts 下定义的非全局的本地模块

npx 直接运行 node_modules/.bin 文件夹下的命令;若运行的命令没有,则较 npm run 多了一个下载功能,用完及删除

核心模块 不需要安装