当前位置: 首页 > Web前端 > HTML

你不知道npm

时间:2023-03-28 12:52:10 HTML

npm前端工程离不开npm(节点包管理器)或Yarn等管理工具。在工程项目中,npm或Yarn不仅负责依赖的安装和维护,还通过npm脚本将各个功能部分连接起来,让独立的链接自动运行。npm的诞生背景npm是由程序员isaacs(https://github.com/isaacs)发明的。他最初的想法是集中管理所有的模块,所有的模块都上传到仓库(registry)。在模块中创建一个package.json,标记模块的基本信息,如模块名称、版本、依赖库等,然后通过npmpublish发布模块并上传到npm仓库(registry),以及最后通过npminstall安装模块,将模块安装到node_modules目录下。npm于2014年商业化,2020年被Github收购。npm简介npm解决的核心问题是模块管理。npm包括三部分:cli脚手架、模块仓库、官网(https://www.npmjs.com/)。npm的相关信息可以查看:https://docs.npmjs.com/about-npm生成模块首先通过npminit创建一个模块,创建的模块包含package.json,我们修改名称、版本、依赖项为确定模块的基本信息,如果模块要使用其他模块,需要使用npminstall安装其他模块,并将模块下载到node_modules目录下,模块中还包含package.json和node_modules。这是npm的规范。module1开发完成后,调用npmpublish上传到npmregistry。注册表由两部分组成,一部分是公开的,任何人都可以使用,另一部分是私有的。现在npm商业化后主要由私有仓库收费。公共共享仓库分为两种,一种是普通仓库,一种是组织仓库。常用的npm命令如下:npminit:创建模块npminstall:安装模块npmpublish:发布模块npmlink:关联本地模块进行本地开发npmconfig:查看或调整本地配置npmrun:调用脚本npm限制npm只能解析modules大学管理和获取的问题无法解决性能加载性能的问题。因此,模块化发明后,制约其广泛应用的因素就是性能因素。npm的内部机制和核心原则让我们看一下npm的核心目标:为您、您的团队和您的公司带来最好的开源。为您、您的团队和您的公司带来最好的开源库和依赖项。通过这句话我们可以知道npm最重要的部分就是安装和维护依赖。在平时的开发中,“删除node_modules,重新npminstall”是解决npm安装问题的一个屡试不爽的方法。npm安装机制及其背后的思想会优先将依赖包安装到当前项目目录下,使得不同应用项目的依赖成为一个系统,同时减轻包作者的API兼容压力,但缺陷这一点也很明显:如果我们的项目A和项目B都依赖同一个公共库C,那么公共库C一般会在项目A和项目B中分别安装一次。这意味着同一个依赖包可能会在我们的电脑上安装多次。当然,对于supervisor、gulp等一些工具模块,仍然可以使用全局安装方式,方便注册路径环境变量,我们可以在任何地方直接使用supervisor和gulp命令。(不过一般建议不同的项目维护自己本地的gulp开发工具,以满足不同项目的需求)配置。这里的优先级是:项目级.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规范).在这个过程中,遇到相同的模块时,判断放置在依赖树中的模块的版本是否符合新模块的版本范围,如果符合则跳过;如果不匹配,则将该模块放在当前模块(最新版本的npm规范)的node_modules下。图中标示了npm不同版本的不同处理情况,从这个“历史问题”中学习总结npm使用的团队最佳实践:同一个项目组要保证npm版本一致。npm缓存机制在本地缓存同一个版本的依赖包,这是当代依赖包管理工具的普遍设计。使用时,先执行如下命令:npmconfiggetcache通过该命令可以获取配置缓存的根目录在C:\Users\用户名\AppData\Local\npm-cache(mac在/Users/username/.npm),我们cd进入C:\Users\username\AppData\Local\npm-cache以找到_cacache文件。npmv5之后,缓存数据放在根目录下的_cacache文件夹中。可以使用如下命令清除C:\Users\用户名\AppData\Local\npm-cache\_cacache中的文件npmcacheclean--force在_cacache目录下,有三个目录:content-v2index-v5tmp,其中content-v2里面基本上都是一些二进制文件。为了让这些二进制文件可读,我们把二进制文件的扩展名改成.tgz,然后解压,结果其实就是我们的npm包资源。在index-v5文件中,我们可以用刚才一样的操作得到一些描述文件。其实这些内容就是content-v2中文件的索引。那么这些缓存是如何产生的呢?执行npminstall时,通过pacote将对应的包解压到对应的node_modules下。npm下载依赖时,先下载到缓存中,然后解压到项目node_modules中。pacote依赖npm-registry-fetch下载包,npm-registry-fetch可以根据IETFRFC7234通过设置cache属性在给定路径中生成缓存数据。然后,每次安装一个资源,根据package-lock.json中存储的完整性、版本、名称信息生成一个唯一的key,这个key可以对应index-v5目录下的缓存记录。如果找到缓存的资源,就会找到tar包的hash,然后根据hash找到缓存的tar包,通过pacote再次将对应的二进制文件解压到对应的项目node_modules中,节省了从中下载资源的开销网络。注意这里提到的缓存策略来自npmv5版本。在npmv5版本之前,每个缓存的模块直接以模块名的形式存储在~/.npm文件夹>>,存储结构为:{cache}/{name}/{version}。npm使用技巧配置npminit默认字段自定义npm内容initnpmconfigsetinit.author.name"test"npmconfigsetinit.author.email"test@gmail.com"npmconfigsetinit.author.url"test.com"npmconfigsetinit.license"MIT"更多信息参见:npm-config利用npmlink在本地高效调试验证包的可用性使用npmlink将模块链接到对应的业务项目运行,从工作原理上总结一下,npmlink的本质就是软链接。主要做了两件事:为目标npm模块创建一个软链接,链接到全局node模块安装路径C:\Users\username\AppData\Roaming\npm\node_modules(mac在/usr/local/lib/node_modules/)为目标npm模块的可执行bin文件创建一个软链接,链接到全局node命令安装路径/usr/local/bin/。npx的作用npx是npmv5.2引入的,解决了使用npm进行快速开发调试的一些痛点,以及项目中全局模块的使用。在传统的npm模式下,如果我们需要使用代码检测工具ESLint,首先要通过npminstall安装npminstalleslint--save-dev然后在项目根目录下执行:./node_modules/.bin/eslint--在里面。/node_modules/.bin/eslintyourfile.js使用npx就简单多了,只需要下面两步:npxeslint--initnpxeslintyourfile.js这是因为可以直接在node_modules/.bin文件夹下执行文档。运行命令时,npx可以自动进入node_modules/.bin路径和环境变量$PATH检查命令是否存在,而无需在package.json中定义相关脚本。npx另一个比较实用的好处是:npx在执行模块时,会先安装依赖,安装完成后删除依赖,避免了模块全局安装带来的问题。比如我们使用create-react-app来创建一个项目。npxcreate-react-appcra-projectnpx会把create-react-app下载到一个临时目录下,使用完后删除相关文章