node.js:依赖项的版本(时刻时区)在运行时发生变化

jon*_*iba 5 node.js node-modules momentjs yarnpkg moment-timezone

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

在添加更多细节之前,这是一个node.js问题还是一个moment-timezone问题?

我最终使用纱线选择性版本分辨率moment-timezone解决了具体问题,但如果这实际上是一个问题,我认为需要采取更极端的措施(纱线安装--平?)。node.js

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

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"
Run Code Online (Sandbox Code Playgroud)

如您所见,我的直接依赖项是版本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}`);
Run Code Online (Sandbox Code Playgroud)

最后一个细节:版本更改为0.5.13时中断的 moment-timezone 函数是版本 0.5.14 中添加的moment.tz函数上的可选标志,在此代码中:

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

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

小智 1

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

因此,如果您的直接依赖项和其他模块中的依赖项解析为同一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;
    // }
Run Code Online (Sandbox Code Playgroud)

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