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

TypeScript编译导致库导入失败(package.json exports配置问题)

问题描述

我正在开发一个JavaScript库,目标支持script标签引入、ES6导入、Node.js require导入三种方式,同时兼容TypeScript和各类构建工具,但实际实现遇到了不少问题。

我的package.json中相关的exports配置如下:

"exports": {
    ".": {
        "require": "./dist/slim.copper.cjs",
        "import": "./dist/slim.copper.js",
        "types": "./dist/typed.copper.d.ts"
    }
}

在TypeScript测试项目中,我用import Copper from "@jwrunge/copper";导入库,类型提示和智能感知正常,编译JavaScript也没报错,但运行Node时出现错误:

C:\Users\jrunge\Documents\CODE\copper_test\src\index.js:3
var copper_1 = require("@jwrunge/copper");
               ^

Instead change the require of slim.copper.js in C:\Users\jrunge\Documents\CODE\copper_test\src\index.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (C:\Users\jrunge\Documents\CODE\copper_test\src\index.js:3:16) {
  code: 'ERR_REQUIRE_ESM'
}

TypeScript编译输出的JavaScript代码用了require,还保留了ES模块的风格:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var copper_1 = require("@jwrunge/copper");
var store1 = copper_1.default.store("foo", { value: 12 });

我在输出的JS里打印copper_1,结果如下,没有default属性,看起来像是直接导入了.cjs版本:

{
  store: [Function: store],
  ustore: [Function: ustore],
  getFunc: [Function: getFunc],
  addFuncs: [Function: addFuncs],
  config: [Function: config]
}

另外,如果只提供ES模块(.js文件)不支持require,会触发以下错误:

Error [ERR_REQUIRE_ESM]: require() of ES Module C:\Users\jrunge\Documents\CODE\pubsub\dist\slim.copper.js from C:\Users\jrunge\Documents\CODE\copper_test\src\index.js not supported.
Instead change the require of slim.copper.js in C:\Users\jrunge\Documents\CODE\copper_test\src\index.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (C:\Users\jrunge\Documents\CODE\copper_test\src\index.js:3:16) {
  code: 'ERR_REQUIRE_ESM'
}

我有两个疑问:

  1. 实际情况是不是JS输出用了库的.cjs版本,而这个版本没有ES模块那样的default导出?
  2. 在保留require支持的前提下,有哪些优雅/标准的解决方法?我可以接受给用户简单的使用说明,但更希望从库侧优化适配。
解决方案

问题1的确认

是的,你的判断完全正确。核心原因是:

  • TypeScript编译输出了CommonJS格式代码(使用require),Node.js会匹配package.json exports里的require字段,加载.cjs版本的库。
  • 你的.cjs文件基于CommonJS规范编写,直接导出了方法集合(比如module.exports = { store, ustore... }),没有default属性;而ES模块版本的.js文件用export default导出,TypeScript编译后会尝试访问copper_1.default,但CommonJS版本中不存在该属性,因此报错。

问题2的解决方法

方案1:库侧统一导出格式(推荐)

让CommonJS和ES模块版本的导出结构对齐,同时支持默认导入和命名导入:

  • 修改CommonJS版本代码:在直接导出对象的基础上,添加default属性适配ES模块逻辑:
    // slim.copper.cjs
    const copper = {
      store: function() {},
      ustore: function() {},
      // ...其他方法
    };
    module.exports = copper;
    // 添加default属性,适配ES模块默认导入
    module.exports.default = copper;
    
  • ES模块版本保持不变:继续使用export default,也可按需添加命名导出:
    // slim.copper.js
    export const store = function() {};
    export const ustore = function() {};
    // ...其他命名导出
    export default { store, ustore, /* ... */ };
    

这样无论用require还是import,都能正常访问到对应导出内容,TypeScript编译后的代码也不会出错。

方案2:优化package.json配置

在package.json中添加type字段,明确默认模块类型,同时配合exports字段的规则:

{
  "type": "module",
  "exports": {
    ".": {
      "require": "./dist/slim.copper.cjs",
      "import": "./dist/slim.copper.js",
      "types": "./dist/typed.copper.d.ts"
    }
  }
}

这个字段告诉Node.js默认文件是ES模块,但exports里的require字段会优先匹配CommonJS版本,确保使用require的用户能正常加载。

方案3:给用户的简单使用提示

如果不想修改库代码,可以告知用户两种环境下的正确导入写法:

  • ES模块/TypeScript环境:可使用默认导入或命名导入:
    // 方式1:默认导入
    import Copper from "@jwrunge/copper";
    // 方式2:命名导入(更直观)
    import { store, ustore } from "@jwrunge/copper";
    
  • CommonJS环境:直接使用require结果,无需访问default:
    const Copper = require("@jwrunge/copper");
    Copper.store("foo", { value: 12 });
    

方案4:TypeScript编译配置优化

如果是用户侧的TypeScript项目,可让用户修改tsconfig.json,输出ES模块而非CommonJS:

{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "NodeNext",
    "target": "ES6"
  }
}

编译后的代码会使用import而非require,Node.js会加载ES模块版本,避免default属性找不到的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:27:36