如何将bigInteger.min.js加载到浏览器中,以便data.bigint找到它?

发布于 2025-02-02 12:51:22 字数 2355 浏览 1 评论 0 原文

我有以下PURESCRIPT程序,该程序将 bigint 打印到日志:

module Main where

import Prelude
import Effect
import Effect.Console

import Data.Integral (fromIntegral)
import Data.BigInt

main :: Effect Unit
main = log $ show (fromIntegral 0x42 :: BigInt)

我想从浏览器中使用它。因此,我制作了以下html文件:

<!doctype html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>

<body>
  <script src="index.js" type="module"></script>
</body>
</html>

index.js 的内容是:

import * as Main from '../output/Main/index';

console.log("Before");
Main.main();
console.log("After");

这是因为失败的,因为 data.bigint 使用ffi使用javascript模块,称为 big-integer < /代码>:

uck offult typeError :无法解析模块指定器“ big-integer” 。 相对引用必须以“/” “ ./” ./“ ” ../ 。。

如何将 biginteger.min.js 加载到“ big-integer” 模块指定器?

到目前

我尝试加载 biginteger.min.js 通过在 index.js 中手动导入它:

import * as Main from '../output/Main/index';
import * as BigInteger from './BigInteger.min.js';

console.log("Before");
Main.main();
console.log("After");

但是这里的问题是我无法将其导入为 big-integer ,只有 biginteger ,因为前者在词法上无效。

我还尝试了一个不合格的导入:

import {bigInt} from './BigInteger.min.js';

但是这两种方法都无法使用(缺少“ big-integer” 模块的错误)。

我还疲倦的加载 biginteger.minjs 直接作为JS源文件:

<body>
  <script src="BigInteger.min.js"></script>
  <script src="index.js" type="module"></script>
</body>

但仍然存在同样的问题。

我还尝试在我的HTML文件中添加导入地图:

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <script type="importmap">
    {
        "imports": {
            "big-integer": "./BigInteger.min.js"
        }
    }
</script>
</head>

然后,这将失败:

uck syntaxerror : 请求的模块'Big-Integer'不提供名为'默认'的导出 (在 forefer.js :3:8)

I have the following PureScript program that prints a BigInt to the log:

module Main where

import Prelude
import Effect
import Effect.Console

import Data.Integral (fromIntegral)
import Data.BigInt

main :: Effect Unit
main = log $ show (fromIntegral 0x42 :: BigInt)

I would like to use it from the browser. So I made the following HTML file:

<!doctype html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>

<body>
  <script src="index.js" type="module"></script>
</body>
</html>

The contents of index.js is:

import * as Main from '../output/Main/index';

console.log("Before");
Main.main();
console.log("After");

This fails because Data.BigInt uses FFI to a Javascript module called big-integer:

Uncaught TypeError: Failed to resolve module specifier "big-integer".
Relative references must start with either "/", "./", or "../".

How do I load BigInteger.min.js into the "big-integer" module specifier?

What I've tried so far

I tried loading BigInteger.min.js by importing it manually in index.js:

import * as Main from '../output/Main/index';
import * as BigInteger from './BigInteger.min.js';

console.log("Before");
Main.main();
console.log("After");

But the problem here is that I can't import it as big-integer, only BigInteger, because the former is not lexically valid.

I also tried an unqualified import:

import {bigInt} from './BigInteger.min.js';

but that doesn't work either (same error about missing "big-integer" module).

I've also tired loading BigInteger.minjs as a JS source file directly:

<body>
  <script src="BigInteger.min.js"></script>
  <script src="index.js" type="module"></script>
</body>

But still, same problem.

I've also tried adding an import map to my HTML file:

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <script type="importmap">
    {
        "imports": {
            "big-integer": "./BigInteger.min.js"
        }
    }
</script>
</head>

This then fails with:

Uncaught SyntaxError:
The requested module 'big-integer' does not provide an export named 'default'
(at foreign.js:3:8)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ぇ气 2025-02-09 12:51:22

