Search code examples
typescriptsveltesveltekitsvelte-3

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 (https://userbase.com/) 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@http://localhost:5173/node_modules/.vite/deps/userbase-js.js?v=b25ad0c3:151:17
node_modules/safe-buffer/index.js@http://localhost:5173/node_modules/.vite/deps/userbase-js.js?v=b25ad0c3:162:19
__require@http://localhost:5173/node_modules/.vite/deps/chunk-TWLJ45QX.js?v=b25ad0c3:8:50
node_modules/randombytes/browser.js@http://localhost:5173/node_modules/.vite/deps/userbase-js.js?v=b25ad0c3:225:19
__require@http://localhost:5173/node_modules/.vite/deps/chunk-TWLJ45QX.js?v=b25ad0c3:8:50
node_modules/diffie-hellman/lib/generatePrime.js@http://localhost:5173/node_modules/.vite/deps/userbase-js.js?v=b25ad0c3:3272:23
__require@http://localhost:5173/node_modules/.vite/deps/chunk-TWLJ45QX.js?v=b25ad0c3:8:50
node_modules/diffie-hellman/browser.js@http://localhost:5173/node_modules/.vite/deps/userbase-js.js?v=b25ad0c3:3554:25
__require@http://localhost:5173/node_modules/.vite/deps/chunk-TWLJ45QX.js?v=b25ad0c3:8:50
@http://localhost:5173/node_modules/.vite/deps/userbase-js.js?v=b25ad0c3:6166:37

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.


Solution

  • 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"