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

如何在utils.js中按需条件导出DOM相关工具函数

条件导出工具模块的解决方案

问题背景

我有一个大型工具模块utils.js,包含原生JS导出和DOM相关导出(例如使用Canvas)。希望在浏览器主线程外的环境(如Worker、Deno)中避免导入DOM工具函数。

曾尝试仅在浏览器主线程导出DOM函数,但因导出必须为顶层语句,if( inDom ) export function ...会报错。用try-catch包裹代码在Deno中也无法正常工作,因为Deno会在加载时检查导入,与浏览器不同。

于是我将utils.js拆分为jsUtils.js和domUtils.js,希望保留utils.js作为入口文件,始终导出jsUtils.js的内容,仅在浏览器主线程条件导出domUtils.js的内容。

本以为可以像这样实现:

const inDom = typeof document !== undefined
export * from './jsUtils.js'
if( inDom ) export * from './domUtils.js'

但显然这会失败,因为第二个export不是顶层语句。

我的问题是:如何实现一个始终包含jsUtils.js且仅在inDom条件下包含domUtils.js的utils.js?


可行解决方案

1. 动态导入+导出合并(异步场景)

利用ES模块的动态导入特性,将DOM工具的导出合并到当前模块。这种方式适合异步使用DOM工具的场景:

// 始终导出原生JS工具
export * from './jsUtils.js';

const inDom = typeof document !== 'undefined';
if (inDom) {
  // 异步加载DOM工具并合并到导出对象
  (async () => {
    const domUtils = await import('./domUtils.js');
    Object.assign(exports, domUtils);
  })();
}

注意:DOM相关导出是异步可用的,同步依赖会导致获取不到。

2. 顶层await同步加载(ES2022+环境)

ES2022支持的顶层await可以实现同步条件导入,确保DOM导出在模块加载完成后可用:

export * from './jsUtils.js';

const inDom = typeof document !== 'undefined';
if (inDom) {
  const domUtils = await import('./domUtils.js');
  // 批量将DOM工具的导出挂载到当前模块
  for (const key in domUtils) {
    if (Object.prototype.hasOwnProperty.call(domUtils, key)) {
      exports[key] = domUtils[key];
    }
  }
}

需要环境支持顶层await(现代浏览器、Deno 1.20+、Node.js 14.8+等)。

3. CommonJS兼容写法(混合模块环境)

如果环境支持CommonJS或混合模块,可以用同步的方式合并导出:

// 导入并导出原生JS工具
const jsUtils = require('./jsUtils.js');
module.exports = { ...jsUtils };

const inDom = typeof document !== 'undefined';
if (inDom) {
  // 条件导入DOM工具并合并导出
  const domUtils = require('./domUtils.js');
  Object.assign(module.exports, domUtils);
}

这种方式兼容性好,所有导出都是同步可用的。

4. package.json条件导出(npm包场景)

如果是npm包项目,可以通过package.json的条件导出配置,让运行时或打包工具自动选择对应环境的入口:
首先在package.json中添加:

{
  "exports": {
    ".": {
      "browser": "./utils.browser.js",
      "default": "./utils.default.js"
    }
  }
}

然后创建两个入口文件:

  • utils.browser.js(浏览器主线程用):
export * from './jsUtils.js';
export * from './domUtils.js';
  • utils.default.js(非浏览器主线程用):
export * from './jsUtils.js';

这种方式无需在代码中做环境判断,是最优雅的方案之一。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 18:55:27