Skip to content

Reduce bundle size: tree-shakeable relations & slimmer normalization #2051

Description

@CodeDredd

Analysis (v2, dist/index.mjs = 48.4 kB min / ~16 kB brotli with all exports, ~11.7 kB brotli in a real app bundle)

Measured with an esbuild metafile over src/index.ts (externals: pinia, vue, uuid, nanoid):

Contributor minified
query/Query.ts 12.2 kB
relation attributes (all 11) 10.6 kB — morphs alone 4.9 kB, belongsToMany/hasManyThrough/hasManyBy 2.9 kB
model/Model.ts 9.8 kB
repository/Repository.ts 3.0 kB
@pinia-orm/normalizr + Schema 3.9 kB
support/Utils 2.4 kB

External packages are NOT the problem — the only bundled dependency is our own normalizr fork (~1 kB brotli). Everything else is core code.

Verified dead ends:

  • sideEffects: false: zero effect (48 381 → 48 381 bytes) — the dist is flat-bundled and every class is reachable from Model/Query, so per-module shaking has nothing to drop.
  • Making normalizr external: only moves bytes, users install & load it anyway.

Why nothing shakes today

Model exposes every relation as a static method (this.hasMany(...)), so all 11 relation classes are statically reachable from any app that touches Model — bundlers cannot drop method bodies. Same for Query's instanceof MorphTo/BelongsToMany handling.

Proposal

  1. Tree-shakeable relation factories (target: 3.0, or additive in 2.x with the static methods deprecated):
    import { hasMany, morphMany } from 'pinia-orm'
    static fields () { return { posts: hasMany(() => Post, 'userId') } }
    Each factory imports only its relation class. Apps without morph relations save ~4.9 kB min (~1.5 kB brotli), without the exotic many-relations another ~2.9 kB min. Query's relation handling needs to dispatch via the relation instances instead of instanceof imports.
  2. Purpose-built normalization replacing the generic normalizr fork (~3.9 kB min potential, high effort/risk — separate evaluation).
  3. Keep measuring: the esbuild-metafile analysis should become a repeatable script so regressions show up in PRs.

Not a 2.0.0 blocker — the release is API-frozen; this is the follow-up plan with real numbers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions