Cannot access "buffer.Buffer" in client code (Svelte with Userbase)

I'm writing an application using Svelte 3.44 and SvelteKit. I want to use Userbase () for user authentication and data storage.

I have a component Login.svelte in which I want to call Userbase API for signing up and logging in. The relevant code is:

<script lang="ts"> import userbase from 'userbase-js'; /* Irrelevant code here */
</script>

When I try to run this using vite dev, then instead of my Login component I see:

500
Module "buffer" has been externalized for browser compatibility. Cannot access "buffer.Buffer" in client code.
get@
node_modules/safe-buffer/index.js@
__require@
node_modules/randombytes/browser.js@
__require@
node_modules/diffie-hellman/lib/generatePrime.js@
__require@
node_modules/diffie-hellman/browser.js@
__require@
@

Browsing for solutions I found two and none worked:

  1. Using dynamic import with OnMount() seems to work, but I can't use the imported module anywhere else outside of OnMount() because of TypeScript type checking.

  2. Adding Userbase SDK from index.html and calling it with window.userbase didn't work, because I got ReferenceError: window is not defined. If I only use it inside OnMount(), then I'm back with problem number one.

To sum up: If anyone has overcome the Cannot access "buffer.Buffer" in client code problem, please tell me how you did that. Excuse me if this is a stupid question, I'm an embedded developer, this is one of my first encounters with Web Development.

3 Answers

I've had the exact same issue and I've been able to solve it!

  1. Install buffer package, as correctly suggested by @H.B.: $ npm i buffer
  2. Add this snippet to your index.html:
<script>
/** * this is a hack for error: global is not defined */
var global = global || window
</script>

Got this little gem from this GitHub comment

My component logic so far is:

<script> import { onMount } from 'svelte'; import userbase from 'userbase-js'; onMount(() => { userbase.init({ appId: '...' }) });
</script>

Versions:

 "@sveltejs/kit": "next" "svelte": "^3.44.0", "typescript": "^4.7.4", "vite": "^3.0.4"
1

I cannot reproduce this exact issue, maybe you are using a different version of Vite. You could try to prevent buffer from being externalized by adding it to ssr.noExternal.

I get a different error which also suggests that the module should be imported only in the browser.

Accessing something outside of onMount is only a typing or scoping issue. If you import it in a component you can declare a variable outside of onMount. It will be undefined until the import has completed:

<script lang="ts"> import { onMount } from 'svelte'; import type { Userbase } from 'userbase-js'; let userbase: Userbase | undefined; onMount(async () => { window.global = window; // If you get a "global is not defined error" userbase = await import('userbase-js').then(x => x.default); });
</script>

If you import the script elsewhere globally, you should be able to access window.userbase, the type declaration files of the module already define this :

// Expose as userbase when loaded in an IIFE environment
export as namespace userbase
2

This idea may help:Module "util" has been externalized for browser compatibility. Cannot access "util.promisify" in client codeSomething like this:

export default defineConfig({ resolve: { alias: { util: 'util/', }, },
})
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like