首页 > 解决方案 > 如何在 ReasonML 绑定中包含来自相邻文件的无类型 JavaScript?

问题描述

在尝试开始使用 Reason 时,在一个 JavaScript 项目中,我有一个非常轻量级的文件,它试图成为现有重型库的 Reason 类型接口:

/* TheLibrary.re */
type engine

external addEngine : string -> engine -> unit = "" [@@bs.val] [@@bs.module "../"]

但是,当我尝试在 ReasonReact 项目(已添加到)中使用该库时,@org/the-librarybsconfig.json bs-dependencies

/* AComponent.re */
[@bs.val] [@bs.module "@org/game-engine/dist/game-engine.js"]
   external gameEngine : TheLibrary.engine = "default";

/* Further down, a React lifecycle method, */
TheLibrary.addEngine("Game", gameEngine);

相对于该 React 组件,我收到有关../未找到的错误:

./src/components/main-menu/AComponent.re
Module not found: Can't resolve '../' in '/Users/ec/Work/reason-reacty/src/components/main-menu'

我也尝试过,而不是../inTheLibrary.reexternal声明:

  1. @bs.module "./index.js"(相关包的无类型 JavaScript 端的直接 ES6 入口点,)
  2. @bs.module "@org/the-library",所述库的全名(即使我该库中输入???)

请帮忙!我希望能够进一步采用 ML,但我最难理解 ReasonReact 的依赖解析!


附加上下文:

因此,我们正在尝试构建我们的第一个 ReasonReact 项目,并且我们已经成功地将 baby's-first-opaque-types 添加到我们的一个内部库中,并将其包含在ReasonReact 页面中,如下所示 -由方法:

/* Imports.re */
type engine;

[@bs.val] [@bs.module "@org/game-engine/dist/game-engine.js"]
   external gameEngine : engine = "default";
[@bs.val] [@bs.module "@org/the-library"] [@bs.scope "default"]
   external addEngine : (string, engine) => unit = "";

这会产生,当我们Imports.(addEngine("Game", gameEngine)),我们需要的全局设置行TheLibrary.addEngine("Game", GameEngine):我正处于尝试将输入信息上游到父项目的第一阶段,并将该代码发布到 npm,以便所有消费项目都可以开始使用 Reason。

标签: javascriptocamlreasonbucklescriptreason-react

解决方案


听起来您可能对构成您的工具链的不同工具有点困惑,所以让我们首先逐个浏览它们以将它们放在适当的位置:

  • ReasonReact是一个固执的、“厚”绑定到 react.js 的库,尽管名称实际上并不是特定于 Reason 的,除了它与 Reason 的 JSX 语法的集成。将其称为 BuckleScript 库会更准确。

  • Reason主要只是您使用的语法,但也经常被更广泛地用于指代它周围的生态系统,并且通常还暗示正在使用 BuckleScript。

  • OCaml是底层语言。理性的“语义”,如果你愿意的话。

  • BuckleScript是 OCaml 到 JavaScript 的编译器。它将一个被认为是模块的源文件编译成一个 JavaScript 模块,但也需要其他 OCaml 模块的类型信息作为输入。

现在,我怀疑您已经知道其中的大部分内容,但是您似乎不知道的是,这些实际上都没有进行任何依赖关系解析。工具链的这些下一部分是这样做的:

  • BuckleScript 构建系统bsb是根据您在 中指定的内容src以及您在bs-dependecies中列出的任何 BuckleScript 库查找本地项目中的所有模块的系统bsconfig.json。它将找出所有这些的依赖顺序,并以正确的顺序将它们提供给编译器,从而为每个 OCaml 模块生成一个 JavaScript 模块(以及其他一些包含类型信息等的人工制品)。但它不会解决任何 JavaScript 依赖项。

  • 最后,webpack或其他一些 JavaScript捆绑器是您可能用来将所有 JavaScript 模块组合到一个文件中的工具,因此需要解析任何 JavaScript 依赖项。这很可能是错误消息的来源。

Using[@bs.module "some-module"]将使 BuckleScript 编译器发出var ... = require('some-module')(或者import ... from 'some-module'如果使用 es6),但 BuckleScript 本身不会对它做更多的事情。如果它是普通的 CommonJS 模块(或您配置的任何其他模块格式),您传递给@bs.module的字符串与您将传递给的字符串相同。require

另请注意,导入不是在external定义的地方发出的,而是在使用它的地方发出的。您可以通过将其重新导出为普通定义,即在模块中解决或“接地”它。let addEngine = addEngine.

为了准确回答您的问题,我需要知道您使用的是哪个捆绑器,您在哪里配置了 BuckleScript 以输出其 JavaScript 工件,在哪里使用了外部组件,而不仅仅是定义,以及外部 JavaScript 模块的位置。但我希望所有这些基础知识将使您和未来的读者更容易自己识别和解决问题。如果您仍然有点不确定,请查看已编译的 JavaScript 工件并将它们视为普通的 JavaScript 模块。在这一点上,这就是他们的全部。


推荐阅读