问题描述
我有一个应该在浏览器和节点中运行的代码库。它需要根据是否在节点或浏览器中运行来切换某些功能。
以前,我以Commonjs格式编写模块。我有一个“填充程序”模块,可以在其中测试功能部件的环境,然后基于该模块导出内容。因此,所有条件行为都包含在此shim文件中。
现在,我尝试创建“ Shim” ESM模块。我不知道怎么办。某些切换行为取决于检查其他ESM模块是否存在。但是,您只能在异步的动态ESM导入中进行此类测试。而且由于export
语句必须在顶层,所以除非有顶层等待可用,否则我无法导出结果。但这在浏览器中不可用。
在我当前的黑客中,我导出了类似延迟的对象,并在需要时await
导出它。但这使我不必要地包裹在(async()=>{...})
中。
那我该怎么做?
我宁愿不使用捆绑程序,我的浏览器目标肯定是最新的。
解决方法
使用 performance.now()
使模块在节点和浏览器中都能工作时遇到了类似的问题。
这有效:
const P = typeof performance !== 'undefined' ? performance
: (await import('perf_hooks')).performance
顶级等待挽救了这一天,但是:
- 截至目前,仅适用于 chrome、node 和 firefox canary
- 正式来说,仍然只是第 3 阶段的提案
另一个更惯用的答案是在 package.json
中设置 main:main.js 和 browser: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'
这避免了使用顶级等待的动态导入