You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make the published bundle tree-shakeable additively: add named per-module
exports and "sideEffects": false, while keeping the default namespace export
exactly as it is today.
No breaking change, no migration guide, no 2.0.0.
Why
Tree-shaking does not currently work at all, for a structural reason:
package.json exposes only "." in exports and declares no "sideEffects".
src/index.ts default-exports the namespace object that src/jsfeatNext.ts
builds by importing and instantiating every module.
A bundler cannot drop anything, because the namespace object holds a live
reference to every singleton. A consumer calling only imgproc.grayscale()
still ships ORB, YAPE, optical flow, the motion estimator and the 18 KB src/orb/bit_pattern_31.ts table — the whole 57 KB UMD / 86 KB ESM bundle,
all or nothing.
This has been true since the 0.9.0 restructure and has simply not been costly
enough to notice. The TEBLID tables change that: they are the largest single
addition the library has taken on, and they land on every consumer regardless of
use.
Proposed change
Additive, in three parts:
Export each module by name from src/index.ts, sourced directly from its
module file rather than from the aggregator, so importing { imgproc }
does not pull the aggregator's evaluation in with it.
Add "sideEffects": false to package.json, so bundlers may drop unused
module evaluations.
Keep export default jsfeatNext unchanged.
Consumers importing the default namespace are unaffected and see the same
bundle. Consumers who care about size switch to named imports and get only what
they use. The jsfeatNext.<module> convention, and everything #96 assumes about
it, stays intact.
Subpath exports (@webarkit/jsfeat-next/teblid) would solve it for the new
modules only, diverge from the single-namespace convention, and penalise CDN
users who rely on one script tag.
Acceptance criteria
import { imgproc } from "@webarkit/jsfeat-next" works and type-checks.
A fixture app importing only { imgproc } produces a measurably smaller
bundle than one importing the default — with the before/after numbers
recorded in this issue.
import jsfeatNext from "@webarkit/jsfeat-next" behaves identically to
today; the API-shape test is unchanged and green.
The UMD build still exposes the full namespace for CDN consumers.
"sideEffects": false is correct — verified by checking that no module
relies on import-time side effects beyond registering itself on the
namespace.
Out of scope
Removing or deprecating the default namespace export.
Summary
Make the published bundle tree-shakeable additively: add named per-module
exports and
"sideEffects": false, while keeping the default namespace exportexactly as it is today.
No breaking change, no migration guide, no 2.0.0.
Why
Tree-shaking does not currently work at all, for a structural reason:
package.jsonexposes only"."inexportsand declares no"sideEffects".src/index.tsdefault-exports the namespace object thatsrc/jsfeatNext.tsbuilds by importing and instantiating every module.
A bundler cannot drop anything, because the namespace object holds a live
reference to every singleton. A consumer calling only
imgproc.grayscale()still ships ORB, YAPE, optical flow, the motion estimator and the 18 KB
src/orb/bit_pattern_31.tstable — the whole 57 KB UMD / 86 KB ESM bundle,all or nothing.
This has been true since the 0.9.0 restructure and has simply not been costly
enough to notice. The TEBLID tables change that: they are the largest single
addition the library has taken on, and they land on every consumer regardless of
use.
Proposed change
Additive, in three parts:
src/index.ts, sourced directly from itsmodule file rather than from the aggregator, so importing
{ imgproc }does not pull the aggregator's evaluation in with it.
"sideEffects": falsetopackage.json, so bundlers may drop unusedmodule evaluations.
export default jsfeatNextunchanged.Consumers importing the default namespace are unaffected and see the same
bundle. Consumers who care about size switch to named imports and get only what
they use. The
jsfeatNext.<module>convention, and everything #96 assumes aboutit, stays intact.
Why not the alternatives
break every existing consumer — a API/behavioral parity: static-vs-instance, double namespace, per-instance cache (Axis 2) #41-scale event, and post-1.0 that means a
major version. The additive route gets the same result for free.
@webarkit/jsfeat-next/teblid) would solve it for the newmodules only, diverge from the single-namespace convention, and penalise CDN
users who rely on one script tag.
Acceptance criteria
import { imgproc } from "@webarkit/jsfeat-next"works and type-checks.{ imgproc }produces a measurably smallerbundle than one importing the default — with the before/after numbers
recorded in this issue.
import jsfeatNext from "@webarkit/jsfeat-next"behaves identically totoday; the API-shape test is unchanged and green.
"sideEffects": falseis correct — verified by checking that no modulerelies on import-time side effects beyond registering itself on the
namespace.
Out of scope
Related
docs/features2d-expansion-plan.md