Bundling GPU.js with Webpack and Vite

This article provides a direct guide on how to properly bundle gpu.js with modern build tools such as Webpack 5 and Vite. It addresses the common build-time pitfalls caused by the library's hybrid Node.js and browser codebase, outlines the recommended import strategies, and provides concrete configuration snippets to ensure seamless GPU acceleration in modern JavaScript applications.

The Core Bundling Challenge

gpu.js is designed to run in both Node.js (via headless-gl) and the browser (via WebGL). Because the package’s main entry point references native Node dependencies like gl, modern bundlers that target the web will often throw resolution errors, such as failing to resolve fs, path, or native binary modules.

To resolve this, bundlers must be configured either to consume the pre-built browser distribution or to ignore Node-specific dependencies during the build process.

Method 1: Importing the Browser Build Directly (Universal)

The simplest and most reliable method across all modern bundlers is to bypass the hybrid root entry point and import the browser-specific bundle directly from node_modules:

import { GPU } from 'gpu.js/dist/gpu-browser.js';

const gpu = new GPU();

This ensures that only client-side WebGL code is evaluated, completely avoiding server-side bindings and the need for complex bundler configurations.

Method 2: Configuring Vite

If you prefer standard package imports (import { GPU } from 'gpu.js'), you can configure Vite to alias the import directly to the browser build. Update your vite.config.js:

import { defineConfig } from 'vite';
import path from 'path';

export default defineConfig({
  resolve: {
    alias: {
      'gpu.js': path.resolve(__dirname, 'node_modules/gpu.js/dist/gpu-browser.js'),
    },
  },
  optimizeDeps: {
    include: ['gpu.js'],
  },
});

Alternatively, if you run into common dependency optimization warnings, exclude native packages in your configuration:

export default defineConfig({
  build: {
    rollupOptions: {
      external: ['gl'],
    },
  },
});

Method 3: Configuring Webpack 5

Webpack 5 removed automatic polyfills for Node.js core modules. When resolving the standard gpu.js package, Webpack must be instructed to ignore Node dependencies such as gl.

Add the following fallback and alias settings to your webpack.config.js:

const path = require('path');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  resolve: {
    alias: {
      'gpu.js': path.resolve(__dirname, 'node_modules/gpu.js/dist/gpu-browser.js'),
    },
    fallback: {
      gl: false,
      fs: false,
      path: false,
    },
  },
};

Setting gl: false prevents Webpack from attempting to compile or bundle native OpenGL bindings required only in Node.js environments.

Verification

After applying these configurations, verify that the instance initializes correctly in your client runtime:

import { GPU } from 'gpu.js';

const gpu = new GPU();
const kernel = gpu.createKernel(function () {
  return this.thread.x;
}).setOutput([5]);

console.log(kernel()); // Output: Float32Array([0, 1, 2, 3, 4])

If the array outputs properly without WebGL context warnings in the browser console, the bundler has successfully packaged the browser-ready runtime.