概述
模块(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安装包的方式分为两种:
- 本地安装
- 全局安装
本地安装
使用下面命令进行本地安装
bash
npm install 包名
install
可以简写为i
bash
npm i 包名
同时下载多个包
bash
npm i 包名1 包名2 ...
本地安装的包会出现在当前目录下的node_modules
目录中
注意:
-
node_modules
目录中的内容不适合传输到生产环境中,因此应该在.gitignore
文件中忽略该目录 -
本地安装的包只会影响当前目录以及当前目录的子目录,不会对当前目录以外的目录造成影响
-
npm在安装包(包括本地安装和全局安装)时,若安装的包依赖了其它包,则npm也会自动将这些依赖的包也下载下来,即npm能够自动管理包依赖
-
若本地安装的包中带有CLI文件,npm会将该CLI文件放置到
node_modules/.bin
目录中,使用该CLI中的命令时,需要命令的最前面加上npx
全局安装的包提供的CLI,其中的命令可以在任何目录中调用
-
若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中记录的信息有:
-
name
包的名称,该名称只能包含英文字符、数字和
-
-
version
包的版本信息,默认为1.0.0
版本号规范:主版本号.次版本号.补丁版本号
主版本号:当程序发生了重大变化时,主版本号增加,重大变化包括大量新特性的加入,技术架构的改变等
此版本号:当程序发生了细微变化时,此版本号增加,细微变化包括加入了一些辅助型的API等
补丁版本号:当解决了程序中的一些bug,或进行了一些局部优化时,补丁版本号增加
有些版本号在后面还可能会跟上一些补充信息,如
-alpha
,-beta
,-rc
等其中
-alpha
,-beta
都表示不太成熟的当前版本,-rc
表示较为成熟的当前版本,如果什么都不加,表示当前版本已经非常成熟,实际使用时也最应该使用这种版本号的版本 -
description
包的描述信息
-
homepage
官网地址
-
repository
包的仓库地址,通常为包在git或svn中的地址
-
main
包的入口文件,默认为index.js
使用该包的人默认从该入口文件导入包的内容
-
keywords
搜索关键字
当包发布到npm上后,需要通过该关键字来搜索到此包的内容
-
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
参数才能将依赖记录进去
cssnpm i -S 包名
若想把安装的本地包作为开发依赖保存到package.json中,应该使用下面命令
bash
npm i --save-dev 包名
--save-dev
可以简写为-D
bash
npm i -D 包名
其实对于普通的前端开发者而言,开发依赖和普通依赖并没有什么区别,因为无论是开发依赖还是普通依赖,只要是在模块中导入的依赖,模块中的代码经过webpack打包过后都会加入到打包结果中
但对于要发布包给别人使用的作者来说,他们才需要关心一个库应该是普通依赖还是开发依赖
node查找包的顺序
require函数中的路径如果不以./
或../
开头,而直接书写包的名称时,nodejs就会按照下面的顺序查找包:
js
require("lodash")
- 查找是否有内置模块lodash
- 如果没有内置模块lodash,则查找模块所在当前目录下的node_modules目录中是否有lodash.js文件
- 若没有lodash.js文件,则查找模块所在当前目录下的node_modules目录中是否存在lodash目录,并查找该目录中是否有相应的入口文件
- 若没有lodash目录,或有lodash目录但没有相应的入口文件,则返回上一级目录,然后对该目录重复2和3两个步骤,直至查找磁盘的根目录
- 若最终都没有找到该模块,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
细节
-
scripts配置中的相对路径,是相对于该package.json的路径
-
npm对一些常见的自定义命令名称进行了简化,下面的自定义命令名称在调用时可以不加
run
① start
② stop
③ test
bashnpm start
-
在scripts配置中所关联的本地第三方库命令,可以省略npx
-
若没有加入scripts配置,或scripts配置中没有书写
start
自定义命令,则start
默认为node server.js
运行环境配置
我们编写的代码可能会在许多种不同的环境下运行:
- 开发环境
- 生产环境
- 测试环境
而针对不同的环境,可能要进行不同的处理
而在代码中应该如何判断当前所处的环境呢,就需要使用到操作系统的环境变量信息
在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命令
-
精确安装最新版本,且package.json中也将使用精确的版本号进行版本记录
bashnpm i --save-exact 包名
--save-exact
可以简写为-E
bashnpm i -E 包名
-
安装指定版本
bashnpm i 包名@版本号
-
查询包的安装路径
bashnpm root [-g]
查看本地包的安装路径
bashnpm root
查看全局包的安装路径
bashnpm root -g
-
查看包的所有信息
bashnpm view 包名
查看包的名称
bashnpm view 包名 name
查看包的所有版本
bashnpm view 包名 versions
查看包的所有依赖
bashnpm view 包名 dependencies
-
查询已安装的包(依赖深度默认为0,即不会显示已安装包的依赖包)
bashnpm list [-g] [--depth=依赖深度]
查询已安装的本地包
bashnpm list [--depth=依赖深度]
查询已安装的全局包
bashnpm list -g [--depth=依赖深度]
-
检查有哪些包可以更新
bashnpm outdated
-
根据package.json中记录的版本号更新规则将包更新为"最新版"
bashnpm update [-g] [包名]
-
卸载包(被卸载的包所依赖的其他包,如果没有被工程中的其他包依赖,那么也将被卸载)
bashnpm uninstall [-g] 包名
uninstall
可以简写为un
bashnpm un [-g] 包名
yarn
核心命令
-
初始化
bashyarn init [--yes/-y]
使用
yarn
生成的package.json
和npm
完全相同 -
添加包
bashyarn [global] add 包名 [--dev/-D] [--exact/-E]
-
根据package.json安装依赖
bashyarn install [--production/--prod]
-
运行自定义命令或本地CLI
bashyarn run 自定义命令名称/本地CLI命令名称
start、stop、test可以省略run
-
查询bin目录(CLI所在目录)
bashyarn [global] bin
-
查询包信息
bashyarn info 包名 [子字段]
子字段就是name、dependencies、versions等
-
列举已安装的依赖
bashyarn [global] list [--depth=依赖深度]
-
列举所有可以更新的包
bashyarn outdated
-
更新包
bashyarn [global] upgrade [包名]
-
卸载包
bashyarn [global] remove 包名
其它命令
-
检查package.json文件中的依赖版本记录与lock文件中的版本记录是否一致
bashyarn check
-
检查本地安装的包有哪些已知漏洞
bashyarn audit
漏洞的级别有以下几种:
① INFO:信息级别
② LOW:低级别
③ MODERATE:中级别
④ HIGH:高几倍
⑤ CRITICAL:关键级别
-
搭建工程时一般需要使用到一些现成的脚手架工具,而大部分脚手架都是以
create-xxx
命名的,比如react官方的脚手架名称为create-react-app
bash#全局安装脚手架 yarn global add create-react-app #使用脚手架搭建工程 create-react-app my-app
若脚手架名称以
create-
开头,则可以使用下面的命令来代替,下面的命令相当于上面的两条命令bashyarn create react-app my-app
若已经在全局安装了脚手架,则只相当于第二条命令
nvm
nvm并非包管理器,它是用于管理多个node版本的工具
nvm会提供一些CLI命令,用于管理node版本
最新版下载地址:github.com/coreybutler...
下载nvm-setup.zip后,直接安装
常用命令
-
安装指定版本的node,以及对应的npm
bashnvm install 版本号
-
列出已安装的node版本
bashnvm list
-
切换到已安装的指定node版本,npm和全局包也会被切换
bashnvm use 版本号
-
卸载已安装的指定版本的node,以及对应的npm
bashnvm uninstall 版本号
-
默认nvm是使用国外的服务器来安装node和npm,因此速度很慢,可以配置它们的下载源为国内的镜像源
bashnvm node_mirror https://npm.taobao.org/mirrors/node/ nvm npm_mirror https://npm.taobao.org/mirrors/npm/
-
列出node已发布的所有版本
bashnvm 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-包名