Global is not defined

I am trying to use the JS agent from the browser and I get this:

ferenceError: global is not defined
    at new Decoder (decoder.js:58:26)
    at new Uint8ArrayDecoder (cbor.ts:105:1)
    at decode3 (cbor.ts:121:19)
    at HttpAgent.status (index.ts:528:17)
    at async HttpAgent.fetchRootKey (index.ts:534:24)
(

This is just trying to do something simple like create an actor. It seems to me that the agent is expecting node polyfills. Why is this the case? It would be great if the agent did not assume a non-browser environment when in the browser, and if the polyfills were automatically included in the deployed npm package, instead of expecting the developer to provide these polyfills.

This goes back to a deeper issue I think which is that the agent seems far too dependent on assuming the user’s bundler (webpack), whereas other bundlers are used and in my case I am using Vite.

4 Likes

I can’t get rid of the global dependency at the moment, tragically. To fix your vite config, you can add this:

export default defineConfig({
  define: {
    global: "window",
  }
});

Here is a full agent-js vite config I haven’t publicized yet while I’m trying to make sure it scales properly

3 Likes

I’d like to evaluate a replacement for borc though. Right now I’m in the process of replacing tweetnacl in favor of @noble/ed25519, so I am open to recommendations

1 Like

My main recommendation would be to deploy the library with the polyfilled libraries in the bundle, thus it doesn’t become a problem to the end developer, and you can hopefully go on simplifying that over time instead of passing the burden onto the end developer.

in this case, I’d really rather not do the polyfill though. it adds bloat and everyone already has a TextDecoder and TextEncoder in their environment. It’s just unfortunate that the library is pointing to a named global object and looking for it there instead of having fallback strategies we could take advantage of

I personally polyfill global as following:

optimizeDeps: {
    esbuildOptions: {
      define: {
        global: "globalThis",
      },
    },
  },

Notably did this when I recently migrated II from webpack to vite: https://github.com/dfinity/internet-identity/blob/1a048f120e6344a7340b56d80124965e1cfd7b88/vite.config.ts#L64

I think my main point is that the dfinity tooling should just do this automatically if global/process do not exist.

1 Like

Agree. Another option would maybe be to provide a (vite) plugin that does the job out of the box, that way no need to repeat the configuration across projects but, just my two cents.

1 Like

Yes, though I’m trying to find a non-vite or any build tool-specific solution. Vite just seems awesome and I picked it up and ran into these issues.

1 Like

I think the simplest solution to consider is just setting global to window or globalThis automatically if the user does not have global defined globally.

1 Like

While agnosticism always has merit, Vite is a thriving community of developers, and it’s tooling (“a dfx vite plugin”) could very well provide an on ramp to many a developer (particularly if coupled with Azle perhaps?).

Anyways the rabbit hole on polyfilling global goes deep:
https://mathiasbynens.be/notes/globalthis

Though globalThis seems to be the current consensus winner.

Incidentally, here’s the final remark on one of (of the several) Vite git issues on this subject:

@ljharb the mainstream tooling authors have reached the consensus that Node is no longer special - with Deno and worker
environments becoming more common, it’s just one of the many JS runtimes that build tools may target. Its platform-specific APIs should not get special treatment in general-purpose build tools, especially when the user is targeting browsers. JS packages published on npm are also no longer by definition Node-specific - if a package is meant to be usable in the browser, then it is the package authors’ responsibility to ensure their code can run properly in the browser without special treatment.

You may disagree with that and that’s fine - but your opinion really doesn’t matter here, because the ecosystem moves forward as a result of the natural selection process of its users. If not supporting Node built-ins is a mistake, surely fewer users would use tools that don’t support them (including Vite and webpack 5), and those tools should die out in the long run. If users turn out to still opt for these tools, then it means to them the utility these tools provide are more important than the occasional minor inconvenience, and in turn they would request the package authors to properly ship universal packages (instead of relying on Node APIs as if it is available in all JS environments). That’s how we shed the collective technical debt and move the ecosystem forward, and it’s 100% an intentional decision in Vite’s design to push it towards that direction.

-Defining `global: 'globalThis'` variable will replace `global.css` as `"globalThis".css` on building · Issue #4796 · vitejs/vite · GitHub

1 Like
<script>
    globalThis.global = globalThis;
</script>

At the top of the head works well for me :ballot_box_with_check:

Note: It uses a proxy of the window object