【问题标题】:How to write ESM modules that work in both the browser, and Node, with conditional imports如何使用条件导入编写在浏览器和 Node 中都可以使用的 ESM 模块
【发布时间】:2020-12-27 06:30:45
【问题描述】:

我有一个应该在浏览器和节点中运行的代码库。它需要根据它是在节点还是浏览器中运行来切换一些功能。

以前我以 CommonJS 格式编写模块。我有一个“shim”模块,我会在其中测试环境的功能,并以此为基础导出内容。所以所有条件行为都包含在这个 shim 文件中。

现在,我尝试创建“shim”ESM 模块。我不知道怎么做。某些切换行为取决于检查是否存在其他 ESM 模块。但是您只能在异步的动态 ESM 导入中进行这样的测试。而且因为export 语句必须在顶层,所以我无法导出结果,除非顶层等待可用。但这在浏览器中不可用。

在我当前的 hack 中,我导出了一个类似延迟的对象,并在需要的地方await 它。但这让我很多不必要地被(async()=>{...})包裹住了。

那么我该怎么做呢?

我不想使用捆绑器,我的浏览器目标保证是相当新的。

【问题讨论】:

  • 对于这个问题,我认为除了顶级-await 之外没有其他解决方案(无论是原生支持还是某种转译)

标签: javascript node.js es6-modules commonjs


【解决方案1】:

在使用performance.now() 让模块同时在节点和浏览器中工作时遇到了类似的问题。

这行得通:

const P = typeof performance !== 'undefined' ? performance
  : (await import('perf_hooks')).performance

顶级等待挽救了这一天,但是:

  • 截至目前,仅适用于 chrome、node 和 firefox canary
  • 正式而言,仍然只是第 3 阶段的提案

【讨论】:

    【解决方案2】:

    另一个更惯用的答案是在package.json 中设置 main:main.jsbrowser:browser.js 字段以设置任何环境-导入和重新导出主模块之前的特定元素。

    //main.js fix for nodejs
    import {something} from 'nodejsSpecificModule'
    global.something = something //or whatever else needed
    export {...} from './index.js'
    
    //browser.js fix for browser
    import {something} from 'browserSpecificModule'
    window.something = something //or whatever else needed
    export {...} from './index.js'
    

    这避免了使用顶级等待的动态导入

    【讨论】:

      猜你喜欢
      • 2021-10-12
      • 1970-01-01
      • 2016-10-10
      • 2021-11-03
      • 2020-08-13
      • 2020-05-25
      • 2022-12-04
      • 2021-12-31
      • 1970-01-01
      相关资源
      最近更新 更多