Node.js如何用C++创建可被ES6模块导入的原生扩展
解决C++ Addon在ES模块(.mjs)中无法导入的问题
核心原因
原生C++ Addon本身不属于CommonJS或ES模块范畴,你遇到的ERR_MODULE_NOT_FOUND报错本质是ES模块加载原生模块的规则和CommonJS不同:
- CommonJS的
require可以自动识别.node后缀的原生addon文件,也支持路径后缀自动补全 - ES模块的
import默认不会自动补全.node后缀,低版本Node.js也不支持直接导入原生addon,需要适配特定的加载规则
可行实现方案
你原有通过node-gyp编译的原生addon不需要修改C++源码和编译流程,按以下任意一种方式适配即可正常在.mjs中使用:
方案1:通过createRequire兼容导入(兼容性最好)
直接在.mjs文件中构造CommonJS require能力加载原生addon:
import { createRequire } from 'module'; const require = createRequire(import.meta.url); // 按实际路径填写编译生成的.node文件位置 const addon = require('./build/Release/addon.node'); // 后续正常调用addon暴露的方法即可 console.log(addon.hello());
方案2:新增ES模块包装层,支持直接import
如果希望对外暴露标准ES模块导入接口,不需要业务方每次写createRequire,可以新增一个ES模块入口文件index.mjs:
import { createRequire } from 'module'; const require = createRequire(import.meta.url); const nativeAddon = require('./build/Release/addon.node'); // 按需导出原生模块的接口 export const hello = nativeAddon.hello; export default nativeAddon;
之后其他.mjs文件就可以直接导入使用:
// 导入全部接口 import addon from './index.mjs'; // 导入指定接口 import { hello } from './index.mjs';
方案3:使用导入断言(Node.js 16.12+ 支持)
高版本Node.js支持通过导入断言直接导入原生addon,必须显式填写.node后缀:
import addon from './build/Release/addon.node' assert { type: 'node-addon' }; console.log(addon.hello());
内容的提问来源于stack exchange,提问作者Dan D
相关产品推荐
相关产品推荐

