添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
谈吐大方的山楂  ·  Optimizer Hints | ...·  9 月前    · 
苦闷的猕猴桃  ·  python tkinter ...·  1 年前    · 
  • Imports are limited to HTTP/1
  • HTTP is limited to loopback addresses
  • Authentication is never sent to the destination server.
  • CORS is never checked on the destination server
  • Cannot load non-network dependencies
  • Network-based loading is not enabled by default
  • Loaders
  • Hooks
  • resolve(specifier, context, nextResolve)
  • load(url, context, nextLoad)
  • globalPreload()
  • Examples
  • HTTPS loader
  • Transpiler loader
  • Imports are limited to HTTP/1
  • HTTP is limited to loopback addresses
  • Authentication is never sent to the destination server.
  • CORS is never checked on the destination server
  • Cannot load non-network dependencies
  • Network-based loading is not enabled by default
  • Loaders
  • Hooks
  • resolve(specifier, context, nextResolve)
  • load(url, context, nextLoad)
  • globalPreload()
  • Examples
  • HTTPS loader
  • Transpiler loader
  • Loader hooks are executed off the main thread.

    v18.6.0, v16.17.0

    Add support for chaining loaders.

    v17.1.0, v16.14.0

    Add support for import assertions.

    v17.0.0, v16.12.0

    Consolidate loader hooks, removed getFormat , getSource , transformSource , and getGlobalPreloadCode hooks added load and globalPreload hooks allowed returning format from either resolve or load hooks.

    v14.8.0

    Unflag Top-Level Await.

    v15.3.0, v14.17.0, v12.22.0

    Stabilize modules implementation.

    v14.13.0, v12.20.0

    Support for detection of CommonJS named exports.

    v14.0.0, v13.14.0, v12.20.0

    Remove experimental modules warning.

    v13.2.0, v12.17.0

    Loading ECMAScript modules no longer requires a command-line flag.

    v12.0.0

    Add support for ES modules using .js file extension via package.json "type" field.

    v8.5.0

    Added in: v8.5.0

    Introduction #

    the official standard format to package JavaScript code for reuse. Modules are defined using a variety of import and export statements.

    The following example of an ES module exports a function:

    // addTwo.mjs
    function addTwo(num) {
      return num + 2;
    export { addTwo }; 

    The following example of an ES module imports the function from addTwo.mjs :

    // app.mjs
    import { addTwo } from './addTwo.mjs';
    // Prints: 6
    console.log(addTwo(4)); 

    Node.js fully supports ECMAScript modules as they are currently specified and provides interoperability between them and its original module format, CommonJS .

    Enabling #

    CommonJS modules and ECMAScript modules.

    Authors can tell Node.js to use the ECMAScript modules loader via the .mjs file extension, the package.json "type" field, or the --input-type flag. Outside of those cases, Node.js will use the CommonJS module loader. See Determining module system for more details.

    Packages #

    Modules: Packages .

    import Specifiers #

    #

    "exports" field.

    Absolute specifiers like 'file:///opt/nodejs/config.js' . They refer directly and explicitly to a full path.

    Bare specifier resolutions are handled by the Node.js module resolution algorithm . All other specifier resolutions are always only resolved with the standard relative URL resolution semantics.

    Like in CommonJS, module files within packages can be accessed by appending a path to the package name unless the package's package.json contains an "exports" field, in which case files within packages can only be accessed via the paths defined in "exports" .

    For details on these package resolution rules that apply to bare specifiers in the Node.js module resolution, see the packages documentation .

    Mandatory file extensions #

    #

    percent-encoded , such as # with %23 and ? with %3F .

    file: , node: , and data: URL schemes are supported. A specifier like 'https://example.com/app.js' is not supported natively in Node.js unless using a custom HTTPS loader .

    file: URLs #

    URL and path resolution (such as percent encoding details), it is recommended to use url.pathToFileURL when importing a path.

    data: imports #

    data: URLs are supported for importing with the following MIME types:

  • text/javascript for ES modules
  • application/json for JSON
  • application/wasm for Wasm
  • import 'data:text/javascript,console.log("hello!");';
    import _ from 'data:application/json,"world!"' assert { type: 'json' }; 

    data: URLs only resolve bare specifiers for builtin modules and absolute specifiers . Resolving relative specifiers does not work because data: is not a special scheme . For example, attempting to load ./foo from data:text/javascript,import "./foo"; fails to resolve because there is no concept of relative resolution for data: URLs.

    node: imports #

    #

    Stability: 1 - Experimental

    The Import Assertions proposal adds an inline syntax for module import statements to pass on more information alongside the module specifier.

    import fooData from './foo.json' assert { type: 'json' };
    const { default: barData } =
      await import('./bar.json', { assert: { type: 'json' } }); 

    Node.js supports the following type values, for which the assertion is mandatory:

    Assertion type Needed for
    'json' JSON modules

    Builtin modules #

    Core modules provide named exports of their public API. A default export is also provided which is the value of the CommonJS exports. The default export can be used for, among other things, modifying the named exports. Named exports of builtin modules are updated only by calling module.syncBuiltinESMExports() .

    import EventEmitter from 'node:events';
    const e = new EventEmitter(); 
    import { readFile } from 'node:fs';
    readFile('./foo.txt', (err, source) => {
      if (err) {
        console.error(err);
      } else {
        console.log(source);
    }); 
    import fs, { readFileSync } from 'node:fs';
    import { syncBuiltinESMExports } from 'node:module';
    import { Buffer } from 'node:buffer';
    fs.readFileSync = () => Buffer.from('Hello, ESM');
    syncBuiltinESMExports();
    fs.readFileSync === readFileSync; 

    import() expressions #

    Dynamic import() is supported in both CommonJS and ES modules. In CommonJS modules it can be used to load ES modules.

    import.meta #

  • <Object>
  • The import.meta meta property is an Object that contains the following properties.

    import.meta.url #

  • <string> The absolute file: URL of the module.
  • This is defined exactly the same as it is in browsers providing the URL of the current module file.

    This enables useful patterns such as relative file loading:

    import { readFileSync } from 'node:fs';
    const buffer = readFileSync(new URL('./data.proto', import.meta.url)); 

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

    Stability: 1 - Experimental

    This feature is only available with the --experimental-import-meta-resolve command flag enabled.

  • specifier <string> The module specifier to resolve relative to parent .
  • parent <string> | <URL> The absolute parent module URL to resolve from. If none is specified, the value of import.meta.url is used as the default.
  • Returns: <string>
  • Provides a module-relative resolution function scoped to each module, returning the URL string. In alignment with browser behavior, this now returns synchronously.

    Caveat This can result in synchronous file-system operations, which can impact performance similarly to require.resolve .

    const dependencyAsset = import.meta.resolve('component-lib/asset.css'); 

    import.meta.resolve also accepts a second argument which is the parent module from which to resolve:

    import.meta.resolve('./dep', import.meta.url); 

    Interoperability with CommonJS #

    #

    import() expressions are supported in CommonJS for loading ES modules.

    When importing CommonJS modules , the module.exports object is provided as the default export. Named exports may be available, provided by static analysis as a convenience for better ecosystem compatibility.

    require #

    import() to load an ES module from a CommonJS module.

    CommonJS Namespaces #

    cjs-module-lexer for the exact semantics implemented.

    Differences between ES modules and CommonJS #

    #

    module.createRequire() .

    No __filename or __dirname #

    import.meta.url .

    No Addon Loading #

    Addons are not currently supported with ES module imports.

    They can instead be loaded with module.createRequire() or process.dlopen .

    No require.resolve #

    import.meta.resolve API.

    Alternatively module.createRequire() can be used.

    No NODE_PATH #
    #
    #

    #

    Stability: 1 - Experimental

    JSON files can be referenced by import :

    import packageConfig from './package.json' assert { type: 'json' }; 

    The assert { type: 'json' } syntax is mandatory; see Import Assertions .

    The imported JSON only exposes a default export. There is no support for named exports. A cache entry is created in the CommonJS cache to avoid duplication. The same object is returned in CommonJS if the JSON module has already been imported from the same path.

    Wasm modules #

    Stability: 1 - Experimental

    Importing WebAssembly modules is supported under the --experimental-wasm-modules flag, allowing any .wasm files to be imported as normal modules while also supporting their module imports.

    This integration is in line with the ES Module Integration Proposal for WebAssembly .

    For example, an index.mjs containing:

    import * as M from './module.wasm';
    console.log(M); 

    executed under:

    node --experimental-wasm-modules index.mjs 

    would provide the exports interface for the instantiation of module.wasm .

    Top-level await #

    status code .

    import { spawn } from 'node:child_process';
    import { execPath } from 'node:process';
    spawn(execPath, [
      '--input-type=module',
      '--eval',
      // Never-resolving Promise:
      'await new Promise(() => {})',
    ]).once('exit', (code) => {
      console.log(code); // Logs `13`
    }); 

    HTTPS and HTTP imports #

    Stability: 1 - Experimental

    Importing network based modules using https: and http: is supported under the --experimental-network-imports flag. This allows web browser-like imports to work in Node.js with a few differences due to application stability and security concerns that are different when running in a privileged environment instead of a browser sandbox.

    Imports are limited to HTTP/1 #

    #

    #

    #

    #

    #

    #

    Stability: 1 - Experimental

    This API is currently being redesigned and will still change.

    To customize the default module resolution, loader hooks can optionally be provided via a --experimental-loader ./loader-name.mjs argument to Node.js.

    When hooks are used they apply to each subsequent loader, the entry point, and all import calls. They won't apply to require calls; those still follow CommonJS rules.

    Loaders follow the pattern of --require :

    node \
      --experimental-loader unpkg \
      --experimental-loader http-to-https \
      --experimental-loader cache-buster 

    These are called in the following sequence: cache-buster calls http-to-https which calls unpkg .

    Hooks #

    realm . The hooks thread may be terminated by the main thread at any time, so do not depend on asynchronous operations (like console.log ) to complete.

    resolve(specifier, context, nextResolve) #
  • <string>
  • context <Object>
  • conditions <string[]> Export conditions of the relevant package.json
  • importAssertions <Object> An object whose key-value pairs represent the assertions for the module to import
  • parentURL <string> | <undefined> The module importing this one, or undefined if this is the Node.js entry point
  • nextResolve <Function> The subsequent resolve hook in the chain, or the Node.js default resolve hook after the last user-supplied resolve hook
  • specifier <string>
  • context <Object>
  • Returns: <Object> | <Promise>
  • format <string> | <null> | <undefined> A hint to the load hook (it might be ignored) 'builtin' | 'commonjs' | 'json' | 'module' | 'wasm'
  • importAssertions <Object> | <undefined> The import assertions to use when caching the module (optional; if excluded the input will be used)
  • shortCircuit <undefined> | <boolean> A signal that this hook intends to terminate the chain of resolve hooks. Default: false
  • url <string> The absolute URL to which this input resolves
  • Caveat Despite support for returning promises and async functions, calls to resolve may block the main thread which can impact performance.

    The resolve hook chain is responsible for telling Node.js where to find and how to cache a given import statement or expression. It can optionally return its format (such as 'module' ) as a hint to the load hook. If a format is specified, the load hook is ultimately responsible for providing the final format value (and it is free to ignore the hint provided by resolve ); if resolve provides a format , a custom load hook is required even if only to pass the value to the Node.js default load hook.

    Import type assertions are part of the cache key for saving loaded modules into the internal module cache. The resolve hook is responsible for returning an importAssertions object if the module should be cached with different assertions than were present in the source code.

    The conditions property in context is an array of conditions for package exports conditions that apply to this resolution request. They can be used for looking up conditional mappings elsewhere or to modify the list when calling the default resolution logic.

    The current package exports conditions are always in the context.conditions array passed into the hook. To guarantee default Node.js module specifier resolution behavior when calling defaultResolve , the context.conditions array passed to it must include all elements of the context.conditions array originally passed into the resolve hook.

    export function resolve(specifier, context, nextResolve) {
      const { parentURL = null } = context;
      if (Math.random() > 0.5) { // Some condition.
        // For some or all specifiers, do some custom logic for resolving.
        // Always return an object of the form {url: <string>}.
        return {
          shortCircuit: true,
          url: parentURL ?
            new URL(specifier, parentURL).href :
            new URL(specifier).href,
      if (Math.random() < 0.5) { // Another condition.
        // When calling `defaultResolve`, the arguments can be modified. In this
        // case it's adding another value for matching conditional exports.
        return nextResolve(specifier, {
          ...context,
          conditions: [...context.conditions, 'another-condition'],
      // Defer to the next hook in the chain, which would be the
      // Node.js default resolve if this is the last user-specified loader.
      return nextResolve(specifier);
    } 
    load(url, context, nextLoad) #
  • <string> The URL returned by the resolve chain
  • context <Object>
  • conditions <string[]> Export conditions of the relevant package.json
  • format <string> | <null> | <undefined> The format optionally supplied by the resolve hook chain
  • importAssertions <Object>
  • nextLoad <Function> The subsequent load hook in the chain, or the Node.js default load hook after the last user-supplied load hook
  • specifier <string>
  • context <Object>
  • Returns: <Object>
  • format <string>
  • shortCircuit <undefined> | <boolean> A signal that this hook intends to terminate the chain of resolve hooks. Default: false
  • source <string> | <ArrayBuffer> | <TypedArray> The source for Node.js to evaluate
  • The load hook provides a way to define a custom method of determining how a URL should be interpreted, retrieved, and parsed. It is also in charge of validating the import assertion.

    The final value of format must be one of the following:

    format Description Acceptable types for source returned by load
    'builtin' Load a Node.js builtin module Not applicable
    'commonjs' Load a Node.js CommonJS module Not applicable
    'json' Load a JSON file { string , ArrayBuffer , TypedArray }
    'module' Load an ES module { string , ArrayBuffer , TypedArray }
    'wasm' Load a WebAssembly module { ArrayBuffer , TypedArray }

    The value of source is ignored for type 'builtin' because currently it is not possible to replace the value of a Node.js builtin (core) module. The value of source is ignored for type 'commonjs' because the CommonJS module loader does not provide a mechanism for the ES module loader to override the CommonJS module return value . This limitation might be overcome in the future.

    Caveat : The ESM load hook and namespaced exports from CommonJS modules are incompatible. Attempting to use them together will result in an empty object from the import. This may be addressed in the future.

    These types all correspond to classes defined in ECMAScript.

  • The specific ArrayBuffer object is a SharedArrayBuffer .
  • The specific TypedArray object is a Uint8Array .
  • If the source value of a text-based format (i.e., 'json' , 'module' ) is not a string, it is converted to a string using util.TextDecoder .

    The load hook provides a way to define a custom method for retrieving the source code of an ES module specifier. This would allow a loader to potentially avoid reading files from disk. It could also be used to map an unrecognized format to a supported one, for example yaml to module .

    export async function load(url, context, nextLoad) {
      const { format } = context;
      if (Math.random() > 0.5) { // Some condition
          For some or all URLs, do some custom logic for retrieving the source.
          Always return an object of the form {
            format: <string>,
            source: <string|buffer>,
        return {
          format,
          shortCircuit: true,
          source: '...',
      // Defer to the next hook in the chain.
      return nextLoad(url);
    } 

    In a more advanced scenario, this can also be used to transform an unsupported source to a supported one (see Examples below).

    globalPreload() #
  • <Object> Information to assist the preload code
  • port <MessagePort>
  • Returns: <string> Code to run before application startup
  • Sometimes it might be necessary to run some code inside of the same global scope that the application runs in. This hook allows the return of a string that is run as a sloppy-mode script on startup.

    Similar to how CommonJS wrappers work, the code runs in an implicit function scope. The only argument is a require -like function that can be used to load builtins like "fs": getBuiltin(request: string) .

    If the code needs more advanced require features, it has to construct its own require using module.createRequire() .

    export function globalPreload(context) {
      return `\
    globalThis.someInjectedProperty = 42;
    console.log('I just set some globals!');
    const { createRequire } = getBuiltin('module');
    const { cwd } = getBuiltin('process');
    const require = createRequire(cwd() + '/<preload>');
    // [...]
    } 

    In order to allow communication between the application and the loader, another argument is provided to the preload code: port . This is available as a parameter to the loader hook and inside of the source text returned by the hook. Some care must be taken in order to properly call port.ref() and port.unref() to prevent a process from being in a state where it won't close normally.

    * This example has the application context send a message to the loader * and sends the message back to the application context export function globalPreload ( { port } ) { port. onmessage = ( evt ) => { port. postMessage (evt. data ); return `\ port.postMessage('console.log("I went to the Loader and back");'); port.onmessage = (evt) => { eval(evt.data); }

    Examples #

    #

    HTTPS and HTTP imports ).

    The loader below registers hooks to enable rudimentary support for such specifiers. While this may seem like a significant improvement to Node.js core functionality, there are substantial downsides to actually using this loader: performance is much slower than loading files from disk, there is no caching, and there is no security.

    // https-loader.mjs
    import { get } from 'node:https';
    export function resolve(specifier, context, nextResolve) {
      const { parentURL = null } = context;
      // Normally Node.js would error on specifiers starting with 'https://', so
      // this hook intercepts them and converts them into absolute URLs to be
      // passed along to the later hooks below.
      if (specifier.startsWith('https://')) {
        return {
          shortCircuit: true,
          url: specifier,
      } else if (parentURL && parentURL.startsWith('https://')) {
        return {
          shortCircuit: true,
          url: new URL(specifier, parentURL).href,
      // Let Node.js handle all other specifiers.
      return nextResolve(specifier);
    export function load(url, context, nextLoad) {
      // For JavaScript to be loaded over the network, we need to fetch and
      // return it.
      if (url.startsWith('https://'
    
    
    
    
        
    )) {
        return new Promise((resolve, reject) => {
          get(url, (res) => {
            let data = '';
            res.setEncoding('utf8');
            res.on('data', (chunk) => data += chunk);
            res.on('end', () => resolve({
              // This example assumes all network-provided JavaScript is ES module
              // code.
              format: 'module',
              shortCircuit: true,
              source: data,
          }).on('error', (err) => reject(err));
      // Let Node.js handle all other URLs.
      return nextLoad(url);
    } 
    // main.mjs
    import { VERSION } from 'https://coffeescript.org/browser-compiler-modern/coffeescript.js';
    console.log(VERSION); 

    With the preceding loader, running node --experimental-loader ./https-loader.mjs ./main.mjs prints the current version of CoffeeScript per the module at the URL in main.mjs .

    Transpiler loader #

    load hook . Before that hook gets called, however, a resolve hook needs to tell Node.js not to throw an error on unknown file types.

    This is less performant than transpiling source files before running Node.js; a transpiler loader should only be used for development and testing purposes.

    // coffeescript-loader.mjs
    import { readFile } from 'node:fs/promises';
    import { dirname, extname, resolve as resolvePath } from 'node:path';
    import { cwd } from 'node:process';
    import { fileURLToPath, pathToFileURL } from 'node:url';
    import CoffeeScript from 'coffeescript';
    const baseURL = pathToFileURL(`${cwd()}/`).href;
    // CoffeeScript files end in .coffee, .litcoffee, or .coffee.md.
    const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/;
    export function resolve(specifier, context, nextResolve) {
      if (extensionsRegex.test(specifier)) {
        const { parentURL = baseURL } = context;
        // Node.js normally errors on unknown file extensions, so return a URL for
        // specifiers ending in the CoffeeScript file extensions.
        return {
          shortCircuit: true,
          url: new URL(specifier, parentURL).href,
      // Let Node.js handle all other specifiers.
      return nextResolve(specifier);
    export async function load(url, context, nextLoad) {
      if (extensionsRegex.test(url)) {
        // Now that we patched resolve to let CoffeeScript URLs through, we need to
        // tell Node.js what format such URLs should be interpreted as. Because
        // CoffeeScript transpiles into JavaScript, it should be one of the two
        // JavaScript formats: 'commonjs' or 'module'.
        // CoffeeScript files can be either CommonJS or ES modules, so we want any
        // CoffeeScript file to be treated by Node.js the same as a .js file at the
        // same location. To determine how Node.js would interpret an arbitrary .js
        // file, search up the file system for the nearest parent package.json file
        // and read its "type" field.
        const format = await getPackageType(url);
        // When a hook returns a format of 'commonjs', `source` is ignored.
        // To handle CommonJS files, a handler needs to be registered with
        // `require.extensions` in order to process the files with the CommonJS
        // loader. Avoiding the need for a separate CommonJS handler is a future
        // enhancement planned for ES module loaders.
        if (format === 'commonjs') {
          return {
            format,
            shortCircuit: true,
        const { source: rawSource } = await nextLoad(url, { ...context, format });
        // This hook converts CoffeeScript source code into JavaScript source code
        // for all imported CoffeeScript files.
        const transformedSource = coffeeCompile(rawSource.toString(), url);
        return {
          format,
          shortCircuit: true,
          source: transformedSource,
      // Let Node.js handle all other URLs.
      return nextLoad(url);
    async function getPackageType(url) {
      // `url` is only a file path during the first iteration when passed the
      // resolved url from the load() hook
      // an actual file path from load() will contain a file extension as it's
      // required by the spec
      // this simple truthy check for whether `url` contains a file extension will
      // work for most projects but does not cover some edge-cases (such as
      // extensionless files or a url ending in a trailing space)
      const isFilePath = !!extname(url);
      // If it is a file path, get the directory it's in
      const dir = isFilePath ?
        dirname(fileURLToPath(url)) :
      // Compose a file path to a package.json in the same directory,
      // which may or may not exist
      const packagePath = resolvePath(dir, 'package.json');
      // Try to read the possibly nonexistent package.json
      const type = await readFile(packagePath, { encoding: 'utf8' })
        .then((filestring) => JSON.parse(filestring).type)
        .catch((err) => {
          if (err?.code !== 'ENOENT') console.error(err);
      // Ff package.json existed and contained a `type` field with a value, voila
      if (type) return type;
      // Otherwise, (if not at the root) continue checking the next directory up
      // If at the root, stop and return false
      return dir.length > 1 && getPackageType(resolvePath(dir, '..'));
    } 
    # main.coffee
    import { scream } from './scream.coffee'
    console.log scream 'hello, world'
    import { version } from 'node:process'
    console.log "Brought to you by Node.js version #{version}" 
    # scream.coffee
    export scream = (str) -> str.toUpperCase() 

    With the preceding loader, running node --experimental-loader ./coffeescript-loader.mjs main.coffee causes main.coffee to be turned into JavaScript after its source code is loaded from disk but before Node.js executes it; and so on for any .coffee , .litcoffee or .coffee.md files referenced via import statements of any loaded file.

    Resolution algorithm #

    #

    #

    #

  • 6.1.7 Array Index , throw an Invalid Package Configuration error.
  • For each property p of target , in object insertion order as,
  • If p equals "default" or conditions contains an entry for p ,
  • Let targetValue be the value of the p property in target .
  • Let resolved be the result of PACKAGE_TARGET_RESOLVE ( packageURL , targetValue , patternMatch , isImports , conditions ).
  • If resolved is equal to undefined , continue the loop.
  • Return resolved .
  • For each item targetValue in target , do
  • Let resolved be the result of PACKAGE_TARGET_RESOLVE ( packageURL , targetValue , patternMatch , isImports , conditions ), continuing the loop on any Invalid Package Target error.
  • If resolved is undefined , continue the loop.
  • Return resolved .
  • Return or throw the last fallback resolution null return or error.
  • Otherwise, if target is null , return null .
  • Otherwise throw an Invalid Package Target error.
  • ESM_FILE_FORMAT ( url )

  • Assert: url corresponds to an existing file.
  • If url ends in ".mjs" , then
  • Return "module" .
  • If url ends in ".cjs" , then
  • Return "commonjs" .
  • If url ends in ".json" , then
  • Return "json" .
  • Let packageURL be the result of LOOKUP_PACKAGE_SCOPE ( url ).
  • Let pjson be the result of READ_PACKAGE_JSON ( packageURL ).
  • If pjson?.type exists and is "module" , then
  • If url ends in ".js" , then
  • Return "module" .
  • Throw an Unsupported File Extension error.
  • Otherwise,
  • Throw an Unsupported File Extension error.
  • Set scopeURL to the parent URL of scopeURL .
  • If scopeURL ends in a "node_modules" path segment, return null .
  • Let pjsonURL be the resolution of "package.json" within scopeURL .
  • if the file at pjsonURL exists, then
  • Return scopeURL .
  • Let pjsonURL be the resolution of "package.json" within packageURL .
  • If the file at pjsonURL does not exist, then
  • Return null .
  • If the file at packageURL does not parse as valid JSON, then
  • Throw an Invalid Package Configuration error.
  • Return the parsed JSON source of the file at pjsonURL .
  • Customizing ESM specifier resolution algorithm #

    Loaders API provides a mechanism for customizing the ESM specifier resolution algorithm. An example loader that provides CommonJS-style resolution for ESM specifiers is commonjs-extension-resolution-loader .