Skip to content

Add "sideEffects": false to enable tree-shaking #158

@arzafran

Description

@arzafran

Context

I maintain @darkroomengineering/fitbox, a text-fitting library built on pretext. We import only four symbols from the main entry:

import {
  prepareWithSegments,
  measureNaturalWidth,
  measureLineStats,
  layoutWithLines,
} from '@chenglou/pretext';

Observation

package.json doesn't declare "sideEffects": false, so downstream bundlers (Vite/webpack/rollup) conservatively ship the full transitive closure of pretext's internal modules:

File Size (raw)
analysis.js 37 KB
line-break.js 33 KB
generated/bidi-data.js 23 KB
layout.js 22 KB
measurement.js 8 KB
bidi.js 6 KB
Total ~129 KB raw

Every downstream consumer ships all 129 KB, even when they exercise only a fraction of the exported surface.

Ask

{ "sideEffects": false }

A scan of dist/*.js shows only top-level const/let initialization (regexes, Sets, let sharedWordSegmenter = null). All pure expressions, safe to mark side-effect-free. With the flag, bundlers can drop unused exports based on what consumers actually import (e.g., the seven layout.d.ts exports fitbox doesn't use, plus unused helpers in analysis.js/line-break.js).

Realistic impact: 20–40% bundle reduction for consumers using a subset of the API, which is most of them.

Secondary (lower priority, separate issue if interested)

generated/bidi-data.js is 23 KB of Unicode data needed only for RTL text. If bidi.js could lazy-load it (dynamic import() gated on a quick RTL scan), latin-only sites would drop 23 KB automatically. Not worth tackling until the sideEffects change is measured.

Willing to PR

Happy to open a one-line PR for the sideEffects change, plus a small bundle-size regression test if that's welcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions