【发布时间】:2026-02-06 22:10:01
【问题描述】:
我们的 Jenkins/CI 服务器每天为我们的 node/js 项目运行数百次构建,我希望能够在完全干净的工作区中运行每个构建。但是,npm install 步骤可能需要超过 10 分钟,这太慢了。相反,由于我们的 npm 依赖项仅针对少量构建(约占所有构建的 1%)发生变化,因此我只想在每次 npm-shrinkwrap.json 更改时运行一次 npm install(每次构建时检查 md5sum)。如果收缩包装文件没有更改,请使用缓存的node_modules/ 目录。
如果我复制缓存的node_modules/,此计划运行良好,但即使该操作也可能需要一分钟。为了进一步优化我们的构建时间,我希望能够符号链接到缓存的node_modules/,这将大大提高我们的整体构建性能。
ln -s /path/to/cache/ /path/to/workspace/node_modules
但是,在依赖关系树的多个级别存在依赖关系的情况下,简单地对缓存路径进行符号链接是行不通的。例如,我们的*项目同时依赖于gulp 和gulp-util。顶层依赖也依赖于gulp-util。在npm install 之后,gulp-util 将安装在* node_modules/ 中,但不会安装在 node_modules/gulp/node_modules 中。
如果本地工作区中存在依赖项(即真实目录/path/to/workspace/node_modules/),那么node_modules/gulp 中的任何require('gulp-util') 实例都会(我认为)递归依赖关系树,直到找到合适的gulp-util模块。也就是说,它开始在 /path/to/workspace/node_modules/gulp/node_modules/gulp-util 中查找,没有找到任何东西,然后在 /path/to/workspace/node_modules/gulp-util 中查找,找到合适的模块,导入它并继续前进。
但是,当这是一个符号链接时,我会收到如下错误:
module.js:339
throw err;
^
Error: Cannot find module 'gulp-util'
at Function.Module._resolveFilename (module.js:337:15)
at Function.Module._load (module.js:287:25)
at Module.require (module.js:366:17)
at require (module.js:385:17)
at Object.<anonymous> (/path/to/cache/gulp/index.js:4:15)
at Module._compile (module.js:435:26)
at Object.Module._extensions..js (module.js:442:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Module.require (module.js:366:17)
at require (module.js:385:17)
我认为这会尝试与其他版本相同,但我不明白为什么它无法找到 gulp-util。无论是在/path/to/workspace/node_modules/gulp-util 还是/path/to/cache/gulp-util 中查找,它都应该找到该模块并能够导入它。
我已经尝试通过手动安装模块gulp/node_modules/gulp-util 来解决这个问题,但是我遇到了很多这样的错误,并且在构建服务器上手动处理这个问题是不可行的。编写一些代码来搜索这种类型的依赖项并安装它们是可能的,但感觉这样做是错误的。
npm 必须有某种方式来支持这样的工作流程,对吧?我错过了一些明显的东西吗?我是否掩盖了文档中的某些内容?
【问题讨论】:
-
您可以通过切换到 NPM 3.x 来实现这一点,这会将 node_modules 结构从
node_modules/parent/node_modules/child更改为node_modules/child。 -
呵呵,我用最新版本的 npm 3.x 试过了,我遇到了完全相同的问题。
-
@laffoyb 检查这个答案*.com/a/18974546/1341008 简而言之,尝试将所有模块放在您的 NODE_PATH 上
-
@darko,实际上,阅读该线程中的最佳答案给了我一个想法。它会查找名为 node_modules 的文件夹的路径。我的缓存在
/path/to/cache/,如果它在/path/to/cache/node_modules/,也许它可以正常工作?我现在无法测试,但我会在早上检查。
标签: node.js npm npm-shrinkwrap