从自定义文件系统目录透明地离线安装 npm 包

Posted

技术标签:

【中文标题】从自定义文件系统目录透明地离线安装 npm 包【英文标题】:Transparently install npm packages offline, from a custom filesystem directory 【发布时间】:2016-08-07 22:21:03 【问题描述】:

编者注:问题的原标题是“Use npm install to install node modules stored on a local directory”,这使得透明重新定义的愿望安装源不太明显。因此,一些现有的答案建议基于修改安装过程的解决方案。

我知道这是一件简单的事情,但我对这方面的任何事情都很陌生,所以在四处寻找并不断找到并不是我真正想要的答案后,我想我会直接问。

我目前有一个在 FOO 目录中运行的进程,它调用 npm install。目录 FOO 包含一个 package.json 和一个 npm-shrinkwrap.json 文件,用于指定模块(在本例中为 bluebird、extend 和 mysql,但并不重要)和版本。这一切都很好。

但是现在我不想通过互联网获取模块,而是希望将它们存储在本地目录 BAR 中并在 foo 中使用 npm 从那里安装它们。我不能将它们永久存储在 FOO 中,但由于我无法控制的原因,我可以将它们存储在 BAR 中。我知道这相对简单,但我似乎无法获得正确的命令集。感谢您的帮助。

【问题讨论】:

我也想知道这个。我有一份詹金斯的工作,我不想每次都从互联网上下载我所有的 npm 依赖项。我希望他们在一个地方。还没找到好办法。 【参考方案1】:

如果存在收缩包装文件,则忽略 package.json。您需要做的是使用诸如sed ... 之类的查找和替换操作来更改要检索的URL。但是我不确定将 URL 更改为 file:/// 语法是否有效,但请试一试。

【讨论】:

【参考方案2】:

注意:这个答案最初建议重新定义缓存位置。虽然这在原则上可行,但npm 仍会尝试为每个包裹联系网络,从而导致过度延迟。

我假设你的意图是透明地更改安装源:换句话说:你不想更改你的包,你只是想调用@987654323 @ 和以前一样,但是从您的自定义文件系统位置离线安装软件包(无需互联网连接)。

这个难题有两个部分:

重新定义 npm 的缓存文件系统位置(之前下载的包被缓存的地方)以指向您的自定义位置:

请注意,缓存包以特定方式存储:package.json 文件存储在子文件夹package 中,压缩包作为一个整体存储为package.tgz。将包从现有缓存复制到自定义位置是最简单的方法,或者在有 Internet 连接时简单地安装额外需要的包,这会自动缓存它们。

对于透明使用(npm install可以照常调用):

通过设置配置项全局npm config set cache '/path/to/BAR' 请注意,这将对所有 npm 操作持续生效。 通过环境变量(可以限定为脚本甚至单个命令): export npm_config_cache='/path/to/BAR' npm_config_cache='path/to/BAR' npm install Ad-hoc 通过命令行选项使用: npm install --cache /path/to/BAR

强制npm 使用缓存包:

目前,这需要通过cache-min 配置项解决。 更直接的功能,例如通过--offline 开关,多年来一直是功能请求 - 请参阅https://github.com/npm/npm/issues/2568 诀窍是将cache-min 设置为一个非常高的值,以便缓存中的所有包都被认为是新鲜的并从那里提供: 对于 transparent 使用(npm install 可以照常调用): 通过设置配置项全局npm config set cache-min 9999999999 请注意,这将对所有 npm 操作持续生效。 通过环境变量(可以限定为脚本甚至单个命令): export npm_config_cache_min=9999999999 npm_config_cache_min=9999999999 npm install Ad-hoc 通过命令行选项使用: npm install --cache-min 9999999999

假设您已在全局范围内或通过环境变量设置 cache-min, 运行 npm install 现在应该直接从您的自定义缓存位置提供包。

注意事项

这假设 所有 包您的 npm install 需要在您的自定义位置可用;如果没有 Internet 连接,尝试安装不在缓存中的软件包显然会失败

相反,如果您确实可以访问 Internet,但希望 防止 npm 使用它来获取包 - 如果在缓存中找不到包,它仍然会尝试 - 您必须更改将registry配置项设置为无效,从而强制在线安装尝试失败;例如:

export npm_config_registry=http://example.org 请注意,URL 必须存在以避免npm 尝试连接它时出现延迟;虽然您可以将值设置为语法无效的值(例如,none),但npm 会在每次使用时发出警告。

示例bash 脚本:

#!/usr/bin/env bash

# Set environment variables that set npm configuration items to:
#  - redefine the location of the cache folder
#  - make npm look in the cache only (assuming the packages are there)
# Note that by doing this inside a script the changes will only take effect
# in the script and NOT persist.
export npm_config_cache='/path/to/BAR' npm_config_cache_min=9999999999

# Now cd to your package and invoke `npm install` as usual.
cd '/path/to/project'
npm install

【讨论】:

这似乎是我正在寻找的(对不起,如果问题不是很清楚)。看起来确实比我想象的要复杂一些。如果我为此重新定义缓存会影响 npm 在其他地方使用吗? (所以我这样做了,然后有人在第三个目录中做某事,他们需要快速执行一次 npm install 来做任何事情。假设我有问题,或者缓存更改只对这个脚本生效,把它放在脚本里?) @JediWolf:如果您全局更改npm配置项(使用npm config set ...,那么,是的,所有未来的npm操作都会受到影响。如果不希望这样做,请使用命令行参数或使用环境变量在脚本中 - 请参阅我的更新。 我设置了这一切,它似乎工作,但如果我将缓存目录设置为不存在的东西,npm 仍然会安装文件。那么如果它在缓存目录中找不到文件,它只是去互联网,还是我做错了什么? @JediWolf。是的,如果缓存不包含软件包,npm 仍然会在线 - 在没有真正的离线安装功能的情况下,这就是它的工作原理。我已经用解决方法更新了答案。 好的,再次感谢,对不起,我一直在想我在原始问题中没有完全说明的事情。我试图使用不正确的目录作为一个简单的检查来确保它的工作(如果它因错误的目录而失败但与正确的目录一起工作)。是否有一种简单的方法来确保其正常工作(从本地目录获取文件?)我不一定需要切断 npm 的互联网访问,只是确保我已正确完成所有操作。【参考方案3】:

您可能想试试npm link。你可以:

    下载依赖 从依赖目录运行npm link 从你的项目运行npm link mycrazydependency

详情在这里:https://docs.npmjs.com/cli/link

【讨论】:

我认为OP的意图是透明地更改安装源,而无需修改包。

以上是关于从自定义文件系统目录透明地离线安装 npm 包的主要内容,如果未能解决你的问题,请参考以下文章

如何在离线时安装 npm 包?

如何在Docker文件中从自定义文件通道安装conda包?

nodejs应用离线安装部署卸载

项目中的yarn.lock文件的作用

NPM离线包的制作和使用

NPM离线包的制作和使用