webarkit / webarkit/jsfeatNext
perf(build): make the bundle tree-shakeable without breaking the namespace export
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 12
- Forks
- 4
- Avg merge
- 16h 24m
- Merged PRs (30d)
- 34
Description
Summary
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.jsonexposes only"."inexportsand declares no"sideEffects".src/index.tsdefault-exports the namespace object thatsrc/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": falsetopackage.json, so bundlers may drop unused
module evaluations. - Keep
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 about
it, stays intact.
Why not the alternatives
- Replacing the namespace with named exports would give the same benefit and
break every existing consumer — a #41-scale event, and post-1.0 that means a
major version. The additive route gets the same result for free. - 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": falseis 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.
- Splitting the package into multiple entry points.
- Reducing the size of any individual table.
Related
- Restructure that introduced the namespace object: #40, #41
- The addition that makes this worth doing now: #135
- Plan:
docs/features2d-expansion-plan.md
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with src/index.ts, src/jsfeatNext.ts, and package.json to trace the default namespace and existing package exports. Check the API-shape test and build a fixture app importing only imgproc alongside one using the default export. Done means named imports type-check, the default and UMD namespace remain unchanged, and the bundle-size and side-effect claims are verified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- build-system, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100