@arkvertex/core
v0.0.3
Published
A graphics and game engine library
Downloads
178
Readme
Rayan Lib - Frontend Graphics Engine Library
A minimal, tree-shakeable TypeScript library for frontend graphics and 3D engine development. Optimized for modern bundlers with zero backend dependencies.
How the Library Works
Rayan Lib provides modular, tree-shakeable exports organized by functionality:
// Math utilities - Vector, Matrix, Quaternion operations
import { Vector3, Matrix4, Quaternion } from "rayan-lib";
// Graphics - Camera, Materials, Meshes, Rendering
import { Camera, Material, Mesh, Renderer, Light } from "rayan-lib";
// Physics - Rigid bodies, colliders, world simulation
import {
RigidBody,
BoxCollider,
SphereCollider,
PhysicsWorld,
} from "rayan-lib";Each class is independently importable and only included in your bundle if used.
Configuration & Why We Did It This Way
1. ESM-Only Format (index.js)
Configuration:
{
"type": "module",
"main": "./dist/index.js",
"exports": {
".": { "import": "./dist/index.js" }
}
}Why:
- ✅ Enables tree-shaking (removes unused code)
- ✅ Modern, future-proof standard
- ✅ Smaller bundle sizes for consumers
What happens without it:
- ❌ CommonJS/UMD outputs prevent dead code elimination
- ❌ Bundlers cannot identify unused exports
- ❌ All code shipped to end users, inflating bundle size
Example Impact:
// With ESM + tree-shaking (BEFORE)
import { Vector3 } from "rayan-lib";
// Bundle: ~1.5 KB (only Vector3)
// With CommonJS (BEFORE)
const lib = require("rayan-lib");
// Bundle: ~5+ KB (entire library)2. "sideEffects": false
Configuration:
{
"sideEffects": false
}Why:
- ✅ Tells bundlers this library has NO side effects on import
- ✅ Allows aggressive tree-shaking
- ✅ Safe to remove unused module exports
What happens without it:
- ❌ Bundlers assume importing code has side effects
- ❌ Bundlers keep unused modules just in case
- ❌ 30-50% larger final bundles
Example:
// src/math.ts
export class Vector3 {
/* ... */
}
export class Matrix4 {
/* ... */
}
// your-app.js
import { Vector3 } from "rayan-lib";
// WITH sideEffects: false → Matrix4 REMOVED from bundle ✅
// WITHOUT sideEffects: false → Matrix4 KEPT "just in case" ❌3. moduleResolution: "bundler"
Configuration:
{
"compilerOptions": {
"moduleResolution": "bundler"
}
}Why:
- ✅ Optimized for Vite, Webpack 5+, esbuild
- ✅ Resolves TypeScript files directly
- ✅ Better support for conditional exports
What happens without it:
- ❌
"node"resolver follows Node.js conventions - ❌ Slower resolution, misses optimizations
- ❌ Conditional exports not fully supported
4. target: "ES2020" (TypeScript & Vite)
Configuration:
{
"compilerOptions": { "target": "ES2020" },
"build": { "target": "ES2020" }
}Why:
- ✅ Modern JavaScript features available
- ✅ Smaller output (no transpilation overhead)
- ✅ Matches modern browser support
What happens without it:
- ❌ ES5 target adds polyfills and transpilation
- ❌ Code bloat (e.g.,
class→ verbosefunction) - ❌ Bundle size increases 20-30%
Example:
// ES2020 output (3 lines)
class Vector3 {
constructor(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
}
// ES5 output (10+ lines with helpers)
var Vector3 = function () {
/* complex transpilation */
};5. formats: ["es"] (Vite Build)
Configuration:
{
build: {
lib: {
formats: ["es"],
fileName: () => "index.js"
}
}
}Why:
- ✅ Single, optimized output
- ✅ Bundlers handle the heavy lifting
- ✅ No UMD/CommonJS bloat
What happens without it:
- ❌ Multiple outputs (ESM + UMD + CommonJS)
- ❌ Larger npm package (3 versions of same code)
- ❌ Users confused which to use
- ❌ npm registry bloat
6. vite-plugin-dts
Configuration:
{
plugins: [
dts({
include: ["src"],
rollupTypes: true,
}),
];
}Why:
- ✅ Auto-generates
.d.tsfrom TypeScript - ✅ Bundles all types into single file
- ✅ Consumers get full IntelliSense/autocomplete
What happens without it:
- ❌ Users have no type definitions
- ❌ No IDE autocomplete
- ❌ TypeScript projects can't use the library properly
- ❌ Community adoption drops
7. No DOM Types ("lib": ["ES2020"])
Configuration:
{
"compilerOptions": {
"lib": ["ES2020"]
}
}Why:
- ✅ Library works in Node.js and browsers
- ✅ Pure, environment-agnostic code
- ✅ Graphics module uses only data structures
What happens without it:
- ❌ Code compiled with DOM types
- ❌ Node.js imports fail (HTMLCanvasElement undefined)
- ❌ Library limited to browser-only
Bundle Size Comparison
| Config | Bundle Size | Tree-Shaking | Notes |
| -------------------------- | ------------ | ------------- | -------------------- |
| ✅ Our Config | 1.63 KB gzip | ✅ Aggressive | Optimized |
| CommonJS only | 5+ KB gzip | ❌ None | Cannot tree-shake |
| With "sideEffects": true | 3+ KB gzip | ⚠️ Partial | Keeps unused modules |
| UMD/IIFE format | 7+ KB gzip | ❌ None | Not modular |
Installation & Usage
npm install rayan-libimport { Vector3, Camera, Renderer, RigidBody } from "rayan-lib";
// Only used exports are bundled
const v = new Vector3(1, 2, 3);
const camera = new Camera();
const renderer = new Renderer("webgl", 1024, 768);
const body = new RigidBody();Understanding Tree-Shaking with Dependencies
Question: If Matrix4 uses Vector3, will tree-shaking remove Vector3 and cause runtime errors?
Answer: ✅ No runtime errors - Tree-shakers are smart about dependencies.
Example: Matrix4 uses Vector3
// math.ts
export class Vector3 {
/* ... */
}
export class Matrix4 {
translate(v: Vector3): this {
// ← Depends on Vector3
this.data[12] += v.x;
return this;
}
}Scenario 1: Using Matrix4 with translate()
import { Matrix4, Vector3 } from "rayan-lib";
const m = new Matrix4();
const v = new Vector3(1, 2, 3);
m.translate(v); // ← This USES the translate() methodWhat tree-shaker does:
- Sees
translate()method is used - Analyzes
translate()→ depends on Vector3 - Keeps both Matrix4 and Vector3 ✅
Bundle includes: Matrix4 + Vector3 + code using both
Scenario 2: Using Matrix4 without translate()
import { Matrix4 } from "rayan-lib";
const m = new Matrix4();
m.identity(); // ← Only identity() method usedWhat tree-shaker does:
- Sees
identity()method used - Analyzes
identity()→ NO Vector3 dependency - Sees
translate()andscale()methods not used - Removes unused methods + Vector3 ✅
Bundle includes: Only Matrix4.identity()
The Smart Part
Tree-shakers don't just look at imports—they analyze actual usage:
// ❌ Imported but not used → REMOVED
import { Vector3 } from "rayan-lib";
// ✅ Used in code → KEPT
import { Matrix4 } from "rayan-lib";
const m = new Matrix4();Dependency Analysis
Your Code
↓
Uses Matrix4.translate()
↓
Matrix4.translate() needs Vector3
↓
Vector3 included automatically ✅Summary:
- Tree-shaking is dependency-aware
- Unused dependencies are removed
- Used dependencies are automatically kept
- No runtime errors occur
- Zero manual dependency management needed
Architecture
src/
├── math.ts → Vector3, Matrix4, Quaternion
├── graphics.ts → Camera, Material, Mesh, Renderer, Light
├── physics.ts → RigidBody, Colliders, PhysicsWorld
└── index.ts → Central export pointAll modules export named exports for tree-shaking.
Key Takeaways
| Decision | Benefit | Alternative Cost |
| -------------------- | ------------------ | -------------------------------- |
| ESM only | Tree-shaking | +30-50% bundle size |
| sideEffects: false | Dead code removal | Bundler includes unused code |
| bundler resolution | Optimized | Slower, misses optimizations |
| ES2020 target | Modern, small | +20-30% with ES5 transpilation |
| Single format | Clean | Multiple output files, confusion |
| DTS generation | TypeScript support | No IDE support for consumers |
| No DOM types | Universal | Node.js incompatible |
Bottom Line: Every configuration choice is optimized for minimal bundle size while maintaining full TypeScript support and tree-shaking capability. Removing any setting increases overhead for end users.
