再也不让 npm 成为面试绊脚石了

前言

Hello 你们好!我是壹甲壹!html

对于日常只会用到简单的 npm 命令的我来讲,面试的时候就被考官按在地上摩擦过前端

  • 请问 package.json 中版本 ~1.2.3^1.2.3 有什么区别?
  • 请问执行 npm install 时,是怎么安装依赖包的?相同的依赖包怎么处理?

面试结果可想而知,因而便有了这篇文章,好好总结下 npm 相关的知识啦node

1、npm 安装

当咱们在安装 node 后,npm 也会一块儿安装好,此时须要另外两个包来协助开发react

  • nvm 管理 node 版本
  • nrm 管理 npm 的源,国内通常都使用 taobaocnpm

详细安装信息,请参考 Node.js的3m安装法jquery

2、npm 命令

2.1 npm init

npm init 命令用来初始化项目webpack

  • 直接执行 npm init,  会依次询问 name, version, description 等配置信息,比较麻烦
  • 添加 --yes-y 后缀,直接生成 package.json 文件,配置信息使用默认值 ( 默认值在 npm config 中定义), 可手动修改

对于每一个项目而言,例如 author.name , author.email 都是固定的,能够给这些字段设置默认值git

// 查看全部配置信息
npm config list --json  // 设置默认值 npm config set init.author.name "userName" npm config set init.author.email "userEmail" 复制代码

接下来,执行 npm init -y, 生成的  package.json 文件以下github

{
 "name": "pkg-a",  "version": "1.0.0",  "description": "",  "scripts": {  "test": "echo \"Error: no test specified\" && exit 1"  },  "keywords": [],  "author": "userName <userEmail>",  "license": "ISC" } 复制代码

2.2 npm install

npm install  命令用来全局安装或本地安装第三方的依赖。npm install 简写为 npm iweb

2.2.1 global

npm i create-react-app -g  会进行全局安装,安装成功后,可在终端任何地方使用 create-react-app 命令。面试

  • 全局安装路径

执行 npm root -g 输出全局安装路径为

/Users/xxx/.nvm/versions/node/v14.2.0/lib/node_modules
复制代码

(Tip: 此时能够看出 nvm 管理node 版本时,每一个版本都有对于的 node_modules )

  • 全局使用

之因此可以全局使用,是由于将 xxx/v14.2.0/lib/node_modules 目录下每一个依赖的可执行文件软连接 到 xxx/v14.2.0/bin 目录下。

每一个依赖包的可执行文件在其 package.json 文件中的 bin  字段指定

{
 "name": "create-react-app",  "bin": {  "create-react-app": "index.js"  } } 复制代码

那么,在  xxx/v14.2.0/bin 目录就会建立  create-react-app 命令,在执行该命令时,就是在执行 index.js 文件

2.2.2 local

npm i moment --save 会在当前项目进行安装,安装成功后,须要在项目中引入后,才能使用

依赖来源

npm i 默认会从 npm registry 上去下载依赖的模块 (使用 nrm 切换),除此以外,还有哪些安装途径呢?

  • from  folder 能够从本地的文件夹中安装 pkg。本地建立 pkg-a 文件夹,并经过 npm init -y 进行初始化,接下来执行 npm i ~/pkg-a 就能够安装了,成功以后 pkg-a的值为相对连接的 file 协议地址
npm_install_floder.png
npm_install_floder.png
  • from tarball 对于👆的本地模块 pkg-a,  执行 npm pack 命令就可对其打包了 截屏2020-07-09下午9.38.12.png 接下来,就能够执行   npm i ~/pkg-a/pkg-a-1.0.0.tgz 安装模块了,安装成功后 pkg-a的值为相对连接的 file 协议地址 npm_install_tgz.png

npm install tarball 比较适合离线安装包或者包不想发布的 npm 源上,但须要手动维护

  • from http(s) url 前面介绍的是本地包,对于已经发布的依赖,例如 react,使用 npm view react 能够查看最新版本的 react 压缩包地址

