You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Node.js动态导入添加自定义文件扩展名?

解决Node.js ESM动态导入自定义文件类型(.jszip)的问题

你遇到的核心问题是ESM模块加载器和CommonJS的模块扩展机制不兼容——你用require.extensions和Module._extensions是CommonJS的玩法,但启用--experimental-modules后,Node.js切换到了ESM加载器,这套机制就完全不生效了,所以会抛出ERR_UNKNOWN_FILE_EXTENSION错误。

下面是具体的解决步骤:

1. 编写ESM自定义加载器

ESM有专门的加载器API,我们需要创建一个自定义加载器来处理.jszip文件。新建一个jszip-loader.js文件,内容如下:

import { readFile } from 'fs/promises';
import { fileURLToPath } from 'url';
import { dirname, extname } from 'path';

// 处理模块路径解析
export async function resolve(specifier, context, defaultResolve) {
  const { parentURL } = context;
  // 仅针对.jszip文件做自定义解析
  if (specifier.endsWith('.jszip')) {
    // 处理相对路径的情况
    if (specifier.startsWith('./') || specifier.startsWith('../')) {
      const resolvedPath = new URL(specifier, parentURL).href;
      return { url: resolvedPath };
    }
  }
  // 其他类型文件交给默认解析逻辑
  return defaultResolve(specifier, context, defaultResolve);
}

// 处理模块内容加载
export async function load(url, context, defaultLoad) {
  const fileExt = extname(fileURLToPath(url));
  if (fileExt === '.jszip') {
    // 读取文件内容
    const content = await readFile(fileURLToPath(url), 'utf8');
    // 这里可以添加你对content的自定义处理逻辑
    console.log('In custom .jszip loader');
    // 将处理后的内容作为ESM模块返回
    return {
      format: 'module',
      source: content,
    };
  }
  // 其他类型文件交给默认加载逻辑
  return defaultLoad(url, context, defaultLoad);
}

2. 修改package.json脚本

更新你的package.json,添加--loader参数指定自定义加载器,同时声明项目默认使用ESM:

{
  "name": "test",
  "type": "module", // 让Node.js默认按ESM解析.js文件
  "scripts": {
    "zip": "node --experimental-modules --loader ./jszip-loader.js test.js"
  }
}

注意:如果你的Node.js版本是16及以上,--loader已经是稳定特性;如果是更早版本,需要替换为--experimental-loader。

3. 调整test.js代码

现在用ESM语法重构test.js,适配ESM的异步导入规则:

import { fileURLToPath } from 'url';
import { dirname } from 'path';

// ESM中模拟__dirname和__filename
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

async function loadJs(relativePath) {
  try {
    // 构建目标文件的完整URL(ESM导入需要用URL或绝对路径)
    const fileUrl = new URL(relativePath, import.meta.url);
    const module = await import(fileUrl.href);
    console.log(`imported from ${relativePath}:`, module);
  } catch (err) {
    console.log(`While importing:`, err);
  }
}

// 调用加载函数
loadJs('./testfile.jszip');

4. 测试运行

执行npm run zip,你就能看到自定义加载器的日志输出,并且成功导入.jszip文件了。

关键注意点

  • ESM加载器是异步机制,所以必须用async/await处理动态导入;
  • 自定义加载器的resolve和load函数是ESM加载流程的核心,分别负责路径解析和内容加载;
  • 不要混用CommonJS和ESM的扩展机制,启用ESM后完全依赖加载器API处理自定义文件类型。

内容的提问来源于stack exchange,提问作者pebl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:38:42