mmntjs
Compatibility-first migration bridge away from moment.js

What To Understand

Main point

The default mmntjs entry is not trying to win the smallest-core contest.

What it does win

Locales and timezone data are separate, so apps do not pay for them unless they import them.

Lite entry

mmntjs/lite (55.2KB raw bundled, 14.8KB gzip bundled) exists for browser-sensitive paths that want method chaining without the full compat surface.

fns entry

mmntjs/fns offers standalone functions with a tiny tree-shaken footprint. A single format import is about 507 B gzip; parseISO + format + addDays is about 1.3KB gzip.

Timezone surprise

The packaged IANA timezone data is smaller than many readers expect once compressed and packed.

Entry Sizes

Compare each entry against the moment.js shape it replaces.

Entry Raw size Compare against Reading Why it matters
mmntjs 179.5 KB raw bundled full compat browser entry compatibility-heavy Full compat entry for migration. Not intended to be the smallest core.
mmntjs/lite 55.2 KB raw bundled browser-sensitive moment-style usage recommended default Method chaining with a much smaller surface than the default entry.
mmntjs/fns 1.0 KB raw / 507 B gzip for `format` small tree-shaken helper sets dramatically smaller for basic usage Standalone functions (`format`, `parseISO`, `addDays`, `diff`). Scales with imports.
dist/locale/ja.js 4.9 KB raw dist single locale add-on single locale stays separate A single locale remains a tiny pure-data module instead of pushing toward all-locales builds.
mmntjs-timezone 477.4 KB raw bundled named-zone browser entry large but separate Full IANA data. Dist output is 318.3 KB raw / 39.0 KB gzip; sub-entries exist for `/logic`, `/1970-2030`, and `/10-year-range`.

Why This Helps

  • Moment's common browser story often drifts toward larger all-locales or timezone-heavy builds.
  • mmntjs keeps the compatibility-heavy core separate from locale data and timezone data. Locale modules stay pure data by default, while locale-auto/* exists for one-line side-effect migration when needed.
  • That means the practical size question is usually: what does this app actually import, not what is the smallest theoretical core in isolation?

How To Read It

  • Use mmntjs/lite (55.2 KB raw bundled, 14.8 KB gzip bundled) as the default for most apps: moment-compatible API, method chaining.
  • Use mmntjs/fns when you prefer standalone functions. A single format import is about 507 B gzip, and small helper sets stay around 1-2 KB gzip.
  • Use mmntjs (179.5 KB raw bundled, 45.1 KB gzip bundled) for full moment.js compatibility during migration.
  • Read locale size separately from core size. A single locale module is cheap; an all-locales browser build is where moment tends to bloat.
  • Read timezone size separately from core size. Apps that do not need named IANA zones should not pay for timezone data at all.

Timezone Data

The IANA package is separate, and its compressed size is fairly modest.

Methodology

The interesting part is not only how the numbers were measured, but how the timezone package was made smaller in the first place.

Name dictionary encoding

Replace long zone names like America/New_York with short base-60 IDs, then materialize them at runtime.

More details

Permutation-group index codec

Compress DST transition index patterns using run forms such as pair-repeat and increment. This is the most 'modern math' part of the timezone size work.

More details

Delta frequency dictionary

Turn repeated timezone deltas into global dictionary IDs so frequent transition values collapse to short tokens.

More details