无服务器堆栈:在 npm 运行 启动期间,仅在 windows 中超出了最大调用堆栈大小

Serverless stack: Maximum call stack size exceeded only in windows during npm run start

我开始使用无服务器堆栈指南,但很快就在 Windows 10 中碰壁了(相同的步骤不会在 Mac 或 Linux 中造成任何问题) .

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

我知道了:

RangeError: Maximum call stack size exceeded at Object.resolve (path.js:153:10) at getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:38) at getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) at getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) at getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) at getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) at getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) at getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) at getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12) at getManager (D:\Sources\demo-notes-app\node_modules@serverless-stack\core\dist\packager\packager.js:48:12)

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

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

谢谢

嗯,您通常会从检查调用堆栈中的 code/files 开始,看看是否能为您提供任何线索。从我们在那里看到的一点点看来,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 目录中的版本 - 确保你正在编辑compiled/transpiled 版本,而不是 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);
}