Node.js v14.20.0 文档


目录

ECMAScript 模块#

中英对照

介绍#

中英对照

ECMAScript 模块是来打包 JavaScript 代码以供重用的官方标准格式。 模块使用各种 importexport 语句定义。



启用#

中英对照

Node.js 默认将 JavaScript 代码视为 CommonJS 模块。 作者可以通过 .mjs 文件扩展名、package.json "type" 字段、或 --input-type 标志告诉 Node.js 将 JavaScript 代码视为 ECMAScript 模块。 有关更多详细信息,请参阅包模块

#

中英对照

此章节已移至包模块

import 说明符#

术语#

中英对照

import 语句的说明符是 from 关键字之后的字符串,例如 import { sep } from 'path' 中的 'path'。 说明符也用于 export from 语句,并作为 import() 表达式的参数。

    强制的文件扩展名#

    中英对照

    当使用 import 关键字解析相对或绝对的说明符时,必须提供文件扩展名。 还必须完全指定目录索引(例如 './startup/index.js')。

    URL#

    中英对照

    ES 模块被解析并缓存为 URL。 这意味着包含 #? 等特殊字符的文件需要转义。

    file: URL#

    中英对照

    如果用于解析模块的 import 说明符具有不同的查询或片段,则会多次加载模块。

    
    

    data: 导入#

    中英对照

    data: URL 支持使用以下 MIME 类型导入:

      
      
      node: 导入#

      中英对照

      支持 node: URL 作为加载 Node.js 内置模块的替代方法。 此 URL 协议允许有效的绝对的 URL 字符串引用内置模块。

      
      

      内置模块#

      中英对照

      核心模块提供了其公共 API 的命名导出。 还提供了默认导出,其是 CommonJS 导出的值。 默认导出可用于修改命名导出等。 内置模块的命名导出仅通过调用 module.syncBuiltinESMExports() 进行更新。

      
      
      
      
      
      

      import() 表达式#

      中英对照

      动态的 import() 在 CommonJS 和 ES 模块中都受支持。 在 CommonJS 模块中它可以用来加载 ES 模块。

      import.meta#

      中英对照

        import.meta 元属性是包含以下属性的 Object

        import.meta.url#

        中英对照

          这与提供当前模块文件 URL 的浏览器中的定义完全相同。

          
          

          import.meta.resolve(specifier[, parent])#

          中英对照

          此特性仅在启用 --experimental-import-meta-resolve 命令标志时可用。

            
            

            
            

            与 CommonJS 的互操作性#

            import 声明#

            中英对照

            import 语句可以引用 ES 模块或 CommonJS 模块。 import 语句只允许在 ES 模块中使用,但 CommonJS 支持动态 import() 表达式来加载 ES 模块。

            require#

            中英对照

            CommonJS 模块 require 总是将它引用的文件视为 CommonJS。

            CommonJS 命名空间#

            中英对照

            CommonJS 模块由可以是任何类型的 module.exports 对象组成。

            
            

            
            

            
            

            
            

            ES 模块和 CommonJS 之间的差异#

            没有 require、exports 或 module.exports#

            中英对照

            在大多数情况下,可以使用 ES 模块 import 加载 CommonJS 模块。

            没有 __filename 或 __dirname#

            中英对照

            这些 CommonJS 变量在 ES 模块中不可用。

            没有 JSON 模块加载#

            中英对照

            JSON 导入仍处于实验阶段,仅通过 --experimental-json-modules 标志支持。

            
            

            没有原生模块加载#

            中英对照

            ES 模块导入当前不支持原生模块。

            没有 require.resolve#

            中英对照

            相对解析可以通过 new URL('./local', import.meta.url) 处理。

            没有 NODE_PATH#

            中英对照

            NODE_PATH 不是解析 import 说明符的一部分。 如果需要这种行为,则使用符号链接。

            没有 require.extensions#

            中英对照

            require.extensions 没有被 import 使用。 期望加载器钩子在未来可以提供这个工作流。

            没有 require.cache#

            中英对照

            require.cache 没有被 import 使用,因为 ES 模块加载器有自己独立的缓存。

            JSON 模块#

            中英对照

            目前导入 JSON 模块仅支持 commonjs 模式,并且使用 CJS 加载器加载。 WHATWG JSON 模块规范仍在标准化中,并且通过在运行 Node.js 时包含额外的标志 --experimental-json-modules 进行实验性地支持。

            
            

            
            

            Wasm 模块#

            中英对照

            --experimental-wasm-modules 标志下支持导入 Web Assembly 模块,允许将任何 .wasm 文件作为普通模块导入,同时还支持它们的模块导入。

            
            

            
            

            顶层的 await#

            中英对照

            await 关键字可以用在 ECMAScript 模块的顶层主体中。

            
            

            
            
            
            

            
            

            加载器#

            中英对照

            注意:此 API 目前正在重新设计,并将继续更改。

            钩子#

            resolve(specifier, context, defaultResolve)#

            中英对照

              resolve 钩子返回给定模块说明符和父 URL 的解析文件 URL。 模块说明符是 import 语句或 import() 表达式中的字符串,父 URL 是导入此模块的 URL,如果这是应用程序的主要入口点,则为 undefined

              
              
              getFormat(url, context, defaultGetFormat)#

              中英对照

                getFormat 钩子提供了一种方式来定义确定网址应如何解释的自定义方法。 返回的 format 也会影响解析时模块的可接受的源值形式。 这可以是以下之一:

                  
                  
                  getSource(url, context, defaultGetSource)#

                  中英对照

                    getSource 钩子提供了一种方法来定义用于检索 ES 模块说明符的源代码的自定义方法。 这将允许加载器潜在地避免从磁盘读取文件。

                    
                    
                    transformSource(source, context, defaultTransformSource)#

                    中英对照

                      transformSource 钩子提供了一种在加载源字符串之后但在 Node.js 对其进行任何操作之前修改加载的 ES 模块文件的源代码的方法。

                      
                      
                      getGlobalPreloadCode()#

                      中英对照

                        有时可能需要在应用程序运行所在的同一全局范围内运行一些代码。 此钩子允许返回在启动时作为宽松模式脚本运行的字符串。

                        
                        

                        示例#

                        中英对照

                        各种加载器钩子可以一起使用来完成对 Node.js 代码加载和评估行为的广泛定制。

                        HTTPS 加载器#

                        中英对照

                        在当前的 Node.js 中,不支持以 https:// 开头的说明符。 下面的加载器注册钩子以启用对此类说明符的基本支持。 虽然这似乎是对 Node.js 核心功能的重大改进,但实际使用这个加载器有很大的缺点:性能比从磁盘加载文件慢得多,没有缓存,也没有安全性。

                        
                        
                        
                        

                        转译器加载器#

                        中英对照

                        可以使用 transformSource 钩子将 Node.js 无法理解的格式的源转换为 JavaScript。 但是,在调用该钩子之前,其他钩子需要告诉 Node.js 不要在未知文件类型上抛出错误;并告诉 Node.js 如何加载这种新文件类型。

                        
                        
                        
                        
                        
                        

                        解析算法#

                        特性#

                        中英对照

                        解析器具有以下属性:

                          解析器算法#

                          中英对照

                          加载 ES 模块说明符的算法通过下面的 ESM_RESOLVE 方法给出。 它返回相对于 parentURL 的模块说明符的解析 URL。

                            解析器算法规范#

                            ESM_RESOLVE(specifier, parentURL)

                            1. Let resolved be undefined.
                            2. If specifier is a valid URL, then
                              1. Set resolved to the result of parsing and reserializing specifier as a URL.
                            3. Otherwise, if specifier starts with "/", "./" or "../", then
                              1. Set resolved to the URL resolution of specifier relative to parentURL.
                            4. Otherwise, if specifier starts with "#", then
                              1. Set resolved to the destructured value of the result of PACKAGE_IMPORTS_RESOLVE(specifier, parentURL, defaultConditions).
                            5. Otherwise,
                              1. Note: specifier is now a bare specifier.
                              2. Set resolved the result of PACKAGE_RESOLVE(specifier, parentURL).
                            6. If resolved contains any percent encodings of "/" or "\" ("%2f" and "%5C" respectively), then
                              1. Throw an Invalid Module Specifier error.
                            7. If the file at resolved is a directory, then
                              1. Throw an Unsupported Directory Import error.
                            8. If the file at resolved does not exist, then
                              1. Throw a Module Not Found error.
                            9. Set resolved to the real path of resolved.
                            10. Let format be the result of ESM_FORMAT(resolved).
                            11. Load resolved as module format, format.
                            12. Return resolved.

                            PACKAGE_RESOLVE(packageSpecifier, parentURL)

                            1. Let packageName be undefined.
                            2. If packageSpecifier is an empty string, then
                              1. Throw an Invalid Module Specifier error.
                            3. If packageSpecifier does not start with "@", then
                              1. Set packageName to the substring of packageSpecifier until the first "/" separator or the end of the string.
                            4. Otherwise,
                              1. If packageSpecifier does not contain a "/" separator, then
                                1. Throw an Invalid Module Specifier error.
                              2. Set packageName to the substring of packageSpecifier until the second "/" separator or the end of the string.
                            5. If packageName starts with "." or contains "\" or "%", then
                              1. Throw an Invalid Module Specifier error.
                            6. Let packageSubpath be "." concatenated with the substring of packageSpecifier from the position at the length of packageName.
                            7. Let selfUrl be the result of PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL).
                            8. If selfUrl is not undefined, return selfUrl.
                            9. If packageSubpath is "." and packageName is a Node.js builtin module, then
                              1. Return the string "node:" concatenated with packageSpecifier.
                            10. While parentURL is not the file system root,
                              1. Let packageURL be the URL resolution of "node_modules/" concatenated with packageSpecifier, relative to parentURL.
                              2. Set parentURL to the parent folder URL of parentURL.
                              3. If the folder at packageURL does not exist, then
                                1. Set parentURL to the parent URL path of parentURL.
                                2. Continue the next loop iteration.
                              4. Let pjson be the result of READ_PACKAGE_JSON(packageURL).
                              5. If pjson is not null and pjson.exports is not null or undefined, then
                                1. Let exports be pjson.exports.
                                2. Return the resolved destructured value of the result of PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions).
                              6. Otherwise, if packageSubpath is equal to ".", then
                                1. Return the result applying the legacy LOAD_AS_DIRECTORY CommonJS resolver to packageURL, throwing a Module Not Found error for no resolution.
                              7. Otherwise,
                                1. Return the URL resolution of packageSubpath in packageURL.
                            11. Throw a Module Not Found error.

                            PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL)

                            1. Let packageURL be the result of READ_PACKAGE_SCOPE(parentURL).
                            2. If packageURL is null, then
                              1. Return undefined.
                            3. Let pjson be the result of READ_PACKAGE_JSON(packageURL).
                            4. If pjson is null or if pjson.exports is null or undefined, then
                              1. Return undefined.
                            5. If pjson.name is equal to packageName, then
                              1. Return the resolved destructured value of the result of PACKAGE_EXPORTS_RESOLVE(packageURL, subpath, pjson.exports, defaultConditions).
                            6. Otherwise, return undefined.

                            PACKAGE_EXPORTS_RESOLVE(packageURL, subpath, exports, conditions)

                            1. If exports is an Object with both a key starting with "." and a key not starting with ".", throw an Invalid Package Configuration error.
                            2. If subpath is equal to ".", then
                              1. Let mainExport be undefined.
                              2. If exports is a String or Array, or an Object containing no keys starting with ".", then
                                1. Set mainExport to exports.
                              3. Otherwise if exports is an Object containing a "." property, then
                                1. Set mainExport to exports["."].
                              4. If mainExport is not undefined, then
                                1. Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, mainExport, "", false, false, conditions).
                                2. If resolved is not null or undefined, then
                                  1. Return resolved.
                            3. Otherwise, if exports is an Object and all keys of exports start with ".", then
                              1. Let matchKey be the string "./" concatenated with subpath.
                              2. Let resolvedMatch be result of PACKAGE_IMPORTS_EXPORTS_RESOLVE( matchKey, exports, packageURL, false, conditions).
                              3. If resolvedMatch.resolve is not null or undefined, then
                                1. Return resolvedMatch.
                            4. Throw a Package Path Not Exported error.

                            PACKAGE_IMPORTS_RESOLVE(specifier, parentURL, conditions)

                            1. Assert: specifier begins with "#".
                            2. If specifier is exactly equal to "#" or starts with "#/", then
                              1. Throw an Invalid Module Specifier error.
                            3. Let packageURL be the result of READ_PACKAGE_SCOPE(parentURL).
                            4. If packageURL is not null, then
                              1. Let pjson be the result of READ_PACKAGE_JSON(packageURL).
                              2. If pjson.imports is a non-null Object, then
                                1. Let resolvedMatch be the result of PACKAGE_IMPORTS_EXPORTS_RESOLVE(specifier, pjson.imports, packageURL, true, conditions).
                                2. If resolvedMatch.resolve is not null or undefined, then
                                  1. Return resolvedMatch.
                            5. Throw a Package Import Not Defined error.

                            PACKAGE_IMPORTS_EXPORTS_RESOLVE(matchKey, matchObj, packageURL, isImports, conditions)

                            1. If matchKey is a key of matchObj and does not end in "/" or contain "*", then
                              1. Let target be the value of matchObj[matchKey].
                              2. Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, "", false, isImports, conditions).
                              3. Return the object { resolved, exact: true }.
                            2. Let expansionKeys be the list of keys of matchObj either ending in "/" or containing only a single "*", sorted by the sorting function PATTERN_KEY_COMPARE which orders in descending order of specificity.
                            3. For each key expansionKey in expansionKeys, do
                              1. Let patternBase be null.
                              2. If expansionKey contains "*", set patternBase to the substring of expansionKey up to but excluding the first "*" character.
                              3. If patternBase is not null and matchKey starts with but is not equal to patternBase, then
                                1. Let patternTrailer be the substring of expansionKey from the index after the first "*" character.
                                2. If patternTrailer has zero length, or if matchKey ends with patternTrailer and the length of matchKey is greater than or equal to the length of expansionKey, then
                                  1. Let target be the value of matchObj[expansionKey].
                                  2. Let subpath be the substring of matchKey starting at the index of the length of patternBase up to the length of matchKey minus the length of patternTrailer.
                                  3. Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, subpath, true, isImports, conditions).
                                  4. Return the object { resolved, exact: true }.
                              4. Otherwise if patternBase is null and matchKey starts with expansionKey, then
                                1. Let target be the value of matchObj[expansionKey].
                                2. Let subpath be the substring of matchKey starting at the index of the length of expansionKey.
                                3. Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, subpath, false, isImports, conditions).
                                4. Return the object { resolved, exact: false }.
                            4. Return the object { resolved: null, exact: true }.

                            PATTERN_KEY_COMPARE(keyA, keyB)

                            1. Assert: keyA ends with "/" or contains only a single "*".
                            2. Assert: keyB ends with "/" or contains only a single "*".
                            3. Let baseLengthA be the index of "*" in keyA plus one, if keyA contains "*", or the length of keyA otherwise.
                            4. Let baseLengthB be the index of "*" in keyB plus one, if keyB contains "*", or the length of keyB otherwise.
                            5. If baseLengthA is greater than baseLengthB, return -1.
                            6. If baseLengthB is greater than baseLengthA, return 1.
                            7. If keyA does not contain "*", return 1.
                            8. If keyB does not contain "*", return -1.
                            9. If the length of keyA is greater than the length of keyB, return -1.
                            10. If the length of keyB is greater than the length of keyA, return 1.
                            11. Return 0.

                            PACKAGE_TARGET_RESOLVE(packageURL, target, subpath, pattern, internal, conditions)

                            1. If target is a String, then
                              1. If pattern is false, subpath has non-zero length and target does not end with "/", throw an Invalid Module Specifier error.
                              2. If target does not start with "./", then
                                1. If internal is true and target does not start with "../" or "/" and is not a valid URL, then
                                  1. If pattern is true, then
                                    1. Return PACKAGE_RESOLVE(target with every instance of "*" replaced by subpath, packageURL + "/")_.
                                  2. Return PACKAGE_RESOLVE(target + subpath, packageURL + "/")_.
                                2. Otherwise, throw an Invalid Package Target error.
                              3. If target split on "/" or "\" contains any ".", ".." or "node_modules" segments after the first segment, throw an Invalid Package Target error.
                              4. Let resolvedTarget be the URL resolution of the concatenation of packageURL and target.
                              5. Assert: resolvedTarget is contained in packageURL.
                              6. If subpath split on "/" or "\" contains any ".", ".." or "node_modules" segments, throw an Invalid Module Specifier error.
                              7. If pattern is true, then
                                1. Return the URL resolution of resolvedTarget with every instance of "*" replaced with subpath.
                              8. Otherwise,
                                1. Return the URL resolution of the concatenation of subpath and resolvedTarget.
                            2. Otherwise, if target is a non-null Object, then
                              1. If exports contains any index property keys, as defined in ECMA-262 6.1.7 Array Index, throw an Invalid Package Configuration error.
                              2. For each property p of target, in object insertion order as,
                                1. If p equals "default" or conditions contains an entry for p, then
                                  1. Let targetValue be the value of the p property in target.
                                  2. Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, targetValue, subpath, pattern, internal, conditions).
                                  3. If resolved is equal to undefined, continue the loop.
                                  4. Return resolved.
                              3. Return undefined.
                            3. Otherwise, if target is an Array, then
                              1. If _target.length is zero, return null.
                              2. For each item targetValue in target, do
                                1. Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, targetValue, subpath, pattern, internal, conditions), continuing the loop on any Invalid Package Target error.
                                2. If resolved is undefined, continue the loop.
                                3. Return resolved.
                              3. Return or throw the last fallback resolution null return or error.
                            4. Otherwise, if target is null, return null.
                            5. Otherwise throw an Invalid Package Target error.

                            ESM_FORMAT(url)

                            1. Assert: url corresponds to an existing file.
                            2. Let pjson be the result of READ_PACKAGE_SCOPE(url).
                            3. If url ends in ".mjs", then
                              1. Return "module".
                            4. If url ends in ".cjs", then
                              1. Return "commonjs".
                            5. If pjson?.type exists and is "module", then
                              1. If url ends in ".js", then
                                1. Return "module".
                              2. Throw an Unsupported File Extension error.
                            6. Otherwise,
                              1. Throw an Unsupported File Extension error.

                            READ_PACKAGE_SCOPE(url)

                            1. Let scopeURL be url.
                            2. While scopeURL is not the file system root,
                              1. Set scopeURL to the parent URL of scopeURL.
                              2. If scopeURL ends in a "node_modules" path segment, return null.
                              3. Let pjson be the result of READ_PACKAGE_JSON(scopeURL).
                              4. If pjson is not null, then
                                1. Return pjson.
                            3. Return null.

                            READ_PACKAGE_JSON(packageURL)

                            1. Let pjsonURL be the resolution of "package.json" within packageURL.
                            2. If the file at pjsonURL does not exist, then
                              1. Return null.
                            3. If the file at packageURL does not parse as valid JSON, then
                              1. Throw an Invalid Package Configuration error.
                            4. Return the parsed JSON source of the file at pjsonURL.

                            自定义的 ESM 说明符解析算法#

                            中英对照

                            当前的说明符解析不支持 CommonJS 加载器的所有默认行为。 行为差异之一是文件扩展名的自动解析以及导入具有索引文件的目录的能力。

                            
                            
                            返回顶部