从 Webpack ReactJS/ReactTS 项目导入/需要 NAPI 插件

Posted

技术标签:

【中文标题】从 Webpack ReactJS/ReactTS 项目导入/需要 NAPI 插件【英文标题】:Importing/requiring an NAPI addon from a Webpack ReactJS/ReactTS project 【发布时间】:2021-03-30 05:10:24 【问题描述】:

我有一个自定义 API(暂时关闭源代码),用纯 C 构建。这个 API 是通信协议的客户端(想想基于网络的数据库查询)。我已成功使用 node-gyp 编译 C 代码包装器,以便 NAPI 插件 addon.node 可以通过调用 C 在 javascript 中运行。我还编写了一个 .d.ts 文件,以便此插件可以在 TypeScript 中工作。这两个用例我都没有问题;即,执行tsc index.ts && nodejs index.js 将顺利编译和运行导入/所需的插件,并且我的C API 的客户端操作顺利进行。我已将此插件制作成一个私有 npm 包,并一直在小型 TypeScript 项目中使用它,将其安装为 node_modules 依赖项,没有任何问题。

当我尝试运行需要使用此插件的 React Web 应用程序时,我的问题出现了。我需要 React,因为我的数据查询将用于 GUI 类型的 Web 小程序(查询它们的数据,并实时更新 GUI 视图)。我使用react-scripts start 启动我的 React 应用程序,就像通​​过 webpack/create-react-app 创建的任何 React 项目一样。我不知道除了react-scripts-family 命令之外,是否还有其他方法可以启动 ReactJS/ReactTS 项目。如果您知道替代方案,我会尝试。

正是我的错误:

在 TypeScript 方面:当我尝试导入/需要插件时,我收到 Module not found: Can't resolve '@my-company/my_package/addon' in '/path/to/typescript/srcdirectory' 错误,以获取正确的路径。是的,我绝对确定我的路径是正确的(在package.json“路径”和调用源中);找到相同依赖目录中的其他(普通.ts)文件,并使用相同的路径(和它们自己的文件名)从相同的.tsx.ts 源很好地导入。另请注意,使用tsc 编译的非React .ts 文件可以很好地识别相同的路径+文件名(即addon 而不是addon.node)。由node-gyp 生成的addon.nodereact-scripts start 处理TypeScript 转换时根本无法识别。

在 JavaScript 方面:我还尝试首先使用 tsc 为我的 TS 源生成相应的 JS 文件,并“要求”我的插件;然后启动react-scripts。对于生成的 JS 中的路径 var api = require("@my-company/my_package/addon");,我得到相同的“找不到模块”错误。对于var api = require("@my-company/my_package/addon.node");,插件被识别,但是,当我到达任何带有api.MyFunction() 的行时,JS 会失败,对于任何函数,带有TypeError: api.MyFunction is not a function

我在 SO 上发现了以下问题,似乎与我的有关:How to use a native node.js addon in React;但它没有得到答复,并且可能不会发生与我完全相同的原因。

我的问题是:用 node-gyp 编译 NAPI 插件、将其打包为 npm 的特定结构并从 React JS/TS 项目导入以使导入工作的合适方法是什么?是否应该验证插件的 package.json 或 React 项目中的某些特定约束,以便能够顺利工作?我不确定很多人是否有过这种用例的经验(从原始 C 一直到 ReactTS);但是肯定会有一些 NAPI 插件很有名,可以在一些 React 项目中使用:即使是指向它的链接也可能对我有用。

您提供的任何链接、想法或建议将不胜感激。感谢您的宝贵时间。

编辑:经过大量实验和文档阅读,我现在确信问题源于 webpack,并且需要在 webpack.config.js 中使用 externals 来解决我如何以某种方式导入插件。 webpack.config.js 的语法是什么,应该如何将这个“外部”库导入到我的 .tsx 文件中?使用特定的 Webpack 配置时,我的 package.json 有什么特别之处吗?

【问题讨论】:

【参考方案1】:

所以我设法解决了我的问题。事实证明,这个问题比我想象的更根本。我通过以下链接找到了答案,并通过询问 Reactiflux discord 了解了解决方案。由于以下问题并未真正解释可用的解决方案,因此我想将它们发布在这里。

How to use Native Node Modules on a React, ES6, Electron App?

Cannot load Node native addons with webpack

基本上,本机节点插件只能从节点服务器启动,而不能直接从浏览器启动。出于安全目的,浏览器将永远不会从节点插件本身运行代码。即,node-gyp/napi 不是一些“C 到 JS”的转译器。如果你想要那种东西,请查找emscripten

解决此问题的仅节点解决方案是将前端逻辑与后端逻辑分开。我的意思是一方面有一个小型节点服务器(例如与express 一起服务)来处理需要由插件完成的事情;另一方面,在另一个项目中拥有一个 React 前端客户端,该客户端连接到该服务器以获取前端所需的任何数据(例如,通过让服务器将 JSON 传递给客户端)。这允许浏览器以浏览器本身不运行任何插件代码的方式使用插件操作的结果。从第一个链接中可以看出,对于一个 Electron 应用程序要做一些类似的划分,使用ipcRendererremote 而不是express 在应用程序的前端和后端部分之间进行通信.

【讨论】:

以上是关于从 Webpack ReactJS/ReactTS 项目导入/需要 NAPI 插件的主要内容,如果未能解决你的问题,请参考以下文章

webpack从入门到精通

从 Webpack 3 迁移到 Webpack 4

[webpack] webpack 从入门到 所有

webpack 从入门到放弃

React/Webpack - 从 webpack 1 迁移到 4,配置对象无效

Angular Webpack 设置:使用 webpack 从 css 迁移到 sass