Mesh LogoMesh

Fix Node.js Polyfill Errors in Browser Projects

Resolve 'Buffer is not defined' and Node.js polyfill errors in React, Vue, Svelte, and Angular with Mesh SDK.

Overview

When building Cardano dApps for the browser, you may encounter errors like Buffer is not defined. This happens because Mesh SDK uses Node.js APIs that are not available in browsers by default.

Common error messages

Uncaught ReferenceError: Buffer is not defined
Module not found: Can't resolve 'buffer'
ReferenceError: TextEncoder is not defined

Affected modules

ModulePurpose
BufferBinary data handling
TextEncoder / TextDecoderString encoding
cryptoCryptographic operations
processEnvironment variables
streamData streaming

Modern bundlers (Webpack 5, Vite) do not automatically polyfill these. This guide shows you how to fix these errors for each framework.

Time to complete

15 minutes

What Are Polyfills?

Polyfills are packages that implement Node.js functionality for browsers. You configure your bundler to use these browser-compatible versions instead of Node.js modules.

Install the common polyfills:

npm install buffer process stream-browserify crypto-browserify --save

Framework-Specific Solutions

Next.js

Next.js uses Webpack internally. Add the polyfill plugin:

npm install node-polyfill-webpack-plugin --save-dev

Update next.config.js:

const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config, { isServer }) => {
    // Only add polyfills for client-side
    if (!isServer) {
      config.plugins.push(new NodePolyfillPlugin());
    }
    return config;
  },
};

module.exports = nextConfig;

What to expect: The build completes without polyfill errors.

Vite (React, Vue, Svelte)

Vite uses Rollup. Install the polyfill plugin:

npm install rollup-plugin-polyfill-node --save-dev

Update vite.config.ts:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react"; // or vue, svelte
import rollupNodePolyFill from "rollup-plugin-polyfill-node";

export default defineConfig({
  plugins: [react()],
  build: {
    rollupOptions: {
      plugins: [rollupNodePolyFill()],
    },
  },
  resolve: {
    alias: {
      buffer: "rollup-plugin-polyfill-node/polyfills/buffer-es6",
      process: "rollup-plugin-polyfill-node/polyfills/process-es6",
    },
  },
});

If you still see errors, add this to your entry file:

import { Buffer } from "buffer";
globalThis.Buffer = globalThis.Buffer || Buffer;

What to expect: The dev server and production build work correctly.

Webpack 5

Webpack 5 removed automatic Node.js polyfills. Choose one approach:

Option 1: Use NodePolyfillPlugin (recommended)

npm install node-polyfill-webpack-plugin --save-dev

Update webpack.config.js:

const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");

module.exports = {
  plugins: [
    new NodePolyfillPlugin(),
  ],
};

Option 2: Manual resolve.fallback

npm install buffer process stream-browserify --save

Update webpack.config.js:

module.exports = {
  resolve: {
    fallback: {
      buffer: require.resolve("buffer/"),
      process: require.resolve("process/browser"),
      stream: require.resolve("stream-browserify"),
    },
  },
};

What to expect: Webpack builds without module resolution errors.

Create React App (CRA)

CRA uses Webpack 5 but does not expose the config. Use CRACO to override:

npm install @craco/craco node-polyfill-webpack-plugin --save-dev

Update package.json scripts:

{
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test"
  }
}

Create craco.config.js:

const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");

module.exports = {
  webpack: {
    plugins: {
      add: [new NodePolyfillPlugin()],
    },
  },
};

What to expect: CRA builds with polyfills applied.

Angular

Angular uses Webpack internally. Use ngx-build-plus to extend the config:

npm install ngx-build-plus node-polyfill-webpack-plugin buffer process stream-browserify --save-dev

Update angular.json:

{
  "projects": {
    "my-app": {
      "architect": {
        "build": {
          "builder": "ngx-build-plus:browser"
        },
        "serve": {
          "builder": "ngx-build-plus:dev-server"
        }
      }
    }
  }
}

Create webpack.config.js:

const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");

module.exports = {
  plugins: [new NodePolyfillPlugin()],
};

Build with the extra config:

ng build --extra-webpack-config webpack.config.js

What to expect: Angular builds with Node.js polyfills.

SvelteKit

SvelteKit uses Vite. Follow the Vite instructions above, but update svelte.config.js:

import adapter from "@sveltejs/adapter-auto";
import { vitePreprocess } from "@sveltejs/kit/vite";

/** @type {import('@sveltejs/kit').Config} */
const config = {
  preprocess: vitePreprocess(),
  kit: {
    adapter: adapter(),
  },
};

export default config;

And vite.config.ts:

import { sveltekit } from "@sveltejs/kit/vite";
import { defineConfig } from "vite";
import rollupNodePolyFill from "rollup-plugin-polyfill-node";

export default defineConfig({
  plugins: [sveltekit()],
  build: {
    rollupOptions: {
      plugins: [rollupNodePolyFill()],
    },
  },
});

What to expect: SvelteKit handles Node.js modules correctly.

Complete Example: Next.js

Here is a complete Next.js setup:

package.json:

{
  "dependencies": {
    "@meshsdk/core": "^1.0.0",
    "@meshsdk/react": "^1.0.0",
    "next": "14.0.0",
    "react": "18.2.0"
  },
  "devDependencies": {
    "node-polyfill-webpack-plugin": "^3.0.0"
  }
}

next.config.js:

const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.plugins.push(new NodePolyfillPlugin());
    }
    return config;
  },
};

module.exports = nextConfig;

Next Steps

Troubleshooting

Error persists after configuration

Cause: Bundler cache contains old build artifacts.

Solution: Clear the cache and rebuild:

# Next.js
rm -rf .next node_modules/.cache
npm run build

# Vite
rm -rf node_modules/.vite
npm run build

Multiple Buffer definitions

Cause: Different packages include conflicting Buffer implementations.

Solution: Ensure only one Buffer polyfill is used:

// Add to entry file
import { Buffer } from "buffer";
if (typeof window !== "undefined") {
  window.Buffer = window.Buffer || Buffer;
}

Runtime errors despite successful build

Cause: Polyfills are configured for build but not dev server.

Solution: Ensure polyfill configuration applies to both build and dev. For Vite, add to optimizeDeps:

export default defineConfig({
  optimizeDeps: {
    include: ["buffer", "process"],
  },
});

Cannot resolve 'fs' or 'path'

Cause: Server-only modules are imported in client code.

Solution: These modules cannot be polyfilled. Use dynamic imports or conditional loading:

// Mark as client-only in Next.js
"use client";

// Or use dynamic import
const MeshComponent = dynamic(() => import("./MeshComponent"), {
  ssr: false,
});

On this page