webarkit / webarkit/jsfeatNext

perf(build): make the bundle tree-shakeable without breaking the namespace export

Open
#137 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

code design enhancement npm Vite bundler
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.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:

  1. 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.
  2. Add "sideEffects": false to package.json, so bundlers may drop unused
    module evaluations.
  3. 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.

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": 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.
  • 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.