1、概念区别:模块、库、包
- 模块 ------
功能片段
:以单文件形式存在的 - 库 ------
完整独立的功能
:由一个或多个模块组成的 - 包 ------
添加了描述信息的库
:包含作者、git主页、许可证等信息的库
范畴:包 > 库 >= 模块
2、为何出现包管理器?
项目通常要使用很多第三方库 ,而第三方库的使用带来了许多问题:
- 下载很麻烦
- 第三方库的依赖问题,层级过深,导致需要下载大量依赖
- 可能出现命名冲突问题
- 不同环境所采用的第三方库不同,导致难以区分问题
- 第三方库版本更新麻烦
- 自己开发的库,复用的维护麻烦问题
为了解决以上问题,所以出现了包管理器,不仅前端,后端语言也有各自的包管理器
(传统前端之所以没有出现包管理器,是因为当时没有模块化技术出现,在出现模块化技术之后,就需要包管理器进行管理)
3、NPM的组成?
-
registry:注册仓库源
-
官网
查找和发布包
-
CLI
NPM
提供给用户一种使用方式(命令行)
4、如何更改NPM注册仓库?
NPM默认注册仓库源是在国外,由于网络非常不稳定,导致包的下载经常失败,所以需要更改
arduino
npm config set registry https://registry.npm.taobao.org
5、包 - 分类与安装
- 分类
不带CLI的包
和 带CLI的包
- 安装
全局安装使用的非常少,仅为了提供全局CLI支持
可使用 npm config get prefix
命令获取全局安装包所在目录
6、包 - 配置文件
所有使用NPM的项目中,必须在根目录下创建 package.json
配置文件,用于保存项目的信息及所用到的脚本
,以便于包的发布和依赖还原等
1、包的基本信息
2、包的依赖信息
7、包 - 使用
当导入模块时,如果模块路径不是以"./"
或"../"
开头的话,则node
会认为导入的模块是来自于node_module
目录,这就是包的使用方式
自定义模块 vs 第三方包
自定义模块就是自己写的模块,导入时,模块路径必须以'./'或'../'开头,代码如下
js
const _ = require("./test.js")
const $ = require("../jquery.js")
而导入从NPM安装的第三方包时,模块路径可以直接写包名,代码如下
js
const _ = require("lodash")
第三方包导入是直接从node_modules
目录开始寻找
导入时寻找模块规则
口诀(第三方包或者自定义模块都适用):
1、先找文件,后找目录
2、如果没有指定文件后缀,按js>json>node文件后缀顺序查找,找不到就找目录
3、当目录内没有package.json配置文件时,就默认找index.js文件作为入口模块导入
4、当目录内存在package.json配置文件时,如果存在main字段,就按main字段的值作为入口模块导入,否则也是按默认index.js导入
下面以导入lodash包为例:
确定入口模块的规则(针对导入路径是包时)
8、包 - 语义化版本
版本规范
主版本号 . 次版本号 . 补丁版本号
- 主版本号:当程序发生重大变化(不兼容)时,主版本号才会增长
- 次版本号:当程序发生小变化(兼容)时,次版本号才会增长
- 补丁版本号:修复BUG或优化(兼容)时,补丁版本号才会增长
语义规则
在package.json配置文件中,不仅要描述当前依赖的包是什么,还需要描述包的 版本信息 ,我们把此版本信息称之为 语义版本
(带有语义规则的版本)
符号 | 描述 | 示例 | 含义 |
---|---|---|---|
~ | 补丁版本号可增 | ~1.2.4 | 保证主版本和次版本不变,补丁版本>=4 |
^ | 次版本和补丁版本可增 | ^1.2.4 | 保证主版本不变,次版本>=2, 补丁版本>=4 |
x | 不固定版本 | 1.2.x | 只要保证主和次版本不变就可以 |
* | 最新版本 | * | 始终安装最新版本 |
避免还原的差异
依赖控制始终是一个面临两难的抉择问题
- 允许依赖版本可增,让包的BUG得到修复和有新的api加入,但也带来不确定性的风险(新BUG的出现)
- 不允许依赖版本可增,可获得最大层度的稳定性,但失去包的自我优化的能力
因此,npm参考了yarn之后,在安装包之后,自动生成一个package-lock.json
文件,用于记录安装包的依赖确切的版本
当移植工程时,如果存在package-lock.json
文件,恢复依赖(npm i
)时,优先按照package-lock.json
文件记录的依赖确切版本进行安装,最大层度保证工程的稳定运行
9、NPM - 脚本
很多第三方包都提供大量CLI命令,由于CLI命令 纷繁复杂,数量众多,难以记忆 等问题,NPM
为了简化命令的使用 ,专门提供了一种可配置化的命令使用方式
命令分类
- 全局命令
系统环境下的所有CLI命令,包括全局安装包所带的CLI命令;任意位置直接使用
- 局部命令
本地安装包所带的CLI命令;可通过npx
命令来使用,但必须在工程根目录中使用,实际开发中,一般使用NPM脚本方式替代npx
方式来运行局部命令
脚本配置
在package.json
文件中,使用script
字段来配置常用命令(不止包提供的命令,还可以配置win系统命令)
json
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
}
10、NPM - 其他命令
安装
less
npm i -D 包名 // 局部安装(开发环境)
npm i -S 包名 // 局部安装(生产环境)
npm i -E 包名 // 精准安装
npm i -g 包名 // 全局安装
npm i 包名@版本号 // 安装指定版本的包
查询
less
// 查看[全局安装]包的安装路径
npm root [-g]
// 查看包的信息(来源于package.json)【任意的包】
npm view 包名
// 查看当前项目安装了哪些包,-g查看全局安装了哪些包
npm list [-g] [--depth=深度]
更新
less
// 检测当前项目的包哪些需要更新
npm outdated
// 更新指定的本地包[全局包]
npm update [-g] 包名
// 更新npm包管理器
npm i -g npm
卸载
css
// 卸载指定本地包[全局包]
npm uninstall [-g] 包名
配置相关
arduino
// 查看当前生效的npm配置[-l包括所有默认配置]
npm config ls [-l]
// 获取某个配置项
npm config get 配置项名称
// 设置某个配置项
npm config set 配置项名称 值
// 删除某个配置项
npm config delete 配置项名称
11、NPX - 包管理器给你提供的便利
如果本地安装的包带有CLI命令,我们使用时不能像全局CLI命令那么方便,为了提供给我们方便,NPM提供给我们一个npx
命令,使用场景通常有2个:
- 执行本地包的
CLI
命令 - 有些包对于项目来说只使用一次,可使用
npx
执行,无需安装本地包