npm内部机制与核心原理

npm 的核心目标:
Bring the best of open source to you, your team and your company.
npm 最重要的任务是安装和维护开源库。

npm 安装机制与背后思想

npm 的安装机制非常值得探究。Ruby 的 Gem,Python的pip都是全局安装机制,但是npm的安装机制秉承了不同的设计哲学。

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

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

下面的流程图体现了npm的安装机制:
在这里插入图片描述构建依赖树时,当前依赖项目无论是直接依赖还是子依赖,我们都应该遵循扁平化原则优先将其放置在node_modules根目录下。在这个过程中,遇到相同模块应先判断已放置在依赖树中的模块版本是否符合对新模块版本的要求,如果符合就跳过,不符合则在当前模块的node_modules下放置该模块。

npm 缓存机制

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

npm config get cache
// C:\Users\xxxxxx\AppData\Local\npm-cache

cd命令进入缓存目录可以看到_cacache文件夹。在npm v5版本之后,缓存数据均放在根目录的_cacache中请添加图片描述
content-v2: 存放一些二进制文件。为了使这些二进制文件可读,将文件的扩展名改为.tgz,然后进行解压,得到的结果其实就是npm包资源。
index-v5:存放一些描述性文件,事实上就是content-v2中文件的索引。
tmp:临时文件

这些缓存是如何被存储并利用的呢?

这就和npm install机制联系在一起了。当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 值找到缓存的包,并再次通过 pacote 将对应的二进制文件解压到相应的项目 node_modules 下,省去了网络下载资源的时间。

npm 不完全指南

自定义 npm init

npm 支持自定义 npm init,快速创建一个符合自己需求的自定义项目。npm init 命令本身并不复杂,它的功能其实就是调用Shell脚本输出一个初始化的package.json文件。相应地,我们要自定义 npm init 命令,就是写一个 Node.js 脚本,它的 module.exports 即为 package.json 配置内容。

为了实现更加灵活的自定义功能,我们可以使用 prompt() 方法,获取用户输入内容:

const desc = prompt('请输入项目描述', '描述...')
module.exports = {
    key: 'value',
    name: prompt('name?', process.cwd().split('/').pop()),
    version: prompt('version?', '0.1.1'),
    description: desc,
    main: 'index.js',
    repository: prompt('github repository url', '', function() {
        if (url) {
            run('touch README.md');
            run('git init');
            run('git add README.md');
            run('git commit -m "first commit"');
            run(`git remote add origin ${url}`);
            run('git push -u origin master');
        }
        return url
    })
}

假设该脚本名为.npm-init.js,执行以下命令来确保 npm init 所对应的脚本指向正确的文件

npm config set init-module ~\.npm-init.js

我们也可以通过配置 npm init 默认字段来自定义 npm init 内容:

npm config set init.author.name "Lucas"
npm config set init.author.email "xxx.com"
npm config set init.author.url "xxx.com"
npm config set init.license "MIT"
npx 的作用

npx 在 npm v5.2 版本中被引入,解决了使用 npm 时面临的快速开发、调试,以及在项目内使用全局模块的痛点。

在传统 npm 模式下,如果需要使用代码检测工具 ESLint,就要先进行安装,命令如下:

npm install eslint --save-dev

然后在项目根目录下执行命令,或通过项目脚本和 package.json 的 npm scripts 字段调用 ESLint。

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

而使用 npx 就简单多了:

npx eslint --init
npx eslint yourfile.js

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

npx 另一个更实用的特点是,它在执行模块时会优先安装依赖,但是在安装成功后便删除此依赖,避免了全局安装带来的问题。

npm 多源镜像和企业级部署私服原理

npm 中的源(regsitry) 其实就是一个查询服务。我们可以通过 npm config 命令来设置安装源或某个作用范围域对应的安装源,很多企业也会搭建自己的 npm 源。我们可以通过 npm-preinstall 的钩子和 npm 脚本,在安装公共依赖前自动切换源。

