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

Node.js(TypeScript)导入Keycloak Admin Client遇ESM/CJS兼容问题

Node.js(TypeScript)中Keycloak Admin Client模块兼容问题解决

问题背景

在Node.js(TypeScript)项目中使用@keycloak/keycloak-admin-client时,遭遇ES6/CommonJS模块兼容错误:代码中明明用了ES模块的import语法,运行时却提示require()加载ES模块不支持。尝试添加"type": "module"到package.json后,又出现TypeError: Unknown file extension ".ts"错误,动态导入类名时也频繁出现编译语法错误。

代码片段

import [... whatever ...]
import KcAdminClient from '@keycloak/keycloak-admin-client';
import { Credentials } from '@keycloak/keycloak-admin-client/lib/utils/auth';

export class Controller {
  private kcAdminClient = new KcAdminClient();
  [...]
}

错误信息

Error [ERR_REQUIRE_ESM]: require() of ES Module .../node_modules/@keycloak/keycloak-admin-client/lib/index.js from .../server/logic/auth/users.ts not supported.
Instead change the require of index.js in .../server/logic/auth/users.ts to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (.../server/logic/auth/users.ts:10:49)
    at m._compile (.../node_modules/ts-node/dist/index.js:791:29)
    at require.extensions.<computed> [as .ts] (.../node_modules/ts-node/dist/index.js:793:16) {
  code: 'ERR_REQUIRE_ESM'
}

核心疑问解答

1. “这类库”指什么?

这类库是纯ES模块库:即库的package.json中声明了"type": "module",或所有输出文件为.mjs格式,只能被ES模块加载,无法被CommonJS的require()直接调用。@keycloak/keycloak-admin-client就属于这类库,它的构建产物是纯ES模块,不兼容CommonJS的同步加载逻辑。

你的代码虽然写了import,但如果项目默认是CommonJS环境(比如package.json无"type": "module"、TypeScript配置module设为CommonJS),TypeScript会把import编译成require(),这就触发了错误——用require()加载纯ES模块。


解决方案

方案一:将项目切换为ES模块环境

这是最彻底的解决方式,让项目整体与目标库的模块类型保持一致:

  1. 在项目根目录package.json中添加:
    "type": "module"
    
  2. 修改tsconfig.json配置,确保输出为ES模块:
    {
      "compilerOptions": {
        "module": "ESNext", // 或ES2020及以上版本
        "moduleResolution": "NodeNext",
        "target": "ES2020",
        "esModuleInterop": true,
        "skipLibCheck": true
      },
      "include": ["src/**/*"]
    }
    
  3. 解决.ts文件扩展名错误:
    • 若用ts-node,需安装ts-node-esm,修改启动命令为:
      ts-node-esm your-entry-file.ts
      
    • 或改用tsx替代ts-node,它原生支持ES模块和TypeScript,启动命令更简洁:
      tsx your-entry-file.ts
      

方案二:在CommonJS环境中使用动态导入

如果不想切换项目模块类型,可通过动态导入(import())加载纯ES模块,注意动态导入是异步操作,需调整代码结构:

import [... whatever ...]

export class Controller {
  // 先声明类型,避免类型报错
  private kcAdminClient: Awaited<typeof import('@keycloak/keycloak-admin-client').default>;
  private credentialsType: typeof import('@keycloak/keycloak-admin-client/lib/utils/auth').Credentials;

  constructor() {
    this.initKeycloak();
  }

  private async initKeycloak() {
    // 动态导入库及类型
    const KcAdminClient = (await import('@keycloak/keycloak-admin-client')).default;
    const { Credentials } = await import('@keycloak/keycloak-admin-client/lib/utils/auth');
    
    this.kcAdminClient = new KcAdminClient();
    this.credentialsType = Credentials;

    // 后续初始化逻辑,比如配置Keycloak连接
    await this.kcAdminClient.setConfig({
      baseUrl: 'http://your-keycloak-url',
      realm: 'master',
    });
  }

  // 所有依赖kcAdminClient的方法都要改为异步
  async someBusinessMethod() {
    await this.kcAdminClient.auth({
      clientId: 'admin-cli',
      username: 'admin',
      password: 'admin',
      grantType: 'password',
    });
    // 调用Admin Client的其他方法
  }
}

注意:因动态导入是异步的,所有依赖kcAdminClient的操作必须等待初始化完成,避免出现undefined调用错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 21:03:39