Mesh LogoMesh

How to Fix Node.js Buffer and Polyfill Errors in Browser Projects

Fix 'Buffer is not defined' and Node.js polyfill errors in React, Vue, Svelte, and Angular when using the Mesh Cardano SDK for dApp development.

When building Cardano dApps for the browser using the Mesh TypeScript blockchain SDK, you may encounter errors like Buffer is not defined or Module not found: Can't resolve 'buffer'. These occur because the Mesh Cardano SDK uses Node.js APIs that aren't 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 Node.js modules:

  • Buffer — Binary data handling
  • TextEncoder / TextDecoder — String encoding
  • crypto — Cryptographic operations
  • process — Environment variables
  • Built-in modules (fs, path, stream)

Modern bundlers (Webpack 5, Vite, Next.js) don't automatically polyfill these. This guide shows you how to fix these errors for each framework in your JavaScript Web3 projects.

What Are Polyfills and Why Do You Need Them?

Polyfills are packages that implement Node.js functionality for browsers in Cardano dApp development. Fallback configuration tells 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

How Do You Fix This in Webpack?

Webpack 5 removed automatic Node.js polyfills. You have two options:

Approach A: Use NodePolyfillPlugin

Install the plugin:

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

Add to webpack.config.js:

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

module.exports = {
  // ...your existing config
  plugins: [
    new NodePolyfillPlugin(),
    // ...other plugins
  ],
};

This plugin injects common polyfills.

Approach B: Use resolve.fallback

For granular control, configure fallbacks manually:

Install polyfills:

npm install buffer process stream-browserify --save

Edit webpack.config.js:

module.exports = {
  // ...
  resolve: {
    fallback: {
      buffer: require.resolve('buffer/'),  // or 'buffer'
      process: require.resolve('process/browser'),
      stream: require.resolve('stream-browserify'),
      // ...add more if needed
    },
  },
};

Import polyfills if needed:

import { Buffer } from 'buffer';
global.Buffer = global.Buffer || Buffer;

How Do You Fix This in Vite?

Vite uses Rollup, which doesn't include Node polyfills by default.

Install the plugin:

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

Add to vite.config.js:

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

export default defineConfig({
  plugins: [
    vue(),
    // any other plugins
  ],
  build: {
    rollupOptions: {
      plugins: [
        rollupNodePolyFill()
      ],
    },
  },
  resolve: {
    alias: {
      // Optionally, if you want the polyfill for `buffer` and `process` as top-level
      buffer: 'rollup-plugin-polyfill-node/polyfills/buffer-es6',
      process: 'rollup-plugin-polyfill-node/polyfills/process-es6',
      // Add more if needed
    },
  },
})

Use the polyfilled global if necessary:

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

How Do You Fix This in Next.js?

Next.js uses Webpack internally. Add the polyfill plugin to your Next.js config:

// next.config.js
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.plugins.push(new NodePolyfillPlugin())
    }
    return config
  },
}

The polyfills only apply to the client-side bundle (!isServer check).

How Do You Fix This in Create React App?

Create React App v5 uses Webpack 5 but doesn't expose the config directly. Use craco to override it.

First install the dependencies:

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()
      ],
    },
    configure: (webpackConfig) => {
      // Optionally, if you want to set fallback manually:
      webpackConfig.resolve.fallback = {
        ...webpackConfig.resolve.fallback,
        buffer: require.resolve('buffer'),
        process: require.resolve('process/browser'),
      }
      return webpackConfig;
    }
  },
};

How Do You Fix This in Angular?

Angular CLI 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

In angular.json:

{
  "projects": {
    "my-app": {
      "architect": {
        "build": {
          "builder": "ngx-build-plus:browser",
          "options": {
            // ...
          },
          "configurations": {
            "production": {
              // ...
            }
          }
        },
        "serve": {
          "builder": "ngx-build-plus:dev-server",
          "options": {
            // ...
          }
        }
      }
    }
  }
}

Create or update webpack.config.js:

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

module.exports = {
  plugins: [
    new NodePolyfillPlugin(),
  ],
  resolve: {
    fallback: {
      buffer: require.resolve('buffer'),
      process: require.resolve('process/browser'),
      // ...
    },
  },
};

Build with the extra config:

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

How Do You Fix This in Svelte/SvelteKit?

SvelteKit uses Vite, so follow the Vite instructions above. For plain Svelte with Rollup:

// rollup.config.js
import nodePolyfills from 'rollup-plugin-polyfill-node'

export default {
  plugins: [
    nodePolyfills(),
    // ...
  ],
  // ...
}

On this page