Skip to content

Spike: extend tree-shakeable conditional-import pattern to other modules to reduce consumer bundle size #885

@NoopDog

Description

@NoopDog

Summary

PR #719 (commit 9406db4) introduced a clean pattern for making next-auth and Google auth integrations conditionally imported and tree-shakeable:

  • Moved integration code into dedicated top-level directories (auth/, google/, nextauth/, terra/)
  • Added subpath exports in package.json so consumers import @databiosphere/findable-ui/<scope>/* directly
  • Marked next-auth as optional in peerDependenciesMeta so consumers that don't use it don't have to install it

We should evaluate where else this pattern applies, and whether there are additional bundle-size wins beyond it. Not every consumer uses Azul, TSV, the chat/research mode, MDX static generation, etc. — carrying that code (and its transitive deps) in every downstream app is waste.

Goals

  1. Identify modules/features in findable-ui that are optional per consumer.
  2. Propose refactors to isolate them behind subpath exports (and where applicable, optional peer deps).
  3. Identify general bundle-size improvements that apply across the library.
  4. Produce a prioritized list of refactor PRs with expected savings.

Candidates for conditional / isolated import

Module Current location Optional peers Consumer split
Azul API client src/apis/azul/, src/entity/azul/, azul-related viewModelBuilders/ Only consumers browsing Azul indices (data-browser, anvil-portal?). Others (hca-atlas-tracker, ncpi-dataset-catalog) don't need it.
TSV entity service src/entity/tsv/ Only consumers with TSV-backed catalogs.
APICF entity service src/entity/apicf/ Consumer-specific.
MDX pipeline src/utils/mdx/ next-mdx-remote, gray-matter, remark-gfm Docs-heavy consumers only. Currently these deps ride along for everyone.
Research mode / chat recent feat: add research mode with chat-driven dataset discovery (#800) Feature-flagged per consumer; likely not universal.
Export / Terra / file manifest src/components/Export/, src/providers/fileManifestState*, terra/ Only consumers that export data to Terra.
DataDictionary src/providers/dataDictionary*, src/components/DataDictionary* (if present) Consumer-specific.
Analytics (GA4) src/common/analytics/ Not every consumer wires GA. See #887 for react-gtm-module cleanup.
Google Sign-In src/google/, src/providers/googleSignInAuthentication/ Already isolated via #719 ✓ done

General bundle-size improvements to evaluate

  1. sideEffects field in package.json — not currently set. Tracked as sub-issue Add sideEffects field to package.json to enable bundler tree-shaking #886.
  2. Remove unused react-gtm-module peer dep — tracked as sub-issue Remove unused react-gtm-module peer dependency #887.
  3. Audit barrel re-exports — confirm no barrel pulls whole feature trees. Current src/index.ts is already minimal (good); keep it that way.
  4. Bundle analyzer in a test consumer — wire @next/bundle-analyzer in one consumer app temporarily to measure what findable-ui contributes; use it as a baseline to track PR-level improvements.
  5. Dynamic imports for heavy features — for genuinely heavy components (charts, MDX renderer, chat UI), consider exporting a loader pattern (() => import(...)) so consumers can code-split them even if they do use them.
  6. Heavy transitive deps audit — review size of ky, yup, @tanstack/*, chart libs, etc. Look for lighter alternatives or confirm they are already tree-shakeable. Check for any CJS-only deps that block tree-shaking.
  7. Ensure all direct deps are ESM / tree-shakeable — verify each peerDependency ships ESM + proper sideEffects hints.
  8. MUI import discipline — confirm every @mui/* import is a named import from @mui/material (not default imports from deep paths that can't be tree-shaken). ESLint rule no-restricted-imports can enforce.
  9. Icon imports@mui/icons-material individual imports only (already standard, but worth verifying).

Resolved open questions

See this comment for decisions:

  • Subpath exports strategy: keep both /lib/* passthrough (as escape hatch) and scoped paths like /azul, /tsv. Don't retroactively re-scope existing paths.
  • Plugin composition: skip for now.
  • Backward compatibility: migrate all consumers forward; no deprecation window. Each migration must be mechanical find-replace — not a structural refactor.

Deliverables

Acceptance criteria

  • Audit doc posted with per-module recommendation
  • Baseline bundle-size numbers captured from one consumer
  • Follow-up refactor tickets filed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions