包管理器

概述

模块(module)

模块通常以单个文件的形式存在,一个模块只包含一部分功能,在页面中引入的模块或使用node命令运行的模块称之为入口模块或主模块

库(library)

库是由若干个模块组成的完整功能块,库可以帮助解决开发中遇到的某一方面的问题

如:jquery让操作DOM更加方便,axios使得网络传输更加简单,mockjs用于进行ajax拦截和模拟数据生成

包(package)

库(一个或多个js文件) + 相关描述信息(元数据) = 包

元数据包括:库的名称、库的描述、库的作者信息等

registry

registry是一个服务器,用于保存编写好的第三方库

第三方库的作者,按照npm的规范编写完库后,就会将其传到npm的registry服务器中

CLI

CLI(command-line interface)命令行接口

该接口提供了一系列的命令,调用这些命令即可获取到系统提供的某些服务

如:在命令行中输入命令npm -v,即可查看系统中npm的版本信息

npm

包的安装

npm官方的registry服务器位于国外,因此使用该服务器下载包,速度很慢

可以将npm的registry服务器地址修改为国内的镜像服务器地址

bash 复制代码
 npm config set registry https://registry.npm.taobao.org

可以通过下面的命令来查看是否设置完成

bash 复制代码
 npm config get registry

npm安装包的方式分为两种:

  1. 本地安装
  2. 全局安装

本地安装

使用下面命令进行本地安装

bash 复制代码
 npm install 包名

install可以简写为i

bash 复制代码
 npm i 包名

同时下载多个包

bash 复制代码
 npm i 包名1 包名2 ...

本地安装的包会出现在当前目录下的node_modules目录中

注意:

  1. node_modules目录中的内容不适合传输到生产环境中,因此应该在.gitignore文件中忽略该目录

  2. 本地安装的包只会影响当前目录以及当前目录的子目录,不会对当前目录以外的目录造成影响

  3. npm在安装包(包括本地安装和全局安装)时,若安装的包依赖了其它包,则npm也会自动将这些依赖的包也下载下来,即npm能够自动管理包依赖

  4. 若本地安装的包中带有CLI文件,npm会将该CLI文件放置到node_modules/.bin目录中,使用该CLI中的命令时,需要命令的最前面加上npx

    全局安装的包提供的CLI,其中的命令可以在任何目录中调用

  5. 若npx所执行的本地命令目前还不存在,则npm会临时本地安装该命令所属的包,然后再执行该命令,执行完后立即删除该包

全局安装

使用下面命令进行全局安装

bash 复制代码
 npm i --global 包名

--global可以简写为-g

bash 复制代码
 npm i -g 包名

全局安装的包会出现在特定的目录中

可以通过下面命令查看全局安装的包所在的目录

bash 复制代码
 npm config get prefix

默认情况下,该目录为C:\Users\...\AppData\Roaming\npm

全局安装包的目的通常是为了使用包所提供的CLI命令,如vue-cli,以便为之后的开发做准备,而不是为每一个工程提供可以共同执行的代码

包配置

任何一个包,它的信息都会记录配置文件package.json

我们开发的工程本身也应该是一个包,因此也需要有相应的package.json

可以手动创建该文件,也可以通过在工程的根目录下运行下面命令来初始化package.json

bash 复制代码
npm init

package.json中记录的信息有:

  1. name

    包的名称,该名称只能包含英文字符、数字和-

  2. version

    包的版本信息,默认为1.0.0

    版本号规范:主版本号.次版本号.补丁版本号

    主版本号:当程序发生了重大变化时,主版本号增加,重大变化包括大量新特性的加入,技术架构的改变等

    此版本号:当程序发生了细微变化时,此版本号增加,细微变化包括加入了一些辅助型的API等

    补丁版本号:当解决了程序中的一些bug,或进行了一些局部优化时,补丁版本号增加

    有些版本号在后面还可能会跟上一些补充信息,如-alpha-beta-rc

    其中-alpha-beta都表示不太成熟的当前版本,-rc表示较为成熟的当前版本,如果什么都不加,表示当前版本已经非常成熟,实际使用时也最应该使用这种版本号的版本

  3. description

    包的描述信息

  4. homepage

    官网地址

  5. repository

    包的仓库地址,通常为包在git或svn中的地址

  6. main

    包的入口文件,默认为index.js

    使用该包的人默认从该入口文件导入包的内容

  7. keywords

    搜索关键字

    当包发布到npm上后,需要通过该关键字来搜索到此包的内容

  8. author

    包的作者信息

上面的配置信息,只有在需要将包发布到npm上时才有用,而使用npm init初始化配置文件时,就需要手动输入上面的信息

如果不需要将包发布出去,那么也就不需要填写上面的信息,此时可以使用下面的命令来让npm生成只包含默认配置的package.json

bash 复制代码
npm init --yes

--yes可以简写为-y

bash 复制代码
npm init -y
配置依赖关系

package.json中还有两个非常重要的配置:dependencies和devDependencies,这两个配置用于记录当前工程的依赖关系

依赖包括:

  • 生产环境依赖,即dependencies

    生产环境依赖是指在开发过程中,以及开发完成后都需要使用到的依赖

    生产环境依赖也称为普通依赖

  • 开发环境依赖,即devDependencies

    开发环境依赖是指仅在开发过程中需要使用到的依赖

json 复制代码
{
    "name": "",
    "version": "",
    "dependencies": {
    	"jquery": "1.1.1",
    	"axios": "1.2.3"
	},
	"devDependencies": {
        "mocha": "2.3.4"
    }
}

当配置好工程的依赖关系后,可以在与package.json的同级目录命令行下使用下面的命令来为工程安装所有的依赖(包括生成环境依赖和开发环境依赖)

bash 复制代码
npm i

使用下面的命令来安装所有的生产环境依赖

bash 复制代码
npm i --production

当使用命令npm install 包名安装本地包时,会自动将对该包的依赖记录到package.json的dependencies配置中

在旧版本的npm中,安装生产环境依赖时默认是不会往package.json中自动加入依赖关系,需要加入--save-S参数才能将依赖记录进去

css 复制代码
npm i -S 包名

若想把安装的本地包作为开发依赖保存到package.json中,应该使用下面命令

bash 复制代码
npm i --save-dev 包名

--save-dev可以简写为-D

bash 复制代码
npm i -D 包名

其实对于普通的前端开发者而言,开发依赖和普通依赖并没有什么区别,因为无论是开发依赖还是普通依赖,只要是在模块中导入的依赖,模块中的代码经过webpack打包过后都会加入到打包结果中

但对于要发布包给别人使用的作者来说,他们才需要关心一个库应该是普通依赖还是开发依赖

node查找包的顺序

require函数中的路径如果不以./../开头,而直接书写包的名称时,nodejs就会按照下面的顺序查找包:

js 复制代码
require("lodash")
  1. 查找是否有内置模块lodash
  2. 如果没有内置模块lodash,则查找模块所在当前目录下的node_modules目录中是否有lodash.js文件
  3. 若没有lodash.js文件,则查找模块所在当前目录下的node_modules目录中是否存在lodash目录,并查找该目录中是否有相应的入口文件
  4. 若没有lodash目录,或有lodash目录但没有相应的入口文件,则返回上一级目录,然后对该目录重复2和3两个步骤,直至查找磁盘的根目录
  5. 若最终都没有找到该模块,nodejs就会抛出Cannot find module 'lodash'错误
入口文件

包的入口文件信息一般都会记录在包的package.json中,其中的main配置就是入口文件的名称

若没有package.json,或package.json中没有记录main配置,或没有与main配置相对应的文件,则默认使用index.js作为包的入口文件

main字段中填写的是入口文件相对于包的根目录的路径

语义版本

版本号规范:主版本号.次版本号.补丁版本号

主版本号:当程序发生了重大变化时,主版本号增加,重大变化包括大量新特性的加入,技术架构的改变等

次版本号:当程序发生了细微变化时,此版本号增加,细微变化包括加入了一些辅助型的API等

补丁版本号:当解决了程序中的一些bug,或进行了一些局部优化时,补丁版本号增加

当一个包的主版本号发生变化时,说明该包一定是发生了重大的变化,这很有可能会造成一些兼容性问题,而次版本号或补丁版本号更新一般不会造成兼容性问题

因此当使用一个其它包时,往往都选择主版本号固定的版本,而允许次版本号和补丁版本号进行变化

可以通过配置package.json来达到此目的:

