Efficiently Bundle Matter.js with Vite
This guide explains how to optimize Matter.js in a Vite project by eliminating unused modules and reducing your final bundle size. By leveraging named ES module imports, pointing Vite to Matter.js's ESM source, and fine-tuning Rollup's dead-code elimination, you can ensure your production build includes only the physics features your application actually uses.
1. Avoid Default Namespace Imports
The default way many developers use Matter.js is by importing the entire root object:
// Avoid this: pulls the entire library into the bundle
import Matter from 'matter-js';
const engine = Matter.Engine.create();Importing the default Matter object binds every
submodule—including heavyweight modules like Matter.Render,
Matter.SVG, and Matter.DomRender—to a single
global object, preventing Rollup from tree-shaking them.
Instead, use named ES module imports to pull only the specific physics components your project requires:
// Recommended: allows Rollup to drop unreferenced modules
import { Engine, Composite, Bodies, Runner } from 'matter-js';
const engine = Engine.create();
const runner = Runner.create();2. Configure Vite to Resolve the ESM Build
By default, some versions of matter-js can resolve to
the pre-bundled Universal Module Definition (UMD) file via Node module
resolution. UMD builds cannot be tree-shaken effectively.
Update your vite.config.js to explicitly alias
matter-js to its modern ESM entry point:
import { defineConfig } from 'vite';
export default defineConfig({
resolve: {
alias: {
'matter-js': 'matter-js/build/matter.esm.js',
},
},
build: {
rollupOptions: {
treeshake: {
preset: 'smallest',
moduleSideEffects: false,
},
},
},
});resolve.alias: Forces Vite to use the pure ES module distribution instead of the monolithic UMD file.treeshake.preset: 'smallest': Instructs Rollup to aggressively remove functions and properties that do not produce runtime side effects.
3. Exclude the Built-in Canvas Renderer
The default Render module in Matter.js includes a
significant amount of canvas-drawing code, debug visualizers, and event
hooks. If you are rendering physics bodies using an external framework
(such as Pixi.js, Three.js, or a custom Canvas 2D loop), omit
Render completely.
import { Engine, Composite, Bodies, Body } from 'matter-js';
const engine = Engine.create();
const box = Bodies.rectangle(400, 200, 80, 80);
Composite.add(engine.world, box);
// Use a custom game loop instead of Matter.Render
function update() {
Engine.update(engine, 1000 / 60);
// Render using your custom loop or third-party renderer
drawBox(box.position.x, box.position.y, box.angle);
requestAnimationFrame(update);
}
requestAnimationFrame(update);4. Verify Bundle Output
To verify that unused modules (like SVG parsing or debugging tools)
are properly eliminated from the production build, use the
rollup-plugin-visualizer plugin to inspect your chunks:
npm install --save-dev rollup-plugin-visualizerAdd it to your vite.config.js:
import { defineConfig } from 'vite';
import { visualizer } from 'rollup-plugin-visualizer';
export default defineConfig({
plugins: [
visualizer({
open: true,
filename: 'bundle-analysis.html',
}),
],
});Run vite build. The generated HTML report will show you
the exact footprint of matter-js in your output, confirming
that only the imported submodules exist in your distribution files.