How Webpack and Vite Bundle glTF and GLB Files

Modern web applications often integrate 3D graphics using glTF (GL Transmission Format) and its binary counterpart, GLB. Automated build tools like Webpack and Vite process these assets differently depending on whether they are packaged as self-contained binaries or multi-file structures with external references. This article explains the underlying mechanisms Webpack and Vite use to detect, emit, and resolve dependencies inside 3D models, covering asset modules, internal path resolution, and best practices for asset delivery.

Understanding the Difference: GLB vs. glTF

To understand how bundlers handle 3D assets, it is necessary to distinguish between the two primary distribution formats:

  • GLB (Binary glTF): A self-contained file containing the scene hierarchy, mesh data, animations, and embedded image textures within a single binary payload. Bundlers treat GLB files identically to monolithic assets like PNGs, MP4s, or WOFF2 fonts.
  • glTF (JSON + External Assets): A structured JSON file referencing external .bin files (for vertex data, animations, and buffers) and image files (PNG, JPEG, WebP, or KTX2 for textures) via relative URIs. This format requires the build tool to understand and resolve a secondary dependency graph.

Bundling with Vite

Vite leverages native ES modules during development and Rollup for production builds.

1. Handling GLB Files

Vite treats GLB files as static assets. When you import a .glb file directly in JavaScript:

import modelUrl from './assets/robot.glb';

Vite returns the resolved public URL of the asset. During production builds, Rollup hashes the filename (e.g., robot-a1b2c3d4.glb), emits it to the dist/assets directory, and replaces the import statement with the final string path.

2. Handling glTF Files with External Dependencies

Standard multi-file glTF assets present a challenge for Vite's default static asset pipeline. When Vite parses an import modelUrl from './scene.gltf', it emits the .gltf file itself, but its internal JSON references to buffer.bin and texture.png are not automatically traversed or rewritten by standard Rollup plugins.

Developers address this in Vite in two ways:

  • The Public Directory: Placing multi-file glTF assets in the public/ folder bypasses the build pipeline entirely. The files are copied as-is to the root output directory, preserving relative path references between the JSON, binary, and image files at runtime.
  • Dedicated Plugins: Community plugins (such as vite-plugin-gltf) parse the glTF JSON manifest during the build, add referenced .bin and image files to the Rollup build graph, emit the processed assets with generated hashes, and rewrite the relative URIs inside the glTF JSON file.

Bundling with Webpack

Webpack 5 introduced Asset Modules, replacing legacy loaders such as file-loader and url-loader.

1. Handling GLB Files

Under Webpack 5, configuring GLB handling requires a basic rule inside webpack.config.js:

module.exports = {
  module: {
    rules: [
      {
        test: /\.glb$/,
        type: 'asset/resource',
        generator: {
          filename: 'models/[hash][ext][query]'
        }
      }
    ]
  }
};

Webpack emits the binary model directly to the output folder and provides the final resolved URL to loaders like Three.js's GLTFLoader.

2. Handling Multi-File glTF Dependencies

Webpack cannot natively parse the JSON structure of a .gltf file to discover referenced buffers and textures using standard asset/resource rules. Treating a .gltf file as a simple resource leaves its external dependencies behind, resulting in 404 errors at runtime when the 3D runtime attempts to fetch the relative URIs.

To solve this, Webpack relies on specialized loaders like gltf-webpack-loader:

  1. JSON Traversal: The loader parses the glTF JSON structure and identifies all URI references within the buffers and images arrays.
  2. Dependency Emission: It converts these references into module dependencies, passing them through Webpack's build pipeline so that images and .bin files are processed, hashed, and emitted.
  3. URI Rewriting: The loader updates the relative URIs inside the glTF JSON to match the newly generated, hashed output paths of the referenced assets.

Comparison of Bundling Strategies

Feature Vite (Default) Webpack 5 (Asset Modules) Specialized Loaders/Plugins
GLB Support Built-in via static import Built-in (asset/resource) Supported
glTF Path Rewriting No (requires public/ folder) No Yes (parses and rewrites JSON)
Cache Busting (Hashing) Automatic for GLB only Automatic for GLB only Supported for all linked assets
Pipeline Complexity Minimal Low Medium

For most production use cases, exporting assets as self-contained GLB files is the industry-standard approach. It completely circumvents the path-resolution problems inherent in multi-file glTF setups, allowing both Webpack and Vite to treat 3D models as single, immutable assets that benefit from standard hashing, caching, and CDN distribution.