符号 描述 示例 示例描述
固定某个版本 1.2.1 固定为1.2.1版本
大于某个版本 >1.2.1 大于1.2.1版本
>= 大于等于某个版本 >=1.2.1 大于等于1.2.1版本
< 小于某个版本 <1.2.1 小于1.2.1版本
<= 小于等于某个版本 <=1.2.1 小于等于1.2.1版本
- 介于两个版本之间 1.2.1 - 1.4.5 介于1.2.1和1.4.5版本之间
x 不固定版本号 1.3.x 保证主版本号为1,次版本号为3
~ 补丁版本号可增 ~1.3.4 保证主版本号为1,次版本号为3,补丁版本号大于等于4
~ 次版本号和补丁版本号可增 ^1.3.4 保证主版本号为1,次版本号大于等于3,补丁版本号大于等于4
* 最新版本 * 始终安装最新版本,等价于latest

例:

json 复制代码
{
    "dependencies": {
        "qrcode": "^1.4.4"
    },
    "devDenpendencies": {
        "webpack": "~5.0.0" 
    }
}

由于包与包之间的依赖关系十分复杂,就使得工程所依赖的某个包只是进行了小小的更新,仍然可能导致整个工程无法使用

因此在使用npm安装包时,它会自动生成一个package-lock.json文件,该文件中会自动记录工程的所有的依赖以及依赖的具体版本号

当工程被移植到了其它地方时,则在还原依赖的过程中如果发现工程中包含package-lock.json,会根据该文件中记录的确切版本的依赖关系进行包的安装,这能最大限度地避免差异

npm的差异版本处理

默认情况下,工程所依赖的包,以及该包所依赖的其它包,都会处于同一层级的目录中,这称之为依赖拍扁(flat dependency)

但如果遇到了两个包,这两个包所依赖的是不同版本的同一个包,则npm会将不同版本的包作为需要依赖的包的子包存在,而不会与其处在同一层级

css 复制代码
├── node_modules
│   ├── a 
│   │   ├── node_modules
│   │   │   ├── c 1.4.0
│   │   │   |   |------ c包的文件
│   │   │── a包的文件     
│   ├── b 
│   │   ├── node_modules
│   │   │   ├── c 1.2.3
│   │   │   |   |------ c包的文件
│   │   │── b包的文件           

npm脚本

才工程的开发过程中通常需要使用到各种各样的命令,而记忆这些命令往往是非常耗时的

npm考虑到了这一点,它允许开发者自己配置命令,并使这些自定义的命令与第三方库提供的命令相关联,今后就可以通过调用自定义配置的命令来间接调用库命令

在package.json中,可以加入scripts配置,在该配置中就可以让自定义命令与库命令相关联

json 复制代码
{
    "scripts": {
        "start": "node ./index.js"
        // start为自定义命令的名称,调用该自定义命令就相当于在该package.json所在的目录下调用node ./index.js
    }
}

通过下面的方式调用自定义命令

bash 复制代码
npm run start
细节
  1. scripts配置中的相对路径,是相对于该package.json的路径

  2. npm对一些常见的自定义命令名称进行了简化,下面的自定义命令名称在调用时可以不加run

    ① start

    ② stop

    ③ test

    bash 复制代码
    npm start
  3. 在scripts配置中所关联的本地第三方库命令,可以省略npx

  4. 若没有加入scripts配置,或scripts配置中没有书写start自定义命令,则start默认为node server.js

运行环境配置

我们编写的代码可能会在许多种不同的环境下运行:

  1. 开发环境
  2. 生产环境
  3. 测试环境

而针对不同的环境,可能要进行不同的处理

而在代码中应该如何判断当前所处的环境呢,就需要使用到操作系统的环境变量信息

在nodejs中,可以使用process.env来获取到系统的所有环境变量

通过读取process.env中的某个环境变量,就可以判断当前环境的哪个环境

而运行环境变化时,也只需要将该环境变量进行修改即可

比如:设置一个环境变量NODE_ENV来记录当前代码的运行环境,使用development来表示开发环境,使用production来表示生产环境,使用test来表示测试环境

而在代码中,只需要进行下面的判断即可

js 复制代码
var env = process.env.NODE_ENV;
if(env === "development"){
    ...
}else if(env === "production"){
    ...
}else if(env === "test"){
    ...
}

不过上面的做法是永久生效的,即环境变量是永久存在于系统中的,并且修改环境变量时还需要进入高级系统设置中进行更改,因此更多时候是选择临时在环境变量中设置一个信息,用完就马上删除即可

使用下面的命令即可在window系统中临时加入或设置一个环境变量(只在window系统中支持)

bash 复制代码
set 环境变量名=环境变量值

