npm
npm
使用流程
npm install
介绍
全局安装的包,不仅仅会在依赖包,还会将依赖包中可执行命令添加至环境变量中,一般放在.bin
目录下
npm install
根据package-lock.json
中包对应的的版本下载,如果没有package-lock.json
文件,也会按照package.json
写定的版本安装,比如vue
的限制版本是^2.6.6
,那么就只会安装2.6.6
版本
npm install 包名
根据package.json
中包对应的版本下载
这里需要注意,因为package.json
中的版本是动态的,比如vue
的限制版本是^2.6.6
,那么在下载vue
包时,就会下载符合^2.6.6
版本限制的最新版本,也就是下载到^2.7.16"
版本,并且
并且下载完还会更新package.json
中的版本号
npm
下载指定版本
# 下载最新版本
npm i md5@latest
# 下载指定版本
npm i md5@2.3.0
npm create vite
实际做了什么?
npx create-vite
注:npm init
和npm create
是一样的
package.json文件配置
用于记录项目的npm
包依赖信息或项目信息
主要作用
- 用于管理本地项目
- 用于发布开源项目,发布到registry仓库中
文件结构
{
// 项目名称(必填)
"name": "npm",
// 项目版本(必填)
"version": "1.0.0",
// 项目描述
"description": "",
// 项目作者 (开源使用)
"author": "",
// 项目的开源协议(开源使用)
"license": "ISC",
// 项目发布成开源项目时,其他开发者如何搜索到该项目,也就是项目的关键词(开源使用)
"keywords": [],
// 项目是否是私有项目,如果是私有项目,就不能开源发布项目
"private": true,
// 项目的入口文件,在访问到该项目目录时,会首先访问该入口文件的地址
"main": "./index.js",
// 声明那些文件不去进行树摇判断处理
"sideEffects":[],
// 项目的脚本命令,通过npm run 命令的方式执行scripts中的脚本
"scripts": {
// 命令: 所需执行的脚本 npm run 命令名称
// start、stop、
"start": "node ./index.js"
},
// 项目中开发环境和生产环境都依赖的库,使用 `npm install 库名称 -S` 命令下载
"dependencies": {
/**
* 库名称: 依赖版本
* semver版本规范说明: `X.Y.Z`
* X:大的版本发生改变,也就是新版本不兼容老版本的时候,比如Vue2和Vue3
* Y:添加新的功能和API是改变的版本号
* Z:修复bug时改变的版本号
*
*
* 版本号规定了在重新下载依赖时,下载依赖的版本
* 依赖版本的前缀含义:
* 无前缀:固定库的版本,库发生版本发生改变,并不会安装新的版本
* ~:代表固定X版本和Y的版本,只要有Z发生变化就会更新最新版本
* ^:代表固定X版本,只要有Y和Z发生变化就会更新最新版本
* *:始终更新最新版本
*
*/
"element-plus": "^2.7.6"
},
// 项目中仅开发环境依赖的库,使用 `npm install 库名称 -D` 命令下载
"devDependencies": {
"webpack": "^5.92.1"
},
// 只会在开源项目中使用,表示该项目的依赖的其他的库,但不会被自动安装到项目中,需要用户手动下载安装
/**
* 为什么需要 peerDependencies,而不是放在 dependencies 或者 devDependencies 中?
* 避免多次安装,而且这属于用户自行需要安装的库
*/
"peerDependencies": {
"vue": "^3.2.0"
}
}
在开发项目时,dependencies
与devDependencies
的区别不强,但是在开发第三方包时,要合理区分开,因为在其他人下载第三包时,会跟着下载dependencies
中的依赖
导入lib包入口配置
默认:如果没有package.json
配置或者package.json
没有相对应的入口配置,就会使用当前文件夹index.js
或者index.ts
main
:一般常用的入口,也是保底入口,如果没有其他入口配置就会根据这个入口的配置,在浏览器和node中都可以使用
modlue
:EsModule
规范的入口
browser
:浏览器环境的入口
- 浏览器环境使用
import
:browser
>modlue
>main
> 默认 - node端使用
require
:main
> 默认
exports
node在16版本之后提出新的的入口配置,会直接覆盖前面的入口配置
{
"main": "index.main.ts",
"module": "index.module.ts",
"browser": "index.browser.ts",
"exports":{
".":{
"require": "./index.module.ts"
}
},
}
比如说,上面的配置,在浏览器使用import
导包,exports
选项没有import
入口配置,虽然有main
、module
、browser
选项,但是都不会采用,会直接使用默认入口
"exports":{
".":{
"require": "./index.module.ts"
},
"./style":{
"import":"./style.import.css",
"require":"./style.require.css"
}
},
exports
还可以配置其他目录引入的情况,但需要主要,其他目录引入的规则,必须包在node_modules
才有效
package-lock.json文件配置
该文件会自动在npm install
命令自动生成
主要作用
- 缓存以前下载的依赖,根据标识在本地找到对应的缓存包
- 在其他开发者进行
npm install
命令时,锁定具体的版本号 - 开发者观察版本依赖的结构
文件结构
{
// 项目名称
"name": "npm",
// 项目版本号
"version": "1.0.0",
// 项目package-lock.json的版本号
"lockfileVersion": 3,
// 项目的依赖关联采用的字段,如果是true,就会检验`dependencies`和`resolutions`两个字段
"requires": true,
// 项目的依赖
"packages": {
// 根依赖的入口
"": {
// 项目的名称
"name": "npm",
// 项目的版本号
"version": "1.0.0",
// 项目的开源协议
"license": "ISC",
// 根依赖的关联依赖
"dependencies": {
"less": "^4.2.0",
"vue": "^2.7.7"
}
},
"node_modules/vue": {
// 依赖的版本号
"version": "2.7.7",
// 依赖的registry仓库的压缩包地址
"resolved": "https://registry.npmmirror.com/vue/-/vue-2.7.7.tgz",
// 当需要下载时,使用该字段的值和本地依赖缓存进行比对,如果相同就不在去registry仓库下载,而是直接使用本地缓存
"integrity": "sha512-osfkncsGCWqtch+YWYxbqTNQ9hl/UQ6TFRkdmK/VqAjuMpxzr5QotFsYpmJ1AB1ez2LJeIKXDmtMkXUotMOTsA==",
// deprecated 字段用于标记某个依赖项已经被废弃
"deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
"dependencies": {
"@vue/compiler-sfc": "2.7.7",
"csstype": "^3.1.0"
}
},
}
npm
命令
卸载某个赖包
npm uninstall package
强制更新项目所有的包版本
npm rebuild
缓存
清除缓存
npm cache clean
查看配置
npm config list
查看包的基本信息
npm info md5
查看当前项目的所有包
npm list
检查项目包是否过期
npm outdated
执行命令
cmd
窗口执行命令
执行当前项目中node_modules
中的命令
从上面的命令查找流程中,可以发现,如果想执行项目中安装依赖包可执行命令,因为依赖包在当前项目的node_modules
目录中,也就决定了在项目根目录中执行不到这些可执行命令
进入命令目录
# 进入.bin目录
cd ./node_modules/.bin
# 执行命令
lessc -v
在当前目录中查找命令,就找到了
在package.json
文件中scripts
添加脚本
"scripts": {
"dev": "lessc -v"
},
# 执行命令
npm run dev
会首先在node_modules
目录中查找可执行命令,如果找不到再去全局环境变量中查找
npx
指令
npx lessc -v
npm link
npm link
安装全局包
在 a-p-dev
项目目录中执行 npm link
,就会在全局安装 a-p-dev
包
npm link
-
在全局
nodejs
node_modules
创建一个的a-p-dev
软链接目录,指向原始a-p-dev
项目原始的地址 -
扫描
h-run
文件夹,判断是否存在bin
属性
{
"name": "a-p-dev",
"bin": {
"a-p-dev": "bin/index.js"
},
"main": "bin/index.js"
}
- 在全局
nodejs
目录添加指定包名的a-p-dev
文件 和a-p-dev.cmd
文件
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\node_modules\a-p-dev\bin\index.js" %*s
npm uninstall [package-name] -g
卸载全局包
npm uninstall a-p-dev -g
- 删除全局
nodejs
node_modules
下面的a-p-dev
软链接目录,并不会影响已存在的项目的引入
npm link [package-name]
项目中引用全局包
npm link a-p-dev
- 在当前目录
node_modules
中添加a-p-dev
目录的软连接,软连接到项目原始的地址,这里不是链接到全局nodejs
node_modules
下面的地址
注意:package.json
并不会发生改变,也就是并没有添加 a-p-dev
到 description
中
{
"name": "a-p"
}
const aPDev = require('a-p-dev');
console.log(aPDev);
npm unlink [package-name]
项目中取消引用全局包
npm unlink a-p-dev
- 在当前目录
node_modules
中删除a-p-dev
目录的软连接
pnpm
npm
缺点
占用空间
多个项目node_modules
中的依赖包是独立的,也就是会出现同一版本同一名称的依赖包出现在磁盘的不同位置,占用磁盘的储存空间
幽灵依赖
项目中可以访问到不属于当前项目所设定的依赖包
软连接和硬链接
在项目中,明明只依赖了less
一个包,但是因为less
依赖其他包,也就会下载其他包,并且因为这些包都放在 node_modules
目录中,那么在源代码就也可以使用,这显然设计不合理的
拷贝
硬链接
只是用于文件
软连接
也就是快捷方式,在点开软连接时,就会弹到打开源文件的地址
在require
加载软连接时,也会追根溯源的加载到源文件
pnpm
优点
节省空间
依赖包只会在磁盘中保存到统一位置,多个项目中相同的依赖包,通过硬链的方式加载
同一个依赖包的不同版本,只会记录不同的文件
速率高
在通过pnpm install
安装第三方依赖包时,会先去本地依赖包的统一位置查询,如果存在就直接获取
pnpm
的 workspace
命令
- 为指定模块安装外部依赖。
pnpm --filter @h-cli/cli add -S import-local
pnpm --filter @h-cli/cli add -D import-local
- 根项目全局安装子项目
pnpm add @h-cli/cli --workspace -w