"scripts": {
  "preinstall": "node ./bin/preinstall.js"
}
// 其中 preinstall.js 脚本的逻辑是通过 Node.js 执行 npm config set 命令
require(' child_process').exec('npm config get registry', function(error, stout, stderr) {
  if (!stdout.toString().match(/registry\.x\/com/)) {
    exec('npm config set @xscope:registry https://xxx.com/npm/')
  }
})

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何部署npm私有仓库以及在项目中如何使用

如何部署npm私有仓库以及在项目中如何使用 为什么要部署npm私有仓库? 安全性:私有仓库允许团队存放内部研发的、不宜公开发布的代码包,只对特定用户或者团队可见和可用,从而保护公司的知识产权和商业秘密。模块的复用性&#xf…

GUI02-在窗口上跟踪并输出鼠标位置(Win32版)

(1) 响应 WM_MOUSEMOVE 消息获得鼠标位置; (2) 响应 WM_PAINT 将鼠标位置输出到窗口中; (3) 学习二者之间的关键步骤:调用 InvalidateRect() 以通知窗口重绘。 零. 课堂视频 在窗口上跟踪输出鼠标位置-Win32版 一、关键知识点 1. BeginPaint…

安装Milvus的可视化工具Attu教程

提供两种方式来安装可视化工具Attu 一、docker安装 # 执行命令,加个 -d 在后台运行 docker run -d -p 8000:3000 -e MILVUS_URL127.0.0.1:19530 zilliz/attu:v2.2.8 至此安装完成! 浏览器输入地址 http:127.0.0.1:8000即可访问 Attu主页 如果拉取最新…

windows下python opencv ffmpeg读取摄像头实现rtsp推流 拉流

windows下python opencv ffmpeg读取摄像头实现rtsp推流 拉流 整体流程1.下载所需文件1. 1下载rtsp推流服务器1.2 下载ffmpeg2. 开启RTSP服务器3. opencv 读取摄像头并调用ffmpeg进行推流4. opencv进行拉流整体流程 1.下载所需文件 1. 1下载rtsp推流服务器 下载 RTSP服务器 下…

Rust入门-所有权与借用

一、为什么、是什么、怎么用 1、为什么Rust要提出一个所有权和借用的概念 所有的程序都必须和计算机内存打交道,如何从内存中申请空间来存放程序的运行内容,如何在不需要的时候释放这些空间,成为所有编程语言设计的难点之一。 主要分为三种…

【opencv】dnn示例-vit_tracker.cpp 使用OpenCV库和ViTTrack模型实现的视频追踪程序

这段代码是一个使用OpenCV库和ViTTrack模型实现的视频追踪程序。程序通过摄像头或视频文件获取图像序列,并对选定的目标对象进行实时追踪。 代码主要分为以下几个部分: 导入必要的库:程序开始时先导入了iostream,cmath以及相关Ope…

Hive进阶(4)----MapReduce的计算过程(赋图助君理解)

MapReduce的计算过程 MapReduce是一种编程模型和处理大规模数据集的方法。它通常用于分布式计算环境中,能够将数据处理任务分解成独立的部分,分配给多台计算机进行并行处理。这个模型由Google提出,并在开源领域中得到了广泛的应用和实现。Map…

CSS显示模式

目录 CSS显示模式简介 CSS显示模式的分类 块元素 行元素 行内块元素 元素显示模式的转换 使块内文字垂直居中的方法 设计简单小米侧边栏(实践) CSS显示模式简介 元素显示模式就是元素(标签)以什么方式进行显示&#xff0…

前端三剑客 HTML+CSS+JavaScript ② HTML相关概念

他们这样形容我 是暴雨浇不灭的火 —— 24.4.18 学习目标 理解 HTML的概念 HTML的分类 HTML的关系 HTML的语义化 应用 HTML骨架格式 sublime基本使用 一、HTML初识 HTML指的是超文本标记语言,是用来描述网页的一种语言 超文本:暂且理解为“超级的文本”&…

