想要获得调用 require() 时加载的确切的文件名,使用 require.resolve() 函数。

    综上所述,以下用伪代码描述的高级算法,解释 resolve() 做了些什么:

    1. require(X) from module at path Y
    2. 1. If X is a core module,
    3. a. return the core module
    4. b. STOP
    5. 2. If X begins with '/'
    6. a. set Y to be the filesystem root
    7. 3. If X begins with './' or '/' or '../'
    8. a. LOAD_AS_FILE(Y + X)
    9. b. LOAD_AS_DIRECTORY(Y + X)
    10. c. THROW "not found"
    11. 4. If X begins with '#'
    12. a. LOAD_PACKAGE_IMPORTS(X, dirname(Y))
    13. 5. LOAD_PACKAGE_SELF(X, dirname(Y))
    14. 6. LOAD_NODE_MODULES(X, dirname(Y))
    15. 7. THROW "not found"
    16. LOAD_AS_FILE(X)
    17. 1. If X is a file, load X as its file extension format. STOP
    18. 2. If X.js is a file, load X.js as JavaScript text. STOP
    19. 3. If X.json is a file, parse X.json to a JavaScript Object. STOP
    20. 4. If X.node is a file, load X.node as binary addon. STOP
    21. LOAD_INDEX(X)
    22. 1. If X/index.js is a file, load X/index.js as JavaScript text. STOP
    23. 2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
    24. 3. If X/index.node is a file, load X/index.node as binary addon. STOP
    25. LOAD_AS_DIRECTORY(X)
    26. 1. If X/package.json is a file,
    27. a. Parse X/package.json, and look for "main" field.
    28. b. If "main" is a falsy value, GOTO 2.
    29. c. let M = X + (json main field)
    30. d. LOAD_AS_FILE(M)
    31. e. LOAD_INDEX(M)
    32. f. LOAD_INDEX(X) DEPRECATED
    33. g. THROW "not found"
    34. 2. LOAD_INDEX(X)
    35. LOAD_NODE_MODULES(X, START)
    36. 1. let DIRS = NODE_MODULES_PATHS(START)
    37. 2. for each DIR in DIRS:
    38. a. LOAD_PACKAGE_EXPORTS(X, DIR)
    39. b. LOAD_AS_FILE(DIR/X)
    40. c. LOAD_AS_DIRECTORY(DIR/X)
    41. NODE_MODULES_PATHS(START)
    42. 1. let PARTS = path split(START)
    43. 2. let I = count of PARTS - 1
    44. 3. let DIRS = [GLOBAL_FOLDERS]
    45. 4. while I >= 0,
    46. a. if PARTS[I] = "node_modules" CONTINUE
    47. b. DIR = path join(PARTS[0 .. I] + "node_modules")
    48. c. DIRS = DIRS + DIR
    49. d. let I = I - 1
    50. 5. return DIRS
    51. LOAD_PACKAGE_IMPORTS(X, DIR)
    52. 1. Find the closest package scope SCOPE to DIR.
    53. 2. If no scope was found, return.
    54. 3. If the SCOPE/package.json "imports" is null or undefined, return.
    55. 4. let MATCH = PACKAGE_IMPORTS_RESOLVE(X, pathToFileURL(SCOPE),
    56. ["node", "require"]) defined in the ESM resolver.
    57. 5. RESOLVE_ESM_MATCH(MATCH).
    58. LOAD_PACKAGE_EXPORTS(X, DIR)
    59. 1. Try to interpret X as a combination of NAME and SUBPATH where the name
    60. may have a @scope/ prefix and the subpath begins with a slash (`/`).
    61. 2. If X does not match this pattern or DIR/NAME/package.json is not a file,
    62. return.
    63. 3. Parse DIR/NAME/package.json, and look for "exports" field.
    64. 4. If "exports" is null or undefined, return.
    65. 5. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(DIR/NAME), "." + SUBPATH,
    66. `package.json` "exports", ["node", "require"]) defined in the ESM resolver.
    67. 6. RESOLVE_ESM_MATCH(MATCH)
    68. LOAD_PACKAGE_SELF(X, DIR)
    69. 1. Find the closest package scope SCOPE to DIR.
    70. 2. If no scope was found, return.
    71. 3. If the SCOPE/package.json "exports" is null or undefined, return.
    72. 4. If the SCOPE/package.json "name" is not the first segment of X, return.
    73. 5. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(SCOPE),
    74. "." + X.slice("name".length), `package.json` "exports", ["node", "require"])
    75. defined in the ESM resolver.
    76. 6. RESOLVE_ESM_MATCH(MATCH)
    77. RESOLVE_ESM_MATCH(MATCH)
    78. 1. let { RESOLVED, EXACT } = MATCH
    79. 2. let RESOLVED_PATH = fileURLToPath(RESOLVED)
    80. 3. If EXACT is true,
    81. a. If the file at RESOLVED_PATH exists, load RESOLVED_PATH as its extension
    82. format. STOP
    83. 4. Otherwise, if EXACT is false,
    84. a. LOAD_AS_FILE(RESOLVED_PATH)
    85. b. LOAD_AS_DIRECTORY(RESOLVED_PATH)
    86. 5. THROW "not found"