【问题标题】:Serverless stack: Maximum call stack size exceeded only in windows during npm run start无服务器堆栈:在 npm run start 期间,仅在 windows 中超过最大调用堆栈大小
【发布时间】:2021-10-28 19:56:49
【问题描述】:

我开始使用无服务器堆栈指南,但很快我在 Windows 10 中遇到了困难(相同的步骤在 Mac 或 Linux 中不会导致任何问题)。

我创建了一个简单的无服务器堆栈项目,并执行以下操作: npm 运行开始

我知道了:

RangeError: 超出最大调用堆栈大小 在 Object.resolve (path.js:153:10) 在 getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:38) 在 getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) 在 getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) 在 getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) 在 getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) 在 getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) 在 getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) 在 getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) 在 getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12)

节点版本为 v14.17.5,npm 为 7.21.1

由于我几乎没有实例化该项目并且它正在其他平台上运行,我真的不明白如何解决这个问题。

谢谢

【问题讨论】:

    标签: javascript node.js npm serverless-stack


    【解决方案1】:

    嗯,您通常会首先检查调用堆栈中的代码/文件,看看是否可以为您提供任何线索。从我们可以看到的一点点看来,getManager() 一遍又一遍地呼唤自己。只是猜测,但也许这是一个配置错误或触发它执行此操作的其他错误路径。

    如果你查看github 上的 serverless-stack/core/dist/packager/packager.js,你会看到这个函数:

    export function getManager(dir: string): Manager {
      const lock = path.join(dir, "yarn.lock");
      if (fs.existsSync(lock)) return Yarn;
      if (dir === "/") return NPM;
      return getManager(path.resolve(dir, ".."));
    }
    

    所以,这似乎是在寻找一个yarn.lock 文件。如果找到,return Yarn。如果我们已经在/ 的顶级路径,那么return NPM。否则,递归调用自身,但在目录层次结构中上一层并重新开始。因此,如果代码实际上是这样工作的,它应该在 *nix 的顶层以 dir === "/" 结束,除非在 Windows 上可能不是这种情况,原因有两个:

    1. Windows 可能在路径的开头有一个驱动器号。
    2. Windows 使用“\”作为路径分隔符,而不是“/”。

    缩小范围的一种方法是暂时将一些日志记录到这个getManager() 函数中以查看它正在传递的内容(只需暂时编辑 dist 目录中的版本 - 确保您正在编辑编译/转译版本,而不是 TypeScript 版本,除非您要再次构建它)。

    export function getManager(dir: string): Manager {
      console.log("getManager()", dir);            // <== add this
      const lock = path.join(dir, "yarn.lock");
      if (fs.existsSync(lock)) return Yarn;
      if (dir === "/") return NPM;
      return getManager(path.resolve(dir, ".."));
    }
    

    查看此处传递的内容将表明上述两个问题中的哪一个可能导致问题。从代码来看,只要确保你只传递一个带有正斜杠的路径,它就可以工作,但是必须测试这里涉及的其他代码是否可以。

    仅供参考,通过将代码更改为以下代码,可以使这段代码更能适应 Windows 世界:

    // regex that matches / or \ or d:/ or d:\
    const topPath = /^(\/|\\|[a-z]:[\/\\]|)$/i;
    
    export function getManager(dir: string): Manager {
      console.log("getManager()", dir);
      const lock = path.join(dir, "yarn.lock");
      if (fs.existsSync(lock)) return Yarn;
      if (topPath.test(dir)) return NPM;
      return getManager(path.resolve(dir, ".."));
    }
    

    注意,这并没有被编码来处理 Windows 上以“\\”开头的 UNC 路径,但它当然也可以适用于此。


    再想一想,这里有一个更简单的方法,可以在您到达顶部时避免无限循环。如果尝试向上 .. 不会改变路径,那么你就在顶部:

    export function getManager(dir: string): Manager {
      const lock = path.join(dir, "yarn.lock");
      if (fs.existsSync(lock)) return Yarn;
      let upDir = path.resolve(dir, "..");
      // if we didn't actually go up any more, then we're at the top
      if (upDir === dir) {
          return NPM;
      }
      return getManager(upDir);
    }
    

    【讨论】:

    • 感谢@jfriend00!它成功了。此外,我提交了一个类似更改的 PR,以避免让其他人感到头疼github.com/serverless-stack/serverless-stack/pull/770
    • @ff8mania - 我认为最后一个解决方案(我添加的)比正则表达式解决方案更好,因为它完全是跨平台的,并且可以处理 Windows 上的 UNC 路径等正则表达式不能处理的情况。跨度>
    • 是的@jfriend00 好点。我相应地更新了 PR。非常感谢!
    • 这已在 v0.40.6 中修复!
    猜你喜欢
    • 2017-03-26
    • 2012-02-02
    • 2012-06-26
    • 2020-01-05
    • 2020-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多