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
.binfiles (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.binand 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:
- JSON Traversal: The loader parses the glTF JSON
structure and identifies all URI references within the
buffersandimagesarrays. - Dependency Emission: It converts these references
into module dependencies, passing them through Webpack's build pipeline
so that images and
.binfiles are processed, hashed, and emitted. - 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.