如何解决Node.js里“Cannot find module”的错误?

2022-01-05大约9分钟

Cannot find module 'xxx' 这个错是在写Node.js代码时一个很常见的错误,可以按照下面的思路来解决。

分三种情况,可以直接按自己的情况来看:

1. 自己的代码文件找不到。

比如下面的错误:

"stack":
          Error: Cannot find module './File1.js'
          Require stack:
          - C:\my-code\src\routes\index.js
          - C:\my-code\src\index.js
          - C:\my-code\src\dev.js
              at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)

按照以下的思路来逐步排查原因:

  1. 确认文件./File1.js存在
  2. 如果第1步没问题,确定require栈里最后一个文件C:\my-code\src\routes\index.js里面require的路径没问题。这里所说的问题,通常是指:文件名没错,大小写完全一致。通常由于Windows系统的路径不区分大小写,而Linux区分大小写,所以文件大小写不一致导致的问题比较多。
  3. 如果第2步没问题,再仔细检查第2步!

2. node_modules下第三方的包或文件找不到。

  1. 如果是自己的程序依赖这个包,那么要确保这个第三方的依赖在package.json里面有添加到dependencies或者devDependencies里面。
  2. 如果第1步没解决问题,删除当前项目下的node_modules目录,然后重新执行npm install命令。
  3. 如果第2步执行没问题,但是问题没解决,那么删除当前项目下的package-lock.json,然后用命令npm cache clean --force清除本地的npm cache之后,再重新执行npm install命令。
  4. 如果第3步做完仍旧有问题,需要看一下是不是第三方的包的代码是否有问题。

3. 使用了@babel/register作为运行时Node.js文件编译的库。

Babel是现代前端开发必不可少的一个工具,不过如果配置不正确,那么可能会出现一些问题。

比如这是@babel/register包的配置选项:

require("@babel/register")({
  // Array of ignore conditions, either a regex or a function. (Optional)
  // File paths that match any condition are not compiled.
  ignore: [
    // When a file path matches this regex then it is **not** compiled
    /regex/,

    // The file's path is also passed to any ignore functions. It will
    // **not** be compiled if `true` is returned.
    function(filepath) {
      return filepath !== "/path/to/es6-file.js";
    },
  ],

  // Array of accept conditions, either a regex or a function. (Optional)
  // File paths that match all conditions are compiled.
  only: [
    // File paths that **don't** match this regex are not compiled
    /my_es6_folder/,

    // File paths that **do not** return true are not compiled
    function(filepath) {
      return filepath === "/path/to/es6-file.js";
    },
  ],

  // Setting this will remove the currently hooked extensions of `.es6`, `.es`, `.jsx`, `.mjs`
  // and .js so you'll have to add them back if you want them to be used again.
  extensions: [".es6", ".es", ".jsx", ".js", ".mjs"],

  // Setting this to false will disable the cache.
  cache: true,
});

这个配置项里有两块儿需要注意:

  1. cache。默认情况下,Babel的cache是打开的,如果怀疑是Babel的cache导致出现Cannot find module 'xxx'的问题,可以尝试把这个选项的值改为false试试。
  2. 如果第1步改完之后没问题,那么说明的确是Babel的cache导致的。不过cache是个好东西,我们还是要用,所以我们可以把cache设置回true,然后检查一下上面的配置项ignoreonly的内容。这种情况下,要尽量确保程序运行的时候,不要把当前项目里/node_modules/目录下的文件让Babel来编译,因为当这个目录下的包更新了的时候,Babel不会知道,所以就会用cache里面的内容,导致出现问题。