写点什么

前端包管理工具 npm yarn cnpm npx

作者:虎妞先生
  • 2023-02-10
    北京
  • 本文字数:3114 字

    阅读完需:约 10 分钟

前言

这篇文章主要和大家分享前端包管理工具,是什么,怎么用和基本原理,通过阅读,我想至少能够帮助大家解决一些常见的面试问题。


1.npm 和 yarn 区别和联系


2.package.json 和 package-lock.json 是干什么的,有什么用


3.npm install 之后发生了什么


4.如何发布一个自己的 npm 包*



包管理工具的产生背景

我们通过 JavaScript 模块化的方式,把代码划分成一个小小的结构,并且封装成一个模块工具。当我们的同事也想使用这个工具的时候,可以手动导入给他当我们想分享给更多人的使用,该怎么做呢?一般来说方式有两种。

方式一

上传到 github,其他人通过 github 下载我们的代码,手动引用


* 需要手动引用,手动管理依赖,手动控制风险较大。
* 当版本更新或者删除依赖时,需要重复上面的操作。
复制代码


根据墨菲定律,凡是可能出问题的地方,就必出发生问题,这种方式是有效的方法,但觉得不是一个方便的方法,就像我们经常所说的,理论上可行,实际开发中不可用

方式二

使用专业的包管理工具来管理我们代码


  • 我们通过工具将代码发布到特定的位置

  • 其他人直接通过工具来安装,升级,删除我们的工具代码包


这也就是我今天要和大家分享的包管理工具

包管理工具 npm

概述

npm 全称 Node Package Manager node 包管理工具,现在已经不仅仅局限于 node 包,在前端项目里我们也使用他来管理依赖包,比如 vue,vue-router,vuex,express,koa,react,axios,babel,webpack。


npm 属于 node 的管理工具,当我们下载安装 node 的时候,就会一起安装 npm


npm 管理的包可以在 npm 官网https://www.npmjs.org/


我们发布自己的包其实是发布到 registry 上面的,当我们安装一个包时其实是从 registry 上面下载的包https://registry.npmjs.org

npm 配置文件

package.json 文件

现在前端开发有大量的包,那么我们用 npm 管理管理这么多包,无论前端项目 vue,react,还是后端项目 express,koa,egg,都会一个配置文件,这个配置文件记录这项目的名称,版本号,项目描述,项目依赖库和依赖库的版本号。


可以使用 npm init 生成一个 package.json 文件


也可以通过脚手架创建一个项目,帮助我们自动生成 package.json

配置文件图示


配置文件中常见的属性

必须填写的属性 name,version

  • name 是项目名称

  • version 是当前项目版本号

  • description 是描述信息,作为项目的补充说明

  • author 是作者,发布时会用到

  • license 是使用的开源协议,发布会用到

private 属性

  • 记录当前项目是否时私有的

  • 当只为 true 时,npm 不能发布它

main 属性

  • 设置程序的入口

  • 当前包的入口文件

  • 注意区别 webpack 入口文件的概念,不是一个东西。

script 属性

  • 常配置一些脚步命令

  • 如我们经常使用的 npm run start,npm run build

  • npm start 也等于 npm run start,start 命令可以省去

dependencies 属性

  • 无论哪个环境都需要依赖的资源包

  • 如 vue 全家桶,axios

devDependencies 属性

  • 本地开发环境需要依赖的资源包如 webpack,babel

  • 安装命令为 npm install webpack --save-dev

engines 属性

  • 用于指定 node 和 npm 的版本号,有些包对 node 版本有最低要求

  • 当下载包的时候,会优先检查版本,如不符合就会安装依赖时报错

browserslist 属性

  • 支持到哪个版本的浏览器,和 babel 配置强相关,可暂时先不关心,等之后我们可以专题讨论 babel 这里的知识

依赖包版本管理

npm 包版本一般规范为为 X.Y.Z


X 为主版本号 一般为大版本更新,可能不兼容之前的版本,如 Vue2.0 和 Vue3.0


Y 为次版本号 一般为新增一恶搞功能,向下兼容,如 Vue2.0 和 Vue2.x


Z 为修订版本号 一般是修复了小问题,小版本优化


我们常见的版本号形如这样


^x.y.z:表示 x 是保持不变的,y 和 z 永远安装最新的版本;


~x.y.z:表示 x 和 y 保持不变的,z 永远安装最新的版本;

依赖包安装

  • 安装分为全局安装和局部安装

  • 如 npm yarn webpack 这样的包就适合全局安装

  • npm install webpack -g

  • 如 vue axios 这样项目中用的包就适合局部安装

  • 安装之后会在当前目录下生成一个 node_modules 文件夹

npm install 原理

npm 在安装之后,不仅生成了 node_modules,还多出了一个 package-lock.json 来支持缓存策略像 yarn 看齐,这个我们后面会说到



