🕹 A simple & lightweight ECS (Entity Component System) library for JavaScript and TypeScript.
Find a file
2026-01-13 00:43:51 +01:00
.github upd: Updated dependencies. 🔝 2026-01-05 17:01:28 +01:00
.husky init: Initialized project. 🚀 2025-04-20 12:34:27 +02:00
src imp: A single iterator for both entity & components on QueryView objects. 2026-01-13 00:43:51 +01:00
tests imp: A single iterator for both entity & components on QueryView objects. 2026-01-13 00:43:51 +01:00
.editorconfig init: Initialized project. 🚀 2025-04-20 12:34:27 +02:00
.gitignore fix: Problem with constructor.name & minified code for production. 2026-01-05 14:51:23 +01:00
.npmignore init: Initialized project. 🚀 2025-04-20 12:34:27 +02:00
CLAUDE.md imp: A single iterator for both entity & components on QueryView objects. 2026-01-13 00:43:51 +01:00
eslint.config.mjs wip: Implemented build for different modes... 2025-12-05 00:24:20 +01:00
index.js wip: Implemented build for different modes... 2025-12-05 00:24:20 +01:00
index.mjs wip: Implemented build for different modes... 2025-12-05 00:24:20 +01:00
LICENSE init: Initialized project. 🚀 2025-04-20 12:34:27 +02:00
package.json chore: Incremented version. 🔝 2026-01-10 20:37:07 +01:00
pnpm-lock.yaml chore: Incremented version. 🔝 2026-01-10 20:37:07 +01:00
pnpm-workspace.yaml imp: Now you can enable / disable systems. 2025-04-25 18:09:26 +02:00
README.md imp: A single iterator for both entity & components on QueryView objects. 2026-01-13 00:43:51 +01:00
tsconfig.json wip: Implementing built-conditional tree-shaking for checks & exceptions. 2025-12-04 18:24:09 +01:00
vite.config.ts wip: Implemented build for different modes... 2025-12-05 00:24:20 +01:00
vitest.config.ts init: Initialized project. 🚀 2025-04-20 12:34:27 +02:00

μECS 🕹

NPM Version Codecov NPM release GPR release NPM Downloads License

A simple & lightweight ECS (Entity Component System) library for JavaScript and TypeScript.


Overview

μECS (micro-ecs) is a headless library, completely agnostic to any graphics or rendering library.

Traditional ECS architectures excel in low-level contexts with direct memory control (C++, Rust, etc.).
JavaScript doesn't offer this level of control, so μECS takes a pragmatic approach: it brings only the ECS benefits that translate well to a high-level environment, leaving behind optimizations that would require direct memory management.

Design Philosophy

The library is built on three pillars:

  • DX-first: Developer Experience is prioritized over raw performance.
    The library doesn't use TypedArrays which would be faster but significantly hurt ergonomics.
    A pleasant API is more valuable than squeezing out every microsecond.
  • Familiarity: The API should feel natural to any JavaScript developer.
    This means using recognizable patterns: ES6 classes, getters/setters, pub/sub events, and typical OOP idioms common in the JS ecosystem.
  • Speed over Memory: When trade-offs are necessary, execution speed is preferred over memory consumption.
    Using extra memory is acceptable if it yields performance benefits at runtime.

Features

  • World — Central container managing Entities, Systems, Resources, and Services
  • Entity — Container for Components, can be enabled/disabled
  • Component — Data attached to Entities, with independent enable/disable
  • System — Logic operating on entities/components, with priority-based execution
  • Resource — Singleton data shared across the world
  • Service — A System that can be used as a Resource dependency
  • QueryManager — Efficient component queries with cached views
  • QueryView — Cached, auto-updating view of entities matching a query
  • Contexts — Dependency injection for Systems (WorldContext) and Components (EntityContext)
  • Events — Built-in pub/sub system via Publisher

Installation

# npm
npm install @byloth/micro-ecs @byloth/core

# pnpm
pnpm add @byloth/micro-ecs @byloth/core

# yarn
yarn add @byloth/micro-ecs @byloth/core

# bun
bun add @byloth/micro-ecs @byloth/core

Note: This library requires @byloth/core as a peer dependency.


Quick Start

import { World, Entity, Component, System } from "@byloth/micro-ecs";
import type { ReadonlyQueryView } from "@byloth/micro-ecs";

// Define Components
class Position extends Component {
  public x = 0;
  public y = 0;
}
class Velocity extends Component {
  public vx = 0;
  public vy = 0;
}

// Define a System
class MovementSystem extends System {
  private view?: ReadonlyQueryView<[Position, Velocity]>;

  public override onAttach(world: World): void {
    this.view = world.getComponentView(Position, Velocity);
  }
  public override update(deltaTime: number): void {

    for (const [position, velocity] of this.view!.components) {
      position.x += velocity.vx * deltaTime;
      position.y += velocity.vy * deltaTime;
    }
  }
}

// Create the World
const world = new World();

// Add Systems and Entities
world.addSystem(new MovementSystem());

const entity = new Entity();
entity.addComponent(new Position());
entity.addComponent(new Velocity());
world.addEntity(entity);

// Game loop
function gameLoop(deltaTime: number) {
  world.update(deltaTime);
}

Architecture

Core Classes

Component   — Data attached to Entities (standalone class)
Resource    — Singleton data, attachable to World
├── Entity  — Container for Components
└── System  — Logic with update(), priority, enable/disable

QueryManager

Efficiently queries entities by component types:

// Get first component of type
world.getFirstComponent(Position);

// Get first entity with all component types
world.getFirstComponents(Position, Velocity);

// Iterate all matching entities
world.findAllComponents(Position, Velocity);

// Get cached view that auto-updates
world.getComponentView(Position, Velocity);

Contexts

WorldContext — Provided to Systems for:

  • Event subscription (on, once, wait, off)
  • Event emission (emit)
  • Resource dependency management (useResource, releaseResource)

EntityContext — Provided to Components for:

  • Component dependency management (useComponent, releaseComponent)

Roadmap

🟠 Improvements

Optimizations and refinements that improve quality and performance.

  • Automatic View garbage collection

    Implement an automatic clean-up system for QueryManager that detects and removes Views no longer referenced or used, avoiding memory accumulation over time.


🟢 Future Considerations

Ideas and possible evolutions to evaluate based on needs.

  • Object pooling

    Implement a pooling system for Entity and Component to reduce Garbage Collector pressure in scenarios with high creation/destruction frequency (e.g., particle systems, projectiles).

    ⚠️ Evaluate carefully: could complicate the API and go against the project's "DX-first" philosophy.


License

Apache 2.0