BNB链融合

BNB Chain融合 BNB Chain目前有BNB智能链(BSC),BNB信标链 BNB信标链:用作质押和投票的治理层,采用BEP-2代币标准BNB智能链(BSC):用作EVM兼容层,提供DApp、DeFi服务、共识层、多链支持和其他Web3…

【AI工具之Prezo如何自动生成PPT操作步骤】

先说优缺点: 最大的优点就是免费(但说实话功能和体验方面很弱)支持中文提问(最好用英文),智能生成图文(但是只能生成英文内容)可以AI生成图片,图片很精美酷炫&#xff0…

Hive进阶(2)----HDFS写入数据流程(赋图助君理解)

HDFS写入数据流程 一、写入流程 1、 Client向NameNode发起RPC请求,来确定请求文件block所在的位置; 2、 NameNode会视情况返回文件的部分或者全部block列表,对于每个block,NameNode都会返回含有该block副本的DataNode地址&…

三、fpga对完成过滤和校验的有效包数据进行有效像素提取、MATLAB对数据源进行处理与下发(完整实现pc机→显示器通信链路)

前言:上篇文章实现了MATLAB模拟发送UDP以太网协议数据包到fpga,能实现双沿数据→单沿数据转换,并将转换后的数据进行包过滤和crc校验,本篇内容要实现真正的从pc机下发视频数据,经过千兆以太网传输存储到fpga 的ddr3中,然后通过hdmi读出到显示屏上。 文章目录 一、模块设…

Tensorflow小技巧01:检测本地Tensorflow的版本

前言: 以Pycharm为例,Windwos10系统,检测本地环境的Tensorflow的版本: 1 打开Pycharm窗口 2 在窗口中输入: pythonPython 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win…

面试经典算法系列之二叉树17 -- 验证二叉树

面试经典算法32 - 验证二叉树 LeetCode.98 公众号:阿Q技术站 问题描述 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当…

视频教程下载:用ChatGPT快速提升股票投资能力

学完此视频后可以获得: 学习如何使用人工智能/Chatgpt进行基础/快速/高级财务与研究分析 学习如何使用人工智能/Chatgpt对任何公司进行定性投资研究 学习如何使用人工智能/Chatgpt对任何公司进行定量投资研究 学习如何使用人工智能/Chatgpt创建、预测和分析财务…

考研日常记录

由于实在太无聊了 , 所以记录以下考研备考日常 , 增加一点成就感 , 获得一点前进动力。 2024.4.18 周四 课程情况: 无课 时间规划: 上午:休息 下午: 事项耗时进度备注写作业1h复习英语单词…

低噪声放大器是如何实现低噪声放大的功能的

灵敏度作为接收机最重要的指标之一,直接决定了接收机能分辨的最小信号。接收机的灵敏度计算公式如下所示。 Psensitivity=-174dBm+NF+10*lg(BW)+SNR 由接收机灵敏度的计算公式可知,影响接收机灵敏度的指标有噪声系数、带宽和信噪比,因此一旦带宽和信噪比确定了,那么能决…

隧道网络对讲广播音频终端-智慧工地网络报警求助箱

隧道网络对讲广播音频终端-智慧工地网络报警求助箱 SV-6007 网络对讲求助终端 一、描述 SV-6007是我司的一款壁挂式双按键求助对讲终端,具有10/100M以太网接口,其接收网络的音频数据,实时解码播放,还配置了麦克风输入和扬声器输…

[Qt网络编程]之UDP通讯的简单编程实现

hello!欢迎大家来到我的Qt学习系列之网络编程之UDP通讯的简单编程实现。希望这篇文章能对你有所帮助!!! 本篇文章的相关知识请看我的上篇文章: http://t.csdnimg.cn/UKyeM 目录 UDP通讯 基于主窗口的实现 基于线程的实现 UDP通讯…