我不确定该 biginteger.min.js 文件来自哪里,但根据其名称以及您尝试使用的方式,我将假设它是一个包裹准备成为一个“通用模块” - 即一个可以加载节点,在UMD/AMD加载程序或浏览器中的模块。也许这是链接您从中得到它吗?

该软件包在浏览器中的工作方式是老式的:它创建一个名为 bigint 的全局变量,然后可以通过想要使用它的人访问该变量。要检查此信息,请尝试加载页面,打开开发工具 - &gt;控制台,然后键入 window.bigint 。定义吗?

问题是,大多数现代工具,包括纯粹的文字,都不再使用这种接口。取而代之的是,每个人都搬到了ES模块,那里没有任何类型的全局变量,每个模块都可以按名称导入其他模块。您尝试通过 import {bigint}从./ biginteger.min.js'进行 import {bigint},并且失败是因为 big> biginteger.min.js 不是ES模块。

至于如何解决这个问题 - 您有选择。


选项0 :( false start)正常在这种情况下安装节点模块

,将使用 npm安装,然后从那里引用它:

<script type="importmap">
  {
    "imports": {
      "big-integer": "../node_modules/big-integer/index.js"
    }
  }
</script>

但是,问题使用该特定软件包,即使安装在节点中,也不是ES模块。该软件包从一开始就将其写成非ES模块,因此永远无法将其导入为ES。

在节点中,这可以正常工作,因为节点可以与ES和CommonJS模块合并在一起,因此它只会加载 big-integer 软件包包装旧样式并使用它。当然,它的效率降低了,但可以工作。

但不在浏览器中。现代浏览器,当面对导入... 构造时,期望目标是ES模块,如果不是ES模块 - 就是这样。


选项1:a存根

该软件包可作为浏览器中的全局变量可用,唯一的问题是ES导入系统无法访问它。因此,我们可以帮助它。创建一个新的模块,例如 big-int-stub.js ,然后从中导出全局变量:

// big-int-stub.js
export default window.bigInt

然后使用 importmap 重复 big-integer 对此存根:

<script type="importmap">
  {
    "imports": {
      "big-integer": "./big-int-stub.js"
    }
  }
</script>
<script src="./BigInteger.min.js"></script>

<script type="module">
  import bigInt from "big-integer"
  console.log(bigInt)
</script>

一个问题是,如果您想能够导入默认导出以外的其他内容,例如从“ big-integer” 中导入{min,max},您' d也必须在导出中列举其中每个人:

export default window.bigInt
export const min = window.bigInt.min
export const max = window.bigInt.max
...

另一个问题 - 不是包裹本身,而是更一般的是 - 是在要求浏览器加载许多小文件,并在页面上加载很多小文件:第一个 index 。这对于玩具项目和练习都是可以的,但是对于任何实际应用,这比没有更可能是不可接受的。


选项2:捆绑

而不是直接在页面中包含 index.js ,首先捆绑它,然后包含捆绑包。

“捆绑”的想法是获取您的“根”模块,然后将其导入的所有内容以及这些导入等等的所有内容,依此类推,等等 - 然后将其全部组合到一个没有的大JS文件中,该文件没有根本导入任何内容,但完全独立,具有它需要运行的所有代码。这样的组合文件称为“ 捆绑包”。以及执行此组合过程的程序-A“ bundler ”。

这种方法的优点很多:这不仅意味着浏览器只需要加载一个文件而不是数十个文件,而且一个好的捆绑器(尤其是ES模块)将能够包括不包括 all 代码,但只有这些函数和变量实际上可能被引用。如果您想听起来很酷,这称为“消除代码消除”或“摇晃”。

但是,对于您特定情况的关键优势在于,捆绑器也识别CommonJS模块,这意味着它可以将 big-integer 软件包纳入捆绑包,即使它不是ES模块。

首先,安装一个捆绑器。那里有许多不同的地方 - 历史上最受欢迎的是WebPack,但是我个人(以及PureScript社区),例如 Esbuild 最佳。它的数量级更快,其API实际上是理智的。要安装它,请使用 npm

npm install esbuild

之后,只需将其提供给您的 index.js 并要求它捆绑。指定输出文件名通常也是一个好主意:

esbuild --bundle ./index.js --outfile=./bundle.js

这将产生 bundle.js 文件,您可以在页面中包含:

<script src="bundle.js" type="module"></script>

I'm not sure where that BigInteger.min.js file came from, but based on its name and the way you're trying to use it, I'm going to assume that it's a package specially prepared to be a "universal module" - i.e. a module that can load in either Node, or under UMD/AMD loader, or in the browser. Perhaps this is the link you got it from?

The way this package works in the browser is old-school: it creates a global variable named bigInt, which can be then accessed by whoever wants to use it. To check this, try loading your page, opening Dev Tools -> Console, and typing window.bigInt. Is it defined?

The problem is, most modern tools, including PureScript, don't work with that kind of interface anymore. Instead, everybody moved to ES modules, where there are no global variables of any sort, and every module can import other modules by name. Which is kind of what you tried to do by import {bigInt} from './BigInteger.min.js', and it failed because BigInteger.min.js is not an ES module.

As to how to solve this - you have options.


Option 0: (false start) install the Node module

Normally in a situation like this, one would install the module in Node with npm install big-integer, and then reference it from there:

<script type="importmap">
  {
    "imports": {
      "big-integer": "../node_modules/big-integer/index.js"
    }
  }
</script>

However, the problem with that particular package is that, even when installed in Node, it's not an ES module. The package is written as a non-ES module from the start, so it can never be imported as ES.

In Node this would work fine, because Node can work with both ES and CommonJS modules combined, so it would just load the big-integer package old-style and run with it. Sure, it's a bit less efficient, but it works.

But not in the browser. Modern browsers, when faced with an import ... from ... construct, expect the target to be an ES module, and if it's not - that's that.


Option 1: a stub

The package is available as a global variable in your browser, the only problem is that the ES import system can't access it like that. So we can help it out a bit. Create a new module, say big-int-stub.js, and export the global variable from it:

// big-int-stub.js
export default window.bigInt

Then use importmap to remap big-integer to that stub:

<script type="importmap">
  {
    "imports": {
      "big-integer": "./big-int-stub.js"
    }
  }
</script>
<script src="./BigInteger.min.js"></script>

<script type="module">
  import bigInt from "big-integer"
  console.log(bigInt)
</script>

One problem with this is that, if you want to be able to import stuff other than the default export, e.g. import { min, max } from "big-integer", you'd have to enumerate every one of them in the export too:

export default window.bigInt
export const min = window.bigInt.min
export const max = window.bigInt.max
...

Another problem - not with the package itself, but more generally - is that you're asking the browser to load a lot of small files with your page: first index.js, then from there - output/Main/index.js, then everything it imports, then everything those imports import, and so on. This is ok for toy projects and exercises, but for any real application this is more likely to be unacceptable than not.


Option 2: bundling

Instead of including index.js directly in your page, first bundle it, then include the bundle.

The idea of "bundling" is to take your "root" module, then take everything it imports, and everything those imports import, and so on, and so on, - and then combine it all in one big JS file that doesn't import anything at all, but is completely self-contained, has all the code that it needs to run. Such combined file is called a "bundle". And a program that performs this combining process - a "bundler".

The advantages of this approach are numerous: not only does this mean that the browser only needs to load one file instead of dozens, but a good bundler (and especially with ES modules) will be able to include not all the code, but only those functions and variables that may actually be referenced. This is called "dead code elimination", or "tree shaking" if you want to sound cool ????.

But the key advantage for your particular situation is that a bundler also recognizes CommonJS modules, which means it can incorporate the big-integer package into the bundle, even though it's not an ES module.

First, install yourself a bundler. There are many different ones out there - the most historically popular is WebPack, but I personally (as well as the PureScript community) like esbuild best. It's orders of magnitude faster and its API is actually sane. To install it, use npm:

npm install esbuild

After that, just give it your index.js and ask it to bundle. It's also usually a good idea to specify the output file name:

esbuild --bundle ./index.js --outfile=./bundle.js

This will produce the bundle.js file, which you can include in the page:

<script src="bundle.js" type="module"></script>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文