第四节:npm介绍、package.json详解、npm install原理、常用指令、npx工具、发布自己的包
一. 包管理工具npm
(关于npm的安装、配置下载路径、一些指令,可以参考之前的文章:https://www.cnblogs.com/yaopengfei/p/14478126.html)
1. npm简介
(1). 包管理工具npm
npm全称,Node Package Manager,也就是Node包管理器;
但是目前已经不仅仅是Node包管理器了,在前端项目中我们也在使用它来管理依赖的包;比如vue、vue-router、vuex、express、koa、react、react-dom、axios、babel、webpack等等;
(2).如何下载npm工具呢?
npm属于node的一个管理工具,所以我们需要先安装Node,安装完node以后,npm也就安装了。
node管理工具:https://nodejs.org/en/
(3). npm管理的包可以在哪里查看、搜索呢?
npm包的官网:https://www.npmjs.com/
(4). npm管理的包存放在哪里呢?
我们发布自己的包其实是发布到registry上面的;当我们安装一个包时其实是从registry上面下载的包;
A. 通过【npm install xxx -g】全局安装的包,在你设置的全局文件夹下:D:\Develop\npm\node_modules
B. 通过【npm install xxx】和【npm install -D】安装项目依赖的包,在对应项目的node_modules里。
注意:对于项目依赖的包,她是有缓存的,即如果本地电脑已经下载过这个版本的包,就直接去本地拿到压缩包,解压到项目中的node_modules即可,不需要去npm官网的registry上下载,那么这个压缩包在 D:\Develop\npm-cache 下。
【后面将结合package_lock.json详细讲解】2. npm配置文件(package.json)
(1). npm如何管理这么多包?
我们每一个项目都会有一个对应的配置文件,无论是前端项目(Vue、React)还是后端项目(Node);这个配置文件会记录着你项目的名称、版本号、项目描述等;也会记录着你项目所依赖的其他库的信息和依赖库的版本号;
这个配置文件就是package.json
(2). 如何生成这个配置文件
A. 手动从零创建项目,【npm init –y】 或者【npm init】一步一步生成
B. 通过脚手架创建项目,脚手架会帮助我们生成package.json,并且里面有相关的配置
npm init -y 创建的配置文件
{
"name": "01_npm",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Vue3的配置文件

{
"name": "vue3Admin",
"version": "0.1.0",
"description": "vue3 vite next admin template js setup",
"author": "ypf",
"license": "MIT",
"scripts": {
"serve": "vite --force",
"build": "vite build",
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
},
"dependencies": {
"@element-plus/icons-vue": "^0.2.4",
"axios": "^0.24.0",
"echarts": "^5.2.2",
"element-plus": "^1.2.0-beta.6",
"mitt": "^3.0.0",
"nprogress": "^0.2.0",
"qrcodejs2-fixes": "^0.0.2",
"screenfull": "^6.0.0",
"sortablejs": "^1.14.0",
"vue": "3.2.20",
"vue-clipboard3": "^1.0.1",
"vue-router": "^4.0.12",
"vuex": "^4.0.2"
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.0.1",
"@vue/compiler-sfc": "^3.2.26",
"dotenv": "^10.0.0",
"eslint": "^8.5.0",
"eslint-plugin-vue": "^8.2.0",
"prettier": "^2.5.1",
"sass": "^1.45.1",
"sass-loader": "^12.4.0",
"unplugin-auto-import": "^0.5.4",
"vite": "^2.7.4",
"vite-plugin-vue-setup-extend": "^0.1.0",
"vue-eslint-parser": "^8.0.1"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
],
"bugs": {
"url": "https://www.cnblogs.com/yaopengfei"
},
"engines": {
"node": ">=12.0.0",
"npm": ">= 6.0.0"
},
"keywords": [
"vue",
"vue3",
"vuejs/vue-next",
"vuejs/vue-next-template",
"vuejs/vue-next-template-js",
"element-ui",
"element-plus",
"vue-next-admin",
"next-admin"
],
"repository": {
"type": "git",
"url": "https://www.cnblogs.com/yaopengfei"
}
}
3. package.json属性详解
(1). 基本属性
name是项目的名称;【必填】
version是当前项目的版本号;【必填】
description是描述信息,很多时候是作为项目的基本描述;
author是作者相关信息(发布时用到);
license是开源协议(发布时用到);
(2). private属性
private属性记录当前的项目是否是私有的;
当值为true时,npm是不能发布它的,这是防止私有项目或模块发布出去的方式;
(3). main属性
设置程序的入口。webpack实际上是找到对应的main属性查找文件的
(4). scripts属性
scripts属性用于配置一些脚本命令,以键值对的形式存在;配置后我们可以通过 npm run 命令的key来执行这个命令;
比如配置了 "serve": "vite --force", 我们就可以执行 【npm run server】 实际上等价于 【npx vite --force】
特殊情况:对于常用的key,是可以省略run的。【npm start】和【npm run start】是等价的。对于常用的 start、 test、stop、restart可以省略掉run直接通过 npm start等方式运行;
(5). dependencies属性
dependencies属性是指定无论开发环境还是生产环境都需要依赖的包;通常是我们项目实际开发用到的一些库模块vue、vuex、vue-router、react、react-dom、axios等等;
(6). devDependencies属性
一些包在生产环境是不需要的,仅开发过程中需要,比如webpack、babel等; 这个时候我们会通过 【npm install webpack --save-dev】,将它安装到devDependencies属性中;
(7). peerDependencies属性
还有一种项目依赖关系是对等依赖,也就是你依赖的一个包,它必须是以另外一个宿主包为前提的; 比如element-plus是依赖于vue3的,ant design是依赖于react、react-dom;
(8). 依赖版本管理【重】
npm的包通常需要遵从semver版本规范:semver:https://semver.org/lang/zh-CN/ npm semver:https://docs.npmjs.com/misc/semver
semver版本规范是X.Y.Z:
X主版本号(major):当你做了不兼容的 API 修改(可能不兼容之前的版本);
Y次版本号(minor):当你做了向下兼容的功能性新增(新功能增加,但是兼容之前的版本);
Z修订号(patch):当你做了向下兼容的问题修正(没有新功能,修复了之前版本的bug);
比如: "vue": "3.2.20"、“^3.2.20”、“~3.2.20”、
我们这里解释一下 ^和~的区别:
^x.y.z:表示x是保持不变的,y和z永远安装最新的版本;【这里指npm install的时候】
~x.y.z:表示x和y保持不变的,z永远安装最新的版本; 【这里指npm install的时候】
x.y.z : 就如字面一样的版本
(9). engines属性
engines属性用于指定Node和NPM的版本号;
在安装的过程中,会先检查对应的引擎版本,如果不符合就会报错;
事实上也可以指定所在的操作系统 "os" : [ "darwin", "linux" ],只是很少用到;
(10). browserslist属性
用于配置打包后的JavaScript浏览器的兼容情况,参考;否则我们需要手动的添加polyfills来让支持某些语法;也就是说它是为webpack等打包工具服务的一个属性
二. npm install原理
1. package-lock.json剖析
下面代码是执行了【npm install axios】后的文件

{
"name": "01_npm",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "01_npm",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"axios": "^0.26.1"
}
},
"node_modules/axios": {
"version": "0.26.1",
"resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"dependencies": {
"follow-redirects": "^1.14.8"
}
},
"node_modules/follow-redirects": {
"version": "1.14.9",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
}
},
"dependencies": {
"axios": {
"version": "0.26.1",
"resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"requires": {
"follow-redirects": "^1.14.8"
}
},
"follow-redirects": {
"version": "1.14.9",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
}
}
}
name:项目的名称;
version:项目的版本;
lockfileVersion:lock文件的版本;
requires:使用requires来跟踪模块的依赖关系;
dependencies:项目的依赖,当前项目依赖axios,但是axios依赖follow-redireacts;
axios中的属性如下:
version表示实际安装的axios的版本;
resolved用来记录下载的地址,registry仓库中的位置;
requires记录当前模块的依赖;
integrity用来从缓存中获取索引,再通过索引去获取压缩包文件;
2. 【npm install】指令原理
npm install首先会检测是有package-lock.json文件:
(1). 没有lock文件
A. 分析依赖关系,这是因为我们可能包会依赖其他的包,并且多个包之间会产生相同依赖的情况;
B. 从registry仓库中下载压缩包(如果我们设置了镜像,那么会从镜像服务器下载压缩包,比如设置了从taobao下载);
C. 获取到压缩包后会对压缩包进行缓存(从npm5开始有的);
D. 将压缩包解压到项目的node_modules文件夹中(require的查找顺序会在该包下面查找)
(2). 有lock文件
A. 检测lock中包的版本是否和package.json中一致(会按照semver版本规范检测,详见上面08);
B. 不一致,那么会重新构建依赖关系,直接会走顶层的流程;
C. 一致的情况下,会去优先查找缓存
D. 没有找到,会从registry仓库下载,直接走顶层流程;
E. 查找到,会获取缓存中的压缩文件,并且将压缩文件解压到node_modules文件夹中;
(3). 缓存的作用
将通过npm下载过的包存放到本地(D:\Develop\npm-cache\_cacache) ,【npm get cache 查找路径】,下次npm的时候,会先查看package_lock中的版本是否符合package中的版本要求,如果符合,则优先查找缓存。
如何查找去缓存中查找呢?
package_lock中的integrity属性存放的是索引,然后根据索引去对应的文件夹Content-v2中找到压缩包,然后解压到项目中去。
D:\Develop\npm-cache\_cacache\index-v5 存放索引
D:\Develop\npm-cache\_cacache\content-v2 存放内容
(4). package_lock.json的作用
A. 锁定实际版本,用于【npm install】恢复的时候,下载该版本的包。
B. 记录包本地缓存的索引,便于查找本地磁盘中的查找压缩包,来解压到项目中。
4. 实战测试
场景1:只有package.json , 初始化运行【npm install】
如下,为package.json中的包对应的版本号,此时npm服务器上最新的版本分别为 0.26.1、4.17.21
"dependencies": {
"axios": "^0.26.0",
"lodash": "^4.17.20"
}
运行指令【npm install】,按照规范 y和z处的版本号都要保持最新,所以实际安装的使 0.26.1 和 4.17.21这一版本 ,如下图生成的package_lock.json文件中的版本号
场景2:存在lock文件,初始化运行【npm install】
如下,为package.json中的包对应的版本号,此时npm服务器上最新的版本分别为 0.26.1、4.17.21
"dependencies": {
"axios": "^0.26.0",
"lodash": "^4.17.20"
}
package_lock.json文件中的的版本号为 0.26.0 、4.17.20
"dependencies": {
"axios": {
"version": "0.26.0",
"resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.0.tgz",
"integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==",
"requires": {
"follow-redirects": "^1.14.8"
}
},
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
}
}
运行【npm install】,安装的是lock中锁定的版本 0.26.0、4.17.20 (通过查node_modules中下载的源码可知)
总结:如果copy代码给别人,只包含package.json文件,则会根据package.json文件的版本号规范,去下载符合规范的最新版本。
如果包含package.json和package_lock.json文件,且lock的中版本号符合package的规范,则安装的使lock文件中锁定的版本号,lock中版本是多少,下载的就是多少。
场景3:存在lock文件,但是安装指定版本【npm install xxx@1.2.1】
无论lock中锁定的版本是多少,都会被修改为1.2.1。
场景4:存在lock文件,安装默认版本 【npm install xxx】
如下,package.json文件中axios的版本为 "axios": "^0.26.0", package_lock.json中的版本号为:0.26.0,服务器上最新的版本号为:0.26.1
此时运行指令【npm install axios】,结果如下:
package.json中变为: axios: ^0.26.1,lock文件中的版本号变为:0.26.1
三. npm 常用指令
详见官方文档:https://docs.npmjs.com/cli-documentation/cli
详见之前的文档:https://www.cnblogs.com/yaopengfei/p/14478126.html
四. npx工具
1. 说明
npx是npm5.2之后自带的一个命令。npx的作用非常多,但是比较常见的是使用它来调用项目中的某个模块的指令(node_modules文件夹中的某个包下的指令)。
2. 实操
比如:以webpack为例,全局安装的是webpack5.1.3,项目安装的是webpack3.6.0。
那么我在项目中的命令行运行指令 【 webpack --version】,显示的是5.1.3, 调用的是全局的webpack,那么如何调用项目依赖的webpack呢?
方案1:
直接到node_modules下的webpack文件夹下执行这个指令,如:【./node_modules/.bin/webpack --version】
方案2:
配置package.json中的script下配置,如下,运行指令【npm run ypf】即可
"scripts": {
"ypf": "webpack --version"
},
方案3:
使用npx直接调用即可,指令为:【npx webpack --version】
五. npm发布包
1. 准备
首先需要去npm官网注册npm账号:https://www.npmjs.com/
2. 发布
(1). 编写ESModule代码
(2). 项目中运行指令 【npm login】,输入账号密码进行登录
(3). 运行指令【npm publish】进行发布
如果要更新的话,需要修改版本号,需要符合semver规范,重新运行【npm publish】进行发布。
其它指令:
删除发布的包:【npm unpublish】
让发布的包过期:【npm deprecate】
3. 使用
通过【npm install xxx】下载即可
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)