可以使用&&连接多个命令,就可以在命令行中一次性运行多个命令(多种操作系统都支持)

bash 复制代码
命令1&&命令2&&命令3...

可以在package.json的scripts配置中添加如下几个自定义命令

json 复制代码
{
    "scripts": {
        "start": "set NODE_ENV=development&&node index.js",
        "build": "set NODE_ENV=production&&node index.js",
        "test": "set NODE_ENV=test&&node index.js"
    }
}

在上面的命令中,临时设置了环境变量NODE_ENV为某个值,并且立即执行工程的入口文件,然后立即还原该临时环境变量

如果当前环境是生产环境,只需要在命令行中输入npm run build即可启动工程并让其在生产环境下运行,开发环境下输入npm run start,测试环境下输入npm test即可

不过使用set临时设置环境变量只在window系统下有效,在macOS系统中,需要将set更改为export

有一个第三方库专门用于这方面的问题,它就是cross-env

向工程中安装cross-env库,将其作为开发依赖

bash 复制代码
npm i -D cross-env

然后修改package.json的scripts为如下内容即可

json 复制代码
{
    "scripts": {
        "start": "cross-env NODE_ENV=development node index.js",
        "build": "cross-env NODE_ENV=production node index.js",
        "test": "cross-env NODE_ENV=test node index.js"
    }
}

更多npm命令

  1. 精确安装最新版本,且package.json中也将使用精确的版本号进行版本记录

    bash 复制代码
    npm i --save-exact 包名

    --save-exact可以简写为-E

    bash 复制代码
    npm i -E 包名
  2. 安装指定版本

    bash 复制代码
    npm i 包名@版本号
  3. 查询包的安装路径

    bash 复制代码
    npm root [-g]

    查看本地包的安装路径

    bash 复制代码
    npm root

    查看全局包的安装路径

    bash 复制代码
    npm root -g
  4. 查看包的所有信息

    bash 复制代码
    npm view 包名

    查看包的名称

    bash 复制代码
    npm view 包名 name

    查看包的所有版本

    bash 复制代码
    npm view 包名 versions

    查看包的所有依赖

    bash 复制代码
    npm view 包名 dependencies
  5. 查询已安装的包(依赖深度默认为0,即不会显示已安装包的依赖包)

    bash 复制代码
    npm list [-g] [--depth=依赖深度]

    查询已安装的本地包

    bash 复制代码
    npm list [--depth=依赖深度]

    查询已安装的全局包

    bash 复制代码
    npm list -g [--depth=依赖深度]
  6. 检查有哪些包可以更新

    bash 复制代码
    npm outdated
  7. 根据package.json中记录的版本号更新规则将包更新为"最新版"

    bash 复制代码
    npm update [-g] [包名]
  8. 卸载包(被卸载的包所依赖的其他包,如果没有被工程中的其他包依赖,那么也将被卸载)

    bash 复制代码
    npm uninstall [-g] 包名

    uninstall可以简写为un

    bash 复制代码
    npm un [-g] 包名

yarn

核心命令

  1. 初始化

    bash 复制代码
    yarn init [--yes/-y]

    使用yarn生成的package.jsonnpm完全相同

  2. 添加包

    bash 复制代码
    yarn [global] add 包名 [--dev/-D] [--exact/-E]
  3. 根据package.json安装依赖

    bash 复制代码
    yarn install [--production/--prod]
  4. 运行自定义命令或本地CLI

    bash 复制代码
    yarn run 自定义命令名称/本地CLI命令名称

    start、stop、test可以省略run

  5. 查询bin目录(CLI所在目录)

    bash 复制代码
    yarn [global] bin
  6. 查询包信息

    bash 复制代码
    yarn info 包名 [子字段]

    子字段就是name、dependencies、versions等

  7. 列举已安装的依赖

    bash 复制代码
    yarn [global] list [--depth=依赖深度]
  8. 列举所有可以更新的包

    bash 复制代码
    yarn outdated
  9. 更新包

    bash 复制代码
    yarn [global] upgrade [包名]
  10. 卸载包

    bash 复制代码
    yarn [global] remove 包名

