Npm 的内部原理以及镜像私服部署

存储
众所周知,前端发展到现在已经形成了完整的体系,除了框架的提高效率外,还有一系列的工程化操作。前端工程化离不开npm或yarn等管理工具,通过script串联起各个职能部分,让独立的环节自动运转起来。

[[435868]]

众所周知,前端发展到现在已经形成了完整的体系,除了框架的提高效率外,还有一系列的工程化操作。前端工程化离不开npm或yarn等管理工具,通过script串联起各个职能部分,让独立的环节自动运转起来。我们知道无论是npm还是yarn等管理工具的体积都是比较大的,那么实际使用过程中就会出现几个疑问:

  • 删除node_modules和lockfiles文件,再重新install,这样操作是否会存在风险呢?
  • 把所有依赖都安装在dependencies中,不区分devDependencies会有什么问题呢?
  • 应用依赖了公共库A和公共库B,同时A依赖了B,那么B会被多次进行安装或重复打包吗?
  • 一个项目中,既有人用npm,又有人使用了yarn,这会引发什么问题呢?
  • 我们是否应该将lockfiles文件push到项目仓库中?

1.npm的内部机制和核心原理

我们知道npm的核心目标就是给你和你的团队、你的公司带来最好的开源库和依赖。我们知道在使用npm进行项目启动最重要的环节就是安装相关包和依赖,而在安装过程中出现相关问题,最好的解决方法就是删除node_modules,重新进行npm install。

npm的安装机制优先安装依赖包到当前项目目录,使得各个项目依赖的包形成体系,可以减轻包的兼容性压力,但是缺点是同一个依赖包可能在电脑上安装多次。但是supervisor和gulp等可以使用全局安装模式,方便注册path环境变量,可以直接使用supervisor、gulp等命令。

当构建依赖树时,不管是当前依赖还是依赖的子依赖时,都应该按照扁平化原则优先将其放置node_modules根目录。在此过程 中,遇到相同模块就判断已放置在依赖树中的版本是否兼容此模块,符合则跳过,不符合则在当前node_modules目录下放置该模块。

前端工程中,依赖嵌套依赖,如果每个依赖包都从网络中获取安装,那么就增加了时间成本,如果node_modules安装包通过缓存进行获取,就提升了安装效率。对于一个依赖包的同一个版本进行本地化缓存,是当前依赖包管理工具的一个常见设计,可以通过命令npm config get cache进行获取缓存。当我们打开本地缓存_cache文件时,npm缓存有三个目录:

  • content-v2 二进制文件
  • index-v5 content-v2里文件索引
  • tmp 临时文件

2.npm缓存机制

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

当npm install执行时,通过pacote把相应的包解压到对应的node_modules下面

pacote依赖npm-registry-fetch来下载包,在给定的路径下根据IETF RFC 7234生成缓存数据

在每次安装资源时,根据package-lock.json中存储的integrity、version、name信息生成一个唯一的key

如果发现有缓存资源,就会找到tar包的hash,再次通过pacote把对应的二进制文件解压到对应的项目node_modules下面

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

3.如何验证组件的可行性

自定义npm init命令:npm init命令调用shell脚本输出一个初始化的package.json文件。

倘若在开发组件库时,某个组件开发完成后,如何验证该组件能在实际业务项目中正常运行呢?可以在组件库开发中,设计examples目录或者一个playground启动一个开发服务,以验证组件的运行情况。此外,还可以手动复制粘贴组件并打包产出到业务项目的node_modules中进行验证。

如何高效率在本地调试以验证包的可用性?使用npm link,将模块链接到对应的业务项目中运行。npm link的本质就是软链接,主要做了两件事情:

为目标npm模块(npm-package 1)创建软链接,将其链接到全局node模块安装路径/usr/local/lib/node_modules/中

为目标npm模块(npm-package 1)的可执行bin文件创建软链接,将其链接到全局node命令安装路径/usr/local/bin/中

简而言之,npm lick能够在工程中解决依赖包在任何一个真实项目中进行调试的问题,并且操作起来更加方便快捷。

4.npx的作用

在传统项目中使用eslint插件,需要先在命令行进行npm install eslint save-dev,然后再在项目进行命令行调用:

  1. ./node_modules/.bin/eslint --init 
  2.  
  3. ./node_modules/.bin/eslint yourfile.js 

而使用npx操作就非常便捷,只需要:

  1. npx eslint --init 
  2.  
  3. npx eslint yourfile.js 

之所以npx如此之便捷,是因为:

可以直接执行node_modules/.bin文件夹下的文件

可以自动去node_modules/.bin路径和环境变量$PATH里面检查命令是否存在

nox在执行模块时会优先安装依赖,但是在安装执行后便删除次依赖,这就避免了全局安装模块带来的问题。

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

例如:npm中的源(registry)对应地址是https://registry.npmjs.org/,我们在开发中常用nrm(npm的镜像源管理工具)进行源的切换和管理。为什么官方源有那么安全,公司还要自己进行部署内部使用的镜像源?原因有两点:

部署镜像后,可以确保高速、稳定的npm服务,使得发布私有模块更加安全

审核机制,保障私服上的npm模块质量和安全

如果我们要部署一个私有npm镜像,有三个工具分别是:

npm的配置优先级:

6.参考 

《前端基础设施建设与架构30讲》

 

责任编辑:武晓燕 来源: 前端万有引力
相关推荐

2015-02-11 11:12:00

Hadoop云部署IaaS

2024-01-10 09:48:52

Docker工具

2021-08-11 07:02:21

npm包管理器工具

2023-06-07 15:25:19

Kafka版本日志

2023-09-18 23:37:50

Kubernetes架构

2024-01-23 10:23:41

2023-10-08 07:45:34

Npm解析服务前端

2009-09-14 10:35:15

Linq内部执行原理

2018-06-05 08:36:47

内部部署云存储

2020-03-12 11:29:51

JavaScript浏览器语言

2020-03-05 16:47:51

Git内部储存

2009-08-05 18:49:11

XmlSerializ

2023-03-01 10:37:51

2023-09-27 12:22:50

Kafka架构

2011-10-08 14:09:27

JavaScript

2023-12-07 12:45:58

进程共享数据

2023-05-30 09:07:06

CPU性能火焰图

2023-09-10 07:20:35

2009-06-11 11:07:25

Java局部内部类Final类型

2023-08-08 00:06:31

点赞
收藏

51CTO技术栈公众号