我遇到一个需求,工程中,有个Node.js技术栈的代码库要用到。但是这个代码库默认发布出的代码,都是按 ESM 模式发布,服务器端的工程,都是按’CommonJS’模式操作,根本没有办法 ‘import xxx’ 这个代码库,只要导入就会报错。

Node.js 里面有所谓的’dynamic import’,我也做了测试,动态导入没有解决这个问题。因为它并不是只有一个文件,而是所有的文件都按 ESM 模式做了处理。

重新编译发布这个库么?非常复杂,光配置这个环境就要一大堆的设定。

反复测试之下,找到了一个比较好的解决方案:用 Babel 转换,用编译工具把 ESM 模块转换成 CommonJS 模块。

1、安装工具包

npm install --save-dev @babel/core @babel/cli @babel/preset-env npm install --save-dev @babel/plugin-transform-modules-commonjsCode language: Bash (bash)

2、在项目根目录下创建一个.babelrc文件,并添加以下内容:

{ "presets": ["@babel/preset-env"], "plugins": ["@babel/plugin-transform-modules-commonjs"] }Code language: JSON / JSON with Comments (json)

3、操作转换:

运行Babel来转换你的ESM模块。你可以创建一个npm脚本来方便执行这个操作。在

package.json中添加一个脚本命令:

"scripts": { "build": "babel src --out-dir lib" }Code language: JavaScript (javascript)

4、导入转换后的模块:

const myModule = require('./lib/commonjs-module'); // 如果使用 TypeScript,可以改成 importCode language: JavaScript (javascript)

事情到这里还没有结束。

目前模块是可以顺利引入了,可是运行会报错:global 对象没有 document/window 属性。

这个原因很容易理解:服务器端的 js 引擎确实是没有浏览器端的这个属性的,但是有一个 ‘jsdom’ 库可以用来模拟。

不过,npm 安装 jsdom 之后,global.document = dom.window.document 这种操作是不行的。因为 global 对象在Node.js 中是只读的,不能直接设置属性。

解决办法是:

Object.defineProperty(global, 'window', { value: dom.window, writable: true, configurable: true});Object.defineProperty(global, 'document', { value: dom.window.document, writable: true, configurable: true});Code language: JavaScript (javascript)

如此,这个程序包就顺利使用了。因为只使用其部分功能,不涉及浏览器层面的图像、字体渲染,这些问题就不再考虑了。

如何评价国区 Apple App Store下架了所有未备案App和境外开发 App?
我想购买苹果的Macbook Pro笔记本电脑,选什么配置合适?