其它命令

  1. 检查package.json文件中的依赖版本记录与lock文件中的版本记录是否一致

    bash 复制代码
    yarn check
  2. 检查本地安装的包有哪些已知漏洞

    bash 复制代码
    yarn audit

    漏洞的级别有以下几种:

    ① INFO:信息级别

    ② LOW:低级别

    ③ MODERATE:中级别

    ④ HIGH:高几倍

    ⑤ CRITICAL:关键级别

  3. 搭建工程时一般需要使用到一些现成的脚手架工具,而大部分脚手架都是以create-xxx命名的,比如react官方的脚手架名称为create-react-app

    bash 复制代码
    #全局安装脚手架
    yarn global add create-react-app
    
    #使用脚手架搭建工程
    create-react-app my-app

    若脚手架名称以create-开头,则可以使用下面的命令来代替,下面的命令相当于上面的两条命令

    bash 复制代码
    yarn create react-app my-app

    若已经在全局安装了脚手架,则只相当于第二条命令

nvm

nvm并非包管理器,它是用于管理多个node版本的工具

nvm会提供一些CLI命令,用于管理node版本

最新版下载地址:github.com/coreybutler...

下载nvm-setup.zip后,直接安装

常用命令

  1. 安装指定版本的node,以及对应的npm

    bash 复制代码
    nvm install 版本号
  2. 列出已安装的node版本

    bash 复制代码
    nvm list
  3. 切换到已安装的指定node版本,npm和全局包也会被切换

    bash 复制代码
    nvm use 版本号
  4. 卸载已安装的指定版本的node,以及对应的npm

    bash 复制代码
    nvm uninstall 版本号
  5. 默认nvm是使用国外的服务器来安装node和npm,因此速度很慢,可以配置它们的下载源为国内的镜像源

    bash 复制代码
    nvm node_mirror https://npm.taobao.org/mirrors/node/
    nvm npm_mirror https://npm.taobao.org/mirrors/npm/
  6. 列出node已发布的所有版本

    bash 复制代码
    nvm list available

    LTS列:最近发布的稳定的node版本

    CURRENT列:最近发布的node版本(不一定是稳定的)

npx

运行本地命令

npx是伴随着node一起安装的,无需另外单独安装

使用npx 命令时,它会首先从本地工程的node_modules/.bin目录中寻找是否有对应的命令

例如:

bash 复制代码
npx webpack

上面这条命令寻找本地工程的node_modules/.bin/webpack

如果将命令配置到package.json的scripts中,则可以省略npx前缀

临时下载执行

当使用npx执行某个不存在的命令(即该命令既不是本地工程的命令,也不是全局命令)时,则npx会把命令对应的包下载到一个临时目录,下载完成后立即执行,而临时目录中的命令会在适当的时候删除

例如:

bash 复制代码
npx prettyjson 1.json

npx会下载prettyjson包到临时目录,然后运行该命令

若包提供的命令名称和包名不对应时,需要手动指定包名

例如:

@vue/cli是包名,该包提供的命令名称为vue,两者不一致,因此需要使用下面的命令

bash 复制代码
npx -p @vue/cli vue create vue-app

-p后面的@vue/cli是包的名称

npm init

npm init通常用于初始化工程的package.json文件

除此之外,有时也可以充当npx的作用

bash 复制代码
npm init 包名 # 等效于 npx create-包名
npm init @命名空间 # 等效于 npx @命名空间/create
npm init @命名空间/包名 # 等效于 npx @命名空间/create-包名
相关推荐
疯狂的沙粒12 分钟前
Vue项目开发 element-UI 前端实现 1到10排列选择的按钮
前端·vue.js·ui
刺客-Andy17 分钟前
React第六节 组件属性prop的propTypes类型使用介绍
前端·javascript·react.js·typescript
Mr.Liu61 小时前
小程序24-滚动效果:scroll-view组件详解
前端·微信小程序·小程序
三金121381 小时前
局部使用Vue
前端·javascript·vue.js
LinXunFeng1 小时前
Flutter - 子部件任意位置观察滚动数据
前端·flutter·开源
好开心331 小时前
js高级06-ajax封装和跨域
开发语言·前端·javascript·ajax·okhttp·ecmascript·交互
小镇程序员2 小时前
vue2 src_Todolist消息订阅版本
前端·javascript·vue.js
Zack No Bug2 小时前
解决报错:rror: error:0308010C:digital envelope routines::unsupported
前端·javascript·vue.js
九幽归墟2 小时前
深入理解 CPU 和 GPU 渲染
前端·浏览器·gpu
凌虚3 小时前
Web 端语音对话 AI 示例:使用 Whisper 和 llama.cpp 构建语音聊天机器人
前端·人工智能·后端