截屏2020-07-09下午5.39.22.png     此时能够直接使用  npm install [https://r.cnpmjs.org/react/download/react-16.13.1.tgz](https://r.cnpmjs.org/react/download/react-16.13.1.tgz)     来安装 react。安装完成后,在 package.jsonreact 值为 https 地址 npm_install_tgz_url.png npm install http(s) 比较适合不想发布的 npm 源上,但须要别人也能安装

  • from git

咱们还能够从 git 上安装,还以 react为例,执行 npm i [https://github.com/facebook/react.git](https://github.com/facebook/react.git) 来安装 npm_install_git.png 以上就是其它的几种 npm install  方式,在平常开发中仍是推荐从 npm 源上面安装依赖

依赖分类

对于不一样的依赖功能不一样,常见会将依赖分红 开发环境依赖 和 生产环境依赖,例如 babel 属于开发依赖,而react 就属于生产依赖了。在 npm install 时能够添加不一样的后缀来区分依赖,--save (-S) 表示生产依赖,下载的依赖会保存到 package.jsondependencies 字段中,而 --save-dev (-D) 表示开发依赖,会保存到 devDependencies 字段中。

npm 5 中,不添加后缀,下载的依赖默认会保存到 dependencies

除去 -S -D后缀,npm install 还存在如下后缀

  • -P: --save-prod , 当保存到 dependencies字段中, 当不存在 -D-O时, -P就是默认值
  • -O: --save-optional , 保存到 optionalDependencies字段中
  • --no-save, 将不会进行保存
  • -B: --save-bundle , 不只保存到 dependencies字段,还会保存到 bundleDependencies 列表中 (可选)
  • -E: --save-exact , 不只保存到 dependencies字段,还会锁定 pkg 的准确版本,而不是使用一个范围 不加 -E,版本 ^16.13.1 是一个范围,表示的是   >=16.13.1 < 17.0.0 这个范围 npm_install_react.png 加上 -E , 就会锁定 react 的版本 code1.png

(Tips: 关于 dependencies 这些字段,以及 ^16.13.1表示的具体版本范围,后续 package.json 中会讲解)

安装位置

本地安装是,全部的依赖都会放到 ./node_module/ 文件夹下面,同时每一个依赖的可执行文件都会软连接到 ./node_module/bin/ 目录下,这样就能够在 package.json  中设置 script 时使用到这些命令,如 code.png

2.2.3 How to Work?

当仅执行 npm install 时,npm 会根据 package.json 来安装项目依赖,究竟是如何工做的呢? 这部分请参考 npm install 如何工做 - node_modules 目录结构 总结以下,若想实践,可经过下面 Tips来切换 npm 版本

  • **npm 2 ** 递归安装依赖

缺点:重复安装相同版本的依赖包       Tips: 执行 nvm install 4.2.0 后,node 版本 4.2.0npm 版本 2.14.7

  • npm 3 扁平化管理, 在安装时遍历整个依赖树,计算出最合理的文件夹安装方式, 避免重复安装

Tips: 执行 nvm install 6.9.0 后,node 版本 6.9.0npm 版本 3.10.8

  • npm 5

增长 package.json 文件, 锁定依赖版本,确保任何环境运行 npm install 获得相同的 node_modules 结            构。禁用命令 npm config set package-lock false

2.3 npm view(info)

npm view(info) xxx ,查看包 xxx 的一些信息,最新稳定版本,在线压缩包地址,依赖等信息。

2.4 npm home(docs)

npm home(docs) xxx ,都会打开在线 github 地址,前提须要在包 xxx 的 package.json 文件中设置 homepage 字段

2.5 npm repo(bugs)

npm repo(bugs) xxx, 跳转到对应的 github repo页面,前言也是须要配置

2.6 npm ls

显示依赖 tree

3、package.json

一个项目的所有信息都在 package.json 文件中了,具体看下有哪些属性吧

3.1 必备属性

若是该项目打包发布到 npm 源上,那么 name 和 version 两个字段是必须的

3.2 version

版本号必须可以被 node-semver 正确解析。

3.2.1 版本号

标准版本号格式为: X.Y.Z , 有下面几点说明

  • X.Y.Z  均为非负整数,X: 主版本号、Y:此版本号、Z:修订号。每一个元素依次递增
  • 任何修改都要用新的版本号发布
  • 当 X 为 0 时(0.y.z),此时属于开发初期,任务公共API 均可能改变,属于非稳按期。1.0.0 用于界定公共 API 的造成
  • 修改 Z,   必须在作了向下兼容的修正时才递增,例如 修复 bug
  • 修改 Y,   必须在有向下兼容的新功能时才递增,当 Y 修改后,Z 必须归 0
  • 修改 X,   必须在有任何不兼容的修改被加入公共 API 时递增,当 X 修改后, Y, Z 必须归  0

**

3.2.2 预发版本号

eg: 2.1.0-beta.1

  • alpha(α):预览版,或者叫内部测试版
  • beta(β):测试版,或者叫公开测试版
  • rc(release candidate):最终测试版本

预发版本代表当前版本并不是稳定,可能不符合要求。

3.2.3 版本号优先级

版本优先级也就是指版本的高低

  • 首先记住 2.1.0-beta 的优先级低于 2.1.0 ,先有预发,再有稳定;
  • 对于正常版本格式 X.Y.Z ,都是数值,比较每一位大小就OK;
  • 而对于预发版本,有数字比数值大小,非数字比较每一个字符的 ASCII 大小;

因此: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0

3.2.4 范围版本号

(1)运算符:> , >=, <, <=
  • 正常: >= 1.2.7 , 那么匹配的版本能够是 1.2.71.2.83.4.2
  • 预发: >1.2.3-alpha.3,那么匹配的版本的 X.Y.Z 必须是 1.2.3
(2)字符范围:X.Y.Z  -  A.B.C
  • 1.2.3 - 2.3.4 , 那么匹配的版本范围是 >=1.2.3 <=2.3.4
  • 1.2 - 2.3.4,第一个版本缺失,会进行补零,因此匹配的版本范围是 >=1.2.0 <=2.3.4
  • 1.2.3 - 2.3,第二个版本缺失,会要求匹配的版本的 X.Y 两位不得大于 2.3,也就是 < 2.4.0, 因此版本范围是 >=1.2.3 <2.4.0,
(3)X-Range: 1.2.X , 1.2.x, 1.2.*
  • * , 匹配任意版本,也就是 >= 0.0.0
  • 1.2.x ,匹配的版本 X.Y 两位不变,因此版本范围是 >=1.2.0 < 1.3.0
  • 1.x ,匹配的版本 X 位不变,因此版本范围是 >=1.0.0 < 2.0.0
(4)Tilde Ranges : ~

若是Y被指定,则容许Z被改变;若是没有,容许Y被改变

  • ~1.2.3 , Y 被指定为 2, 那么匹配的范围为 >=1.2.3 <1.3.0
  • ~1.2, Y 被指定为 2, 那么匹配的范围为 >=1.2.0 <1.3.0
  • ~1, 没有指定 Y, 那么 Y 能够被改变,匹配的范围为 >1.0.0 <2.0.0
(5)Garet Range: ^

匹配的版本,会保证最左边的第一个非 0 位不修改

  • ^1.2.3, 最左边非 0 位为 X 位,因此匹配的范围为 >=1.2.3 <2.0.0
  • ^0.2.3, 最左边非 0 位为 Y 位,因此匹配的范围为 >=0.2.3 <0.3.0
  • ^1.2.x , 当版本缺失,缺失位会降到 0 ,因此匹配的范围位 >=1.2.0 <2.0.0

3.3 dependency

3.3.1 dependencies

生产环境依赖,对应 npm install 时后缀 -S

3.3.2 devDependencies

开发环境依赖,对应 npm install 时后缀 -D

3.3.3 peerDependencies

同等依赖,若是安装了依赖包 pkg-a, 最好也安装下 pkg-a 对应的依赖

// pkg-a package.json
{  "peerDependencies": {  "jquery": "2.2.0"  } } 复制代码

上面表示 pkg-a 的运行依赖于 jquery,因此当 npm install pkg-a 时,控制台会提示如下信息 截屏2020-07-10下午2.03.39.png 在 npm 2.x 版本时,peerDependencies 会被强制安装,3.0 版本后不被强制安装

3.3.4 bundleDependencies

捆绑依赖, 也叫 bundledDependencies,属性值是个数组

// pkg-a package.json
{  "bundledDependencies": [  "moment"  ] } 复制代码

npm pack 时会将捆绑依赖一同打包,在安装 tgz 压缩包时,捆绑依赖也会被安装。但注意捆绑依赖并无指定版本号

3.3.5 optionalDependencies

可选依赖,属性值为对象。当项目依赖 pkg A, 但 pkgA 安装失败或者找不到并不会影响项目的运行,就能够在 optionalDe.... 中指定 pkgA 了

3.4 homepage

指定项目主页,设置后可经过 npm docs(info) xxx 打开

3.5 bugs

指定项目 issues 页面, 设置后经过 npm bugs xxx 可打开

3.6 license

截屏2020-07-10下午2.21.26.png
截屏2020-07-10下午2.21.26.png

3.7 main

指定项目入口文件,当 require(xxx) 时,返回的就是入口文件导出的内容

3.8 bin

当 pkg 中的可执行文件须要安装到 PATH 中,可在 bin 中指定。以 http-server 为例

"bin": {
 "http-server": "./bin/http-server",  "hs": "./bin/http-server" } 复制代码

http-server 全局安装,会将执行文件软链接到 xxx/node/v14.2.0/bin/http-server 中,本地安装就会连接到 ./node_module/bin/http-server  中。 可执行文件须要在文件顶部增长 #!/usr/bin/env node  指定 node 执行

3.9 config

设置 config 可经过 npm_package_config_xxx 来获取,但同名变量会被本地 npm config 所覆盖

3.10 script

这部分请参考 阮一峰 npm scripts 使用指南

4、npx

npx 命令是 npm v5.2 以后引入的新命令,npx 能够帮咱们直接执行 node_modules/.bin文件夹下的文件

  • 执行脚本
npx webpack
复制代码

这样就省略了配置scripts脚本

  • 避免安装全局模块

全局安装的模块会带来不少问题,例如:多个用户全局安装的模块版本不一样

npx create-react-app react-project
复制代码

咱们能够直接使用 npx 来执行模块,它会先进行安装,安装执行后会将下载过的模块删除,这样能够一直使 最新版本

5、npm 发布

npm 包的发布比较简单

  • 首先使用 nrm 切换到 npm 官方源
  • 使用 npm login 进行登陆(提早注册)
  • npm publish (确保 name 是惟一值)
  • 对于不想打包的可在 .npmignore 文件中进行忽略

6、参考连接

本文使用 mdnice 排版

相关文章
相关标签/搜索