阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      Node.js ECMAScript 加载器钩子解析

      Node.js ECMAScript

      加载器钩子

      要自定义默认模块分辨率,可以选择通过Node.js的 --loader ./loader-name.mjs参数提供加载程序挂钩。

      使用挂钩时,它们仅适用于ES模块加载,而不适用于加载的任何CommonJS模块。

      解析钩子

      resolve钩子返回给定模块说明符和父文件URL的已解析文件URL和模块格式

      const baseURL = new URL('file://');
      baseURL.pathname = `${process.cwd()}/`;
      
      export async function resolve(specifier, parentModuleURL = baseURL,  defaultResolver) {
        return {
          url: new URL(specifier, parentModuleURL).href,
          format: 'esm'
        };
      }
      

      在执行主Node.js加载时,parentModuleURL以未定义的形式提供。

      默认的Node.js ES模块解析功能作为解析器的第三个参数提供,以便于兼容性工作流程。

      除了返回已解析的文件URL值之外,resolve hook还返回format属性,该属性指定已解析模块的模块格式。这可以是以下之一:

      格式描述
      ‘esm’加载标准JavaScript模块
      ‘cjs’加载节点式CommonJS模块
      ‘builtin’加载内置CommonJS模块的节点
      ‘json’加载JSON文件
      ‘addon’加载C ++插件
      ‘dynamic’使用动态实例化挂钩

      例如,可以编写一个虚拟加载器,用于加载限制为浏览器解析规则的JavaScript,只有JS文件扩展名和Node.js内置模块支持

      import path from 'path';
      import process from 'process';
      import Module from 'module';
      
      const builtins = Module.builtinModules;
      const JS_EXTENSIONS = new Set(['.js', '.mjs']);
      
      const baseURL = new URL('file://');
      baseURL.pathname = `${process.cwd()}/`;
      
      export function resolve(specifier, parentModuleURL = baseURL, defaultResolve) {
        if (builtins.includes(specifier)) {
          return {
            url: specifier,
            format: 'builtin'
          };
        }
        if (/^\.{0,2}[/]/.test(specifier) !== true && !specifier.startsWith('file:')) {
          // For node_modules support:
          // return defaultResolve(specifier, parentModuleURL);
          throw new Error(
            `imports must begin with '/', './', or '../'; '${specifier}' does not`);
        }
        const resolved = new URL(specifier, parentModuleURL);
        const ext = path.extname(resolved.pathname);
        if (!JS_EXTENSIONS.has(ext)) {
          throw new Error(
            `Cannot load file with non-JavaScript file extension ${ext}.`);
        }
        return {
          url: resolved.href,
          format: 'esm'
        };
      }
      

      有了这个装载机,就可以运行

      NODE_OPTIONS='--experimental-modules --loader ./custom-loader.mjs' node x.js
      

      将模块x.js加载为具有相对分辨率支持的ES模块(在此示例中跳过了node_modules加载)


      更多选项请参考:ECMAScript 模块,或者通过 点击对应菜单 进行查看;


      目录
      目录