npm instll 原理图解

  • npm install 会检测是有 package-lock.json 文件:

  • 没有 package-lock.json 文件

  • 分析依赖关系,这是因为我们可能包会依赖其他的包,并且多个包之间会产生相同依赖的情况;

  • 从 registry 仓库中下载压缩包(如果我们设置了镜像,那么会从镜像服务器下载压缩包);

  • 获取到压缩包后会对压缩包进行缓存(从 npm5 开始有的)

  • 将压缩包解压到项目的 node_modules 文件夹中

  • 有 package-lock.json 文件

  • 检测 lock 中包的版本是否和 package.json 中一致

  • 不一致,那么会重新构建依赖关系,直接会走上面的流程;

  • 一致的情况下,会去优先查找缓存

  • 缓存没有找到,从 registry 仓库下载,直接走上面流程;

  • 命中缓存会获取缓存中的压缩文件

  • 将压缩文件解压到 node_modules 文件夹中;

package-lock.json


** package-lock.json 文件解析**


  • name:项目的名称;

  • version:项目的版本;

  • lockfileVersion:lock 文件的版本;

  • requires:使用 requires 来跟踪模块的依赖关系;

  • dependencies:项目的依赖

  • version 表示实际安装的版本;

  • resolved 用来记录下载的地址,registry 仓库中的位置;

  • requires 记录当前模块的依赖;

  • integrity 用来从缓存中获取索引,再通过索引去获取压缩包文件

npm 其他常用命令

卸载某个依赖包:


  npm uninstall package  npm uninstall package --save-dev  npm uninstall package -D
复制代码


强制重新 build


npm rebuild
复制代码


清除缓存


npm cache clean
复制代码

yarn

早期的 npm 安装依赖速度慢,依赖管理混乱,所以提出了 yarnyarn 通过缓存和生产 package.json 文件这些方式来加快安装速度,依赖管理清晰。在 npm5 之后,npm 也借鉴了 yarn 的思想,现在两个已经性能相当


所以当有人问起 yarn 和 npm 的区别时,就可以说上面的话术,展开说说缓存策略和依赖管理方式。为了降低学习成本,所以两者命令上区别不大,

cnpm

概述

很多时候,我们下载一些依赖包的时候,从地址https://registry.npmjs.org 拉取用资源,会安装失败所以淘宝维护了一套淘宝源的镜像仓库,定时从https://registry.npmjs.org 去拉取最新包,便于国内开发下载

常用指令

查看 npm 镜像:


npm config get registry  
复制代码


我们可以直接设置 npm 的镜像


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


当我们想和原来的 npm 区分开时,也不想修改原有 npm 源时,建议使用 cnpm


npm install -g cnpm --registry=https://registry.npm.taobao.org cnpm config get registry
复制代码


返回 https://r.npm.taobao.org/ 则安装成功

npx 工具

概述

npx 是 npm5.2 之后自带的一个命令,一般用于它来调用项目中的某个模块

问题产生

我们以 webpack 为例:全局安装的是 webpack5 项目安装的是 webpack3 如果我在终端执行 webpack --version 使用的是哪一个命令呢?


显示结果会是 webpack5,事实上使用的是全局的,为什么呢?



原因非常简单,在当前目录下找不到 webpack 时,就会去全局找,并且执行命令;


那么我想使用 局部的 webpack 版本,该怎么办呢

解决方案

  • 方式一:在终端中使用如下命令(在项目根目录下)./node_modules/.bin/webpack --version

  • 方式二:修改 package.json 中的 scripts


   "scripts": {      "webpack": "webpack --version"
复制代码


  • 方式三:使用 npxnpx webpack --versionnpx 的原理非常简单,它会到当前目录的 node_modules/.bin 目录下查找对应的命令;

npm 发布自己的包

  • 注册 npm 账号:

  • https://www.npmjs.com/

  • 选择 sign up

  • 在命令行登录: npm login

  • 修改 package.json

  • 发布到 npm registry 上 :npm publish

  • 更新仓库:

  • 修改版本号(最好符合 semver 规范)

  • 重新发布

  • 删除发布的包: npm unpublish

  • 让发布的包过期: npm deprecate

总结

以 npm 为切入点,展开说了 npm 的属性和原理,方便大家理解,也简单介绍了其他包管理工具和 npm 比较相似的一些指令,希望能对大家有所帮助。


现在前端最火的应该是 pnpm,我在下篇文章会和大家分享,敬请期待



发布于: 刚刚阅读数: 4
用户头像

虎妞先生

关注

还未添加个人签名 2017-12-22 加入

还未添加个人简介

评论

发布
暂无评论
前端包管理工具 npm yarn cnpm npx_前端_虎妞先生_InfoQ写作社区