你不知道的npm

news2024/11/26 1:37:23

npm

前端工程化离不开 npm(node package manager) 或者 Yarn 这些管理工具。npm 或 Yarn 在工程项目中,除了负责依赖的安装和维护以外,还能通过 npm scripts 串联起各个职能部分,让独立的环节自动运转起来。

npm诞生背景

npm由程序员isaacs(https://github.com/isaacs)发明,他的初步思路是集中管理所有的模块,所有的模块都上传到仓库中(registry)。在模块内创建package.json标注模块的基本信息,像模块名、版本、依赖库等等,然后通过npm publish发布模块上传倒npm仓库中(registry),最后通过npm install安装模块,模块安装到node_modules目录下。npm于2014年商业化,2020年被Github收购。

npm介绍

npm解决的核心问题是模块管理问题,npm包含cli脚手架、模块仓库、官网(https://www.npmjs.com/)三大部分。

关于npm的相关信息可以查阅:https://docs.npmjs.com/about-npm

在这里插入图片描述

产生一个模块首先通过npm init来创建一个模块,创建的模块中包含package.json,我们通过修改name、version、dependencies来确定模块的基本信息,如果模块想使用其他的模块则需要使用npm install来安装其他的模块,将模块下载到node_modules目录中,其中模块也包含package.json和node_modules这就是npm的规范。

当module1开发完成后,调用npm publish上传到npm registry中,registry包含两部分,一部分是public公开的,任何人都能使用,另一部分是private私有的,现在npm商业化后主要靠私有仓库收费。

public共有仓库又分为两种,一种是普通的仓库,一种是组织的仓库。

常见的npm命令如下:

  • npm init:创建模块
  • npm install:安装模块
  • npm publish:发布模块
  • npm link:关联本地模块进行本地开发
  • npm config:查看或调整本地配置
  • npm run:调用scripts

npm的局限

npm只能解决模块的高校管理和获取问题,无法解决性能加载性能问题。所以模块化发明后,制约其广泛应用的因素就是性能因素。

npm内部机制和核心原理

我们先来看看 npm 的核心目标:

Bring the best of open source to you, your team and your company.
给你和你的团队、你的公司带来最好的开源库和依赖。

通过这句话,我们可以知道 npm 最重要的一环是安装和维护依赖。在平时开发中,“删除 node_modules,重新 npm install”是一个百试不爽的解决 npm 安装类问题的方法。

npm 的安装机制和背后思想

它会优先安装依赖包到当前项目目录,使得不同应用项目的依赖各成体系,同时还减轻了包作者的 API 兼容性压力,但这样做的缺陷也很明显:如果我们的项目 A 和项目 B,都依赖了相同的公共库 C,那么公共库 C 一般都会在项目 A 和项目 B 中,各被安装一次。这就说明,同一个依赖包可能在我们的电脑上进行多次安装。

当然,对于一些工具模块比如 supervisor 和 gulp,你仍然可以使用全局安装模式,这样方便注册 path 环境变量,我们可以在任何地方直接使用 supervisor、 gulp 这些命令。(不过,一般还是建议不同项目维护自己局部的 gulp 开发工具以适配不同项目需求。)

npm的安装机制如下图所示:

在这里插入图片描述

npm install 执行之后,首先,检查并获取 npm 配置,这里的优先级为:项目级的 .npmrc 文件 > 用户级的 .npmrc 文件> 全局级的 .npmrc 文件 > npm 内置的 .npmrc 文件。

然后检查项目中是否有 package-lock.json 文件。

如果有,则检查 package-lock.json 和 package.json 中声明的依赖是否一致:

  • 一致,直接使用 package-lock.json 中的信息,从缓存或网络资源中加载依赖;
  • 不一致,按照 npm 版本进行处理(不同 npm 版本处理会有不同,具体处理方式如图所示)。

如果没有,则根据 package.json 递归构建依赖树。然后按照构建好的依赖树下载完整的依赖资源,在下载时就会检查是否存在相关资源缓存:

  • 存在,则将缓存内容解压到 node_modules 中;
  • 否则就先从 npm 远程仓库下载包,校验包的完整性,并添加到缓存,同时解压到 node_modules。

最后生成 package-lock.json。

构建依赖树时,当前依赖项目不管其是直接依赖还是子依赖的依赖,都应该按照扁平化原则,优先将其放置在 node_modules 根目录(最新版本 npm 规范)。在这个过程中,遇到相同模块就判断已放置在依赖树中的模块版本是否符合新模块的版本范围,如果符合则跳过;不符合则在当前模块的 node_modules 下放置该模块(最新版本 npm 规范)。

图中标明的 npm 不同版本的不同处理情况,并学会从这种“历史问题”中总结 npm 使用的团队最佳实践:同一个项目团队,应该保证 npm 版本的一致。

npm缓存机制

对于一个依赖包的同一版本进行本地化缓存,是当代依赖包管理工具的一个常见设计。使用时要先执行以下命令:

npm config get cache

通过这行命令可以得到配置缓存的根目录在C:\Users\用户名\AppData\Local\npm-cache(mac在/Users/用户名/.npm),我们 cd 进入C:\Users\用户名\AppData\Local\npm-cache中可以发现_cacache文件。在 npm v5 版本之后,缓存数据均放在根目录中的_cacache文件夹中。

在这里插入图片描述

可以使用以下命令清除C:\Users\用户名\AppData\Local\npm-cache_cacache 中的文件

npm cache clean --force

在_cacache目录下,有三个目录:

  1. content-v2
  2. index-v5
  3. tmp

其中 content-v2 里面基本都是一些二进制文件。为了使这些二进制文件可读,我们把二进制文件的扩展名改为 .tgz,然后进行解压,得到的结果其实就是我们的 npm 包资源。

而 index-v5 文件中,我们采用跟刚刚一样的操作就可以获得一些描述性的文件,事实上这些内容就是 content-v2 里文件的索引。

那么这些缓存是如何生成的呢?

当 npm install 执行时,通过pacote把相应的包解压在对应的 node_modules 下面。npm 在下载依赖时,先下载到缓存当中,再解压到项目 node_modules 下。pacote 依赖npm-registry-fetch来下载包,npm-registry-fetch 可以通过设置 cache 属性,在给定的路径下根据IETF RFC 7234生成缓存数据。

然后在每次安装资源时,根据 package-lock.json 中存储的 integrity、version、name 信息生成一个唯一的 key,这个 key 能够对应到 index-v5 目录下的缓存记录。如果发现有缓存资源,就会找到 tar 包的 hash,根据 hash 再去找缓存的 tar 包,并再次通过pacote把对应的二进制文件解压到相应的项目 node_modules 下面,省去了网络下载资源的开销。

注意

这里提到的缓存策略是从 npm v5 版本开始的。在 npm v5 版本之前,每个缓存的模块在 ~/.npm 文件夹> > 中以模块名的形式直接存储,储存结构是:{cache}/{name}/{version}。

npm的使用技巧

配置 npm init 默认字段来自定义 npm init 的内容

npm config set init.author.name "test"
npm config set init.author.email "test@gmail.com"
npm config set init.author.url "test.com"
npm config set init.license "MIT"

更多信息见:npm-config

利用 npm link,高效率在本地调试以验证包的可用性

使用 npm link可以将模块链接到对应的业务项目中运行,从工作原理上总结,npm link 的本质就是软链接,它主要做了两件事:

  • 为目标 npm 模块创建软链接,将其链接到全局 node 模块安装路径 C:\Users\用户名\AppData\Roaming\npm\node_modules(mac在/usr/local/lib/node_modules/)中
  • 为目标 npm 模块的可执行 bin 文件创建软链接,将其链接到全局 node 命令安装路径 /usr/local/bin/ 中。

npx 的作用

npx 由 npm v5.2 版本引入,解决了 npm 的一些使用快速开发、调试,以及项目内使用全局模块的痛点。

在传统 npm 模式下,如果我们需要使用代码检测工具 ESLint,就要先通过 npm install 安装

npm install eslint --save-dev

然后在项目根目录下执行:

./node_modules/.bin/eslint --init
./node_modules/.bin/eslint yourfile.js

而使用 npx 就简单多了,你只需要下面 2 个操作步骤:

npx eslint --init
npx eslint yourfile.js

这是因为它可以直接执行 node_modules/.bin 文件夹下的文件。在运行命令时,npx 可以自动去 node_modules/.bin 路径和环境变量 $PATH 里面检查命令是否存在,而不需要再在 package.json 中定义相关的 script。

npx 另一个更实用的好处是:npx 执行模块时会优先安装依赖,但是在安装执行后便删除此依赖,这就避免了全局安装模块带来的问题。
例如我们使用create-react-app创建工程。

npx create-react-app cra-project

npx 会将 create-react-app 下载到一个临时目录,使用以后再删除

相关文章

  • 前端工程化 - 剖析npm的包管理机制

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/48383.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

跨平台.NET应用UI组件DevExpress XAF v22.1 - 增强Web API Service

DevExpress XAF是一款强大的现代应用程序框架,允许同时开发ASP.NET和WinForms。DevExpress XAF采用模块化设计,开发人员可以选择内建模块,也可以自行创建,从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。&#xff…

Web进阶

目录 DOM节点操作(上) 一、任务目标 二、任务背景 三、任务内容 1、DOM结构及节点 DOM节点操作(下) 一、任务目标 二、任务背景 三、任务内容 1、DOM修改 DOM控制CSS样式 一、任务目标 二、任务背景 三、任务内容 …

达摩院快速动作识别TPS ECCV论文深入解读

一、论文&代码 论文:https://www.ecva.net/papers/eccv_2022/papers_ECCV/papers/136630615.pdf 模型&代码:ModelScope 魔搭社区 二、背景 高效的时空建模(Spatiotemporal modeling)是视频理解和动作识别的核心问题。相较于图像的Transforme…

ArrayList源码分析

ArrayList源码分析 注意:本笔记分析对象为 Java8 版本,随版本不同,源码会发生变化。 1 ArrayList类图与简介 ArrayList是一个 非线程安全,基于数组实现的一个动态数组。可以看到,它的顶层接口是 Collection<E> 集合类。 Note: ArrayList 可以存放所有元素,包括 n…

C语言详细知识点(下)

⛄️上一篇⛄️C语言详细知识点&#xff08;上&#xff09; 文章目录五、数组1、一维数组的定义及使用2、二维数组的定义及使用3、字符数组的定义及使用六、函数1、函数的定义2、函数的调用3、函数的声明4、函数的嵌套调用5、函数的递归调用七、指针1、什么是指针2、指针变量3、…

如何用蓝牙实现无线定位(二)--信号塔设置

1. 配置BLE4.0模块 根据三点定位原理&#xff0c;本项目需要使用3个信号塔。3个信号塔的主体均为BLE4.0模块&#xff0c;需要把BLE4.0模块的AT指令设置为“从设备”。 方法为&#xff1a; &#xff08;1&#xff09;给控制板刷一套空的程序。初始打开arduino IDE或新建&#x…

RabbitMQ事务消息

通过对信道的设置实现 channel.txSelect()&#xff1b;通知服务器开启事务模式&#xff1b;服务端会返回Tx.Select-Ok channel.basicPublish&#xff1b;发送消息&#xff0c;可以是多条&#xff0c;可以是消费消息提交ackchannel.txCommit() &#xff1b;提交事务&#xff1b;…

Devkit开发框架插件工具——Gzip工程创建

Devkit开发框架插件工具——Gzip工程创建 基于鲲鹏亲和开发框架进行原生开发&#xff0c;创建通用计算功能。 二、 操作前提。 1、 在鲲鹏社区申请远程实验室&#xff0c;操作系统选择OpenEuler。 点击链接&#xff1a;鲲鹏社区-官网丨凝心聚力 共创行业新价值&#xff0c;打…

[附源码]Python计算机毕业设计Django的网上点餐系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;我…

蓝牙耳机什么牌子音质最好?高音质蓝牙耳机盘点

如今蓝牙耳机是越来越获得大众的喜爱了&#xff0c;越来越多的年轻人都离不开它了&#xff0c;很多人在买耳机的时候会在意蓝牙耳机的音质&#xff0c;毕竟在自己的耳朵里面听到完美的音乐还是很重要的。下面为大家介绍几款音质超赞的无线蓝牙耳机。 1、南卡小音舱 蓝牙版本&…

关于使用图表控件LightningChart的十大常见问题及解答

LightningChart是芬兰的一款高性能图表开发控件&#xff0c;其中的LightningChart .NET支持实时可视化1万亿个数据点&#xff0c;且可以直接用于.NET WinForms、WPD、传统的Win32 C的应用程序中&#xff1b;而LightningChart JS是一款性能极高的JavaScript图表库&#xff0c;专…

如何设计高可用架构

高可用复杂度模型 计算高可用 任务分配 将任务分配给多个服务器执行 复杂度分析 增加“任务分配器”节点&#xff0c;可以是独立的服务器&#xff0c;也可以是SDK任务分配器需要管理所有的服务器&#xff0c;可以通过配置文件&#xff0c;也可以通过配置服务器&#xff08;例…

2023 年 10 大 Web 开发趋势

公司的在线形象是最重要的。您使用的平台越多&#xff0c;您就会变得越成功&#xff01;拥有在线形象的困难部分是脱颖而出。如果你没有有趣的东西可以提供&#xff0c;你会迷失在人群中。 除了网站具有的基本功能外&#xff0c;您还需要拥有更多功能才能使您的网站具有可持续…

基于BDD的接口自动化框架开箱即用

1、背景说明 项目思想&#xff1a;BDD 行为驱动开发的思想褒贬不一&#xff0c;这里不多说。遵循的宗旨能解决业务痛点的思想就是好思想。 接口测试工具在实际的业务测试场景中往往会遇到一些使用上的局限性&#xff0c;自定义扩展要求技术较高&#xff0c;如果二次开发工具…

平安康养的生意经:养老的壳,金融的核

图片来源Unsplash 文丨螳螂观察 作者丨陈淼 根据第七次人口普查数据&#xff0c;我国60岁及以上老年人口占总人口的比重为18.7%&#xff0c;人口结构即将进入中度老龄化。而伴随着社会老龄化趋势的加剧&#xff0c;背后的养老市场也在迎来巨大的商业化增长。 现阶段&#x…

下班路上捡了一部手机,我用8年开发知识主动找到了失主

☆ 我们学习开发知识&#xff0c;其实并不是只解决当前用户的需求&#xff0c;实现UI原型的还原&#xff0c;不应该只把自己嵌套在当前的浏览器或者某个docker的环境下。 因为不管你在tomcat或者数据库里折腾得再欢&#xff0c;可能到了生活中发现自己失去了超能力。 ☆ 记得有…

校园论坛(Java)——环境配置篇

校园论坛&#xff08;Java&#xff09;——环境配置篇 文章目录校园论坛&#xff08;Java&#xff09;——环境配置篇1、写在前面2、新建Maven项目2.1 引入相关依赖2.2 配置Tomcat环境3、项目发布测试4、项目代码5、参考资料1、写在前面 Windows版本&#xff1a;Windows10JDK版…

Vue中数据代理与事件处理

目录 数据代理 Object.defineProperty 常见属性值 get和set函数 理解数据代理 Vue中的数据代理 Vue中的数据代理小结 事件处理 v-bind 事件处理小结 数据代理 Object.defineProperty 常见属性值 <body> <script type"text/javascript"> let per…

你的数据库到底应该如何存储密码?

最近接手公司一个之前的服务&#xff0c;竟然发现用户密码是明文存储在数据库中&#xff01; 说实话还是有点吃惊的&#xff0c;这可不兴学 CSDN 呀&#xff08;手动狗头&#xff09;&#xff0c;至少也得搞个 MD5 存一存吧。 不过 MD5 其实也没啥用&#xff0c;今天我们就来…

阿里P7告诉你,接口测试真的很简单,有手就行

一、什么是接口测试&#xff1f; 所谓接口&#xff0c;是指同一个系统中模块与模块间的数据传递接口、前后端交互、跨系统跨平台跨数据库的对接。而接口测试&#xff0c;则是通过接口的不同情况下的输入&#xff0c;去对比输出&#xff0c;看看是否满足接口规范所规定的功能、…