node.js:依赖的版本(时刻-时区)在运行时改变

Posted

技术标签:

【中文标题】node.js:依赖的版本(时刻-时区)在运行时改变【英文标题】:node.js: version of dependency (moment-timezone) changes at runtime 【发布时间】:2018-10-27 08:45:33 【问题描述】:

在最后一天,我研究了一个神秘的问题,其中moment-timezone 功能在特定的、看似任意的情况下不起作用。 我发现我的 moment-timezone 库的运行时版本在某个时候从版本 0.5.17 更改为 0.5.13。

在添加更多详细信息之前,这是node.js 问题还是moment-timezone 问题?

moment-timezone 的具体问题我最终使用yarn selective-version-resolutions 解决了,但如果这实际上是node.js 问题,我认为需要采取更极端的措施(yarn install --flat?)。

我不知道是哪个依赖项导致版本在运行时发生更改,但这是在添加 resolutions 部分之前我的 yarn.lock 文件中的相关部分:

moment-timezone@0.5.17:
  version "0.5.17"
  resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.17.tgz#3c8fef32051d84c3af174d91dc52977dcb0ad7e5"
  dependencies:
    moment ">= 2.9.0"

moment-timezone@^0.5.0, moment-timezone@^0.5.4, moment-timezone@~0.5.5:
  version "0.5.13"
  resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.13.tgz#99ce5c7d827262eb0f1f702044177f60745d7b90"
  dependencies:
    moment ">= 2.9.0"

如您所见,我的直接依赖关系是版本 0.5.17,但我的其他模块的依赖关系正在解析为版本 0.5.13。但我不明白在某些时候 我的 依赖项是如何解决到 0.5.13 的。

要检查moment-timezone 版本,我只需使用moment.tz.version。这意味着在我的生产代码中,以下代码打印 0.5.17 直到某个时候突然打印 0.5.13

const moment = require('moment-timezone');
console.log(`moment.tz.version: $moment.tz.version`);

最后一个细节:版本更改为 0.5.13 时中断的时刻时区函数是 moment.tz 函数 added in version 0.5.14 上的可选标志,在此代码中:

moment(utcDateTime, format).clone().tz(timezone, true)

谁能解释这怎么可能?我希望这是一个时区错误,而不是 node.js 错误...

【问题讨论】:

你有package-lock吗?删除它和您的node_modules,检查您的package.json 中的版本是否正确,然后运行npm install @MaxBaldwin,这如何解释模块版本在运行时发生变化?正如我所说,我使用纱线选择性版本分辨率解决了具体问题。 当你安装 npm 或 yarn 时,会先查看你的 yarn.lock,然后再查看 package.json。它几乎像缓存一样工作。如果它看到对正在安装的包的引用,它将安装该版本并跳过package.json 但是经常发生的是你引用了同一个包的多个版本(在 yarn.lock 文件中),它们应该和谐地生活在一起。 这可能是因为添加包的顺序以及稍后运行的 yarn 命令可能会改变它。由于您有多个依赖项引用不同的版本,因此您确实需要使用解决方案,就像您已经在做的那样。 【参考方案1】:

我今天遇到了同样的问题,几个小时后,我想我知道发生了什么。如果你检查 moment-timezone 代码,你会看到它在初始化时需要 moment,添加 tz 属性以及与时区相关的所有内容,最后返回修改后的 moment 实例:

需要时刻 -> https://github.com/moment/moment-timezone/blob/0.5.27/moment-timezone.js#L12

修改矩实例 -> https://github.com/moment/moment-timezone/blob/0.5.27/moment-timezone.js#L532

返回具有所有新方法和属性的实例 -> https://github.com/moment/moment-timezone/blob/0.5.27/moment-timezone.js#L626

因此,如果您的直接依赖项和其他模块中的依赖项解析为相同的 moment 版本,则同一对象被修改两次,您获得的最终版本仅取决于您需要的顺序 moment-timezone 和具有 moment-timezone 作为依赖项的模块。

其实在moment-timezone代码中,你可以看到这些行被注释掉了:

// Do not load moment-timezone a second time.
    // if (moment.tz !== undefined) 
    //  logError('Moment Timezone ' + moment.tz.version + ' was already loaded ' + (moment.tz.dataVersion ? 'with data from ' : 'without any data') + moment.tz.dataVersion);
    //  return moment;
    // 

我不知道为什么开发人员对此进行了注释,但显然这是一种已知行为。

【讨论】:

以上是关于node.js:依赖的版本(时刻-时区)在运行时改变的主要内容,如果未能解决你的问题,请参考以下文章

node.js在发出http请求时区分错误

在 Windows 上运行 Python 以获取 Node.js 依赖项

Node.js包的依赖及版本号(转)

node.js 9 来了!重大版本更新!

软件版本号规范与命名原则(node.js与package.json依赖包规范)

浅析Node.js中使用依赖注入的相关问题及解决方法