Introduction
A flexible toolkit for data-oriented design in game development.
What is bitECS?
bitECS is a high-performance Entity Component System (ECS) library for JavaScript and TypeScript. It offers core ECS concepts without imposing strict rules onto your architecture:
- Entities are numerical IDs
- Component stores can be anything
- No formal concept of systems, only queries
What is ECS?
Entity Component System is an architectural pattern that favors composition over inheritance. It separates data (components) from behavior (systems) and uses entities as identifiers that link components together.
Entity
Component
System
Core Principles
JavaScript runs in a JIT-compiled environment, and performance characteristics vary across engines (V8, SpiderMonkey, JavaScriptCore). Data-oriented design helps, but only goes so far in JS. bitECS embraces this by leaving component storage agnostic—you choose the backing store that works best for your use case and target runtime.
- Structure of Arrays (SoA) - Store component data in arrays indexed by entity ID. Generally faster than objects and significantly more memory-efficient.
- Function pipelines - Implement systems as composable functions that can be reordered and profiled independently.
- Agnostic storage - Use TypedArrays, regular arrays, or custom stores. Optimize where profiling shows you need it.
- ZAII - Zero As Initial Initialization. Design around zero being the default state.
Choose the backing store that fits your needs:
- TypedArrays - Zero garbage collection. Required for SharedArrayBuffer multithreading.
- Regular arrays - Flexible, lower memory than objects, minimal GC pressure.
- Array of Structures (AoS) - Objects per entity. Familiar API, but more memory at scale.
Both SoA (Position.x[eid]) and AoS (Position[eid].x) work with bitECS—just matters which side of the brackets the dot is on. We encourage SoA for memory efficiency, but the choice is yours.
Example
Here's a complete example showing the core concepts:
1import { createWorld, addEntity, addComponent, query } from 'bitecs'23// Define components as objects with arrays4const Position = {5 x: [] as number[],6 y: [] as number[],7}89const Velocity = {10 x: [] as number[],11 y: [] as number[],12}1314// Create a world15const world = createWorld()1617// Add an entity to the world18const entity = addEntity(world)1920// Add components to entity21addComponent(world, entity, Position)22addComponent(world, entity, Velocity)2324// Set initial values25Position.x[entity] = 026Position.y[entity] = 027Velocity.x[entity] = 128Velocity.y[entity] = 12930// Define a system that moves entities31const moveSystem = (world) => {32 for (const eid of query(world, [Position, Velocity])) {33 Position.x[eid] += Velocity.x[eid]34 Position.y[eid] += Velocity.y[eid]35 }36}3738// Game loop39const loop = () => {40 moveSystem(world)41 requestAnimationFrame(loop)42}4344loop()What's New in 0.4
Version 0.4 is a complete TypeScript rewrite with significant new features: