如果作为 CommonJS 或 ESM 模块运行,请检查 NodeJS JavaScript 运行时代码

问题描述 投票:0回答:2

我正在编写一个可以在 CommonJS 和 ESM 模块系统中使用的 JS 函数。

但是根据运行的情况,它会做不同的事情。

有什么方法可以在运行时代码中测试我们所处的系统吗?

javascript node.js es6-modules commonjs
2个回答
0
投票

我的方法使用单独的生成进程来检测文件正在运行的当前模块系统。

脚本作为子进程运行:

checkType.js

import('node:process').then(({ stdout }) => {
  try {
    require.main
  } catch {
    stdout.write('module')
    return 'module'
  }

  try {
    import.meta
  } catch {
    stdout.write('commonjs')
    return 'commonjs'
  }
})

用于确定运行时模块上下文的父进程:

moduleType.js

export const moduleType = async () => {
  const { resolve } = await import('node:path')
  const { spawnSync } = await import('node:child_process')
  const { stdout, stderr } = spawnSync('node', [resolve(import.meta.dirname, 'checkType.js')])
  let type = 'unknown'

  // Only one of these will be non-falsy strings
  const err = stderr.toString()
  const out = stdout.toString()

  /**
   * Based on error messaging from v8
   * @see https://github.com/nodejs/node/blob/bc13f23f7e25d750df9b0a7bfe891a3d69f995f3/deps/v8/src/common/message-template.h#L124
   */
  if (/outside a module/i.test(err)) {
    type = 'commonjs'
  }

  if (out) {
    type = out
  }

  return type
}

moduleType.js 在构建过程中转换为 ESM 和 CJS 模块,这在 TypeScript 等其他工具链中可能很有用。

一些文件.ts

import { moduleType } from './moduleType.js'

;(async () => {
  console.log(`ts file running in module mode ${await moduleType()}`
})()

模块类型由

"type"
中的
package.json
或文件扩展名(
.cts
.mts
)决定。

这是否最终有用取决于除了发布双包之外是否存在任何用例。 FWIW,我在 npm 上的 node-module-type 下提供了此功能。


-2
投票

如果满足以下条件,那么您正在使用 CommonJS 模块运行:

typeof module !== 'undefined' && typeof exports !== 'undefined'

但是,要检查您是否正在使用 ECMAScript 模块,您可以使用以下条件:

typeof import !== 'undefined' && typeof export !== 'undefined'

您可以在代码中使用它,如下所示:

if (typeof module !== 'undefined' && typeof exports !== 'undefined') {
  // CommonJS code path
} else if (typeof import !== 'undefined' && typeof export !== 'undefined') {
  // ESM code path
}

注意:我通常使用 TypeScript,这就是我使用的方法。当 TypeScript 编译为 JavaScript 时,它会改变形式。然而,我相信这是最好的解决方案,并且应该与常规普通 JS 完全兼容

© www.soinside.com 2019 - 2024. All rights reserved.