Skip to content

perf: make the published package tree-shakeable - #1841

Open
saurabhraghuvanshii wants to merge 2 commits into
layer5io:masterfrom
saurabhraghuvanshii:perf/tree-shakeable-package
Open

saurabhraghuvanshii wants to merge 2 commits into
layer5io:masterfrom
saurabhraghuvanshii:perf/tree-shakeable-package

Conversation

@saurabhraghuvanshii

@saurabhraghuvanshii saurabhraghuvanshii commented Sep 13, 2026

Copy link
Copy Markdown
Member

Consumers could not tree-shake @sistent/sistent at all. Importing one component from 0.22.6 pulls ~14,000 modules and 14.7 MB into a webpack build, 10,775 of those modules being @mui/icons-material. In layer5.io this was the largest single contributor to build memory.

Three causes, all fixed here:

  • module pointed at the CommonJS build. main and module were both ./dist/index.js, so no bundler ever selected dist/index.mjs. module now points at the ESM build, and an exports map routes import and require to the matching build and declarations.

  • There was no sideEffects field, so bundlers had to keep every export. The package has no top-level side effects (no CSS imports, no global registration), so it is now marked sideEffects: false.

  • Six components imported icons from the @mui/icons-material barrel, which re-exports ~10,800 modules. They now import by path, and a no-restricted-imports rule keeps the barrel out.

Serving the ESM build exposed two imports that only worked through CJS interop, and would have broken strict ESM consumers:

  • import jsyaml from 'js-yaml' has no default export in js-yaml's ESM build; now import * as jsyaml.
  • lodash/debounce has no extension and lodash has no exports map, which webpack rejects from an .mjs file (fullySpecified); now lodash/debounce.js.

Measured with webpack 5, a consumer that imports only Box:

published 0.22.6 this change*
modules 14,132 5,288
@mui/icons-material 10,775 55
output 14.68 MB 2.27 MB

  • with the matching @sistent/mui-datatables deep-import fix (layer5io/mui-datatables), which removes the remaining barrel.

The build succeeds (ESM, CJS and declarations), all 515 tests pass, and lint is clean. The public API is unchanged.

Not changed: noExternal: [/^@meshery\/schemas/] (c34bfaa) is what grew the package from 2.3 MB in 0.18.0 to 9.3 MB in 0.18.1, but it was added to fix a schema version mismatch in the Meshery UI, so un-bundling it needs a maintainer decision rather than a drive-by change.

Notes for Reviewers

This PR fixes #

Signed commits

  • Yes, I signed my commits.

Summary by CodeRabbit

  • Compatibility

    • Improved package entry-point handling for both ESM and CommonJS consumers.
    • Added explicit package exports and identified the package as side-effect free.
  • Maintenance

    • Standardized icon imports to dedicated module paths.
    • Updated YAML and utility imports for improved module compatibility.
    • Added a linting rule to prevent barrel imports for Material UI icons.

@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: c42d1a11-a054-42ca-8bce-62add07603d6

📥 Commits

Reviewing files that changed from the base of the PR and between 53f1329 and 8b46a58.

📒 Files selected for processing (11)
  • eslint.config.js
  • package.json
  • src/custom/Carousel/Carousel.tsx
  • src/custom/CatalogDesignTable/DesignTableColumnConfig.tsx
  • src/custom/CatalogDetail/helper.ts
  • src/custom/CollaboratorAvatarGroup/CollaboratorAvatarGroup.tsx
  • src/custom/CustomCatalog/Helper.ts
  • src/custom/DashboardWidgets/RecentDesignWidget.tsx
  • src/custom/SearchBar.tsx
  • src/custom/Workspaces/WorkspaceTransferButton.tsx
  • src/custom/Workspaces/WorkspaceViewsTable.tsx

Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

The package now exposes conditional ESM and CommonJS entry points. ESLint rejects MUI icon barrel imports. Existing source imports use individual icon paths and explicit module bindings.

Changes

Module resolution updates

Layer / File(s) Summary
Package entry-point configuration
package.json
The package uses dist/index.mjs for ESM imports and dist/index.js for CommonJS requires. It exposes matching declaration files, ./package.json, and sideEffects: false.
Restricted barrel imports
eslint.config.js
The lint configuration rejects imports from @mui/icons-material and specifies individual icon paths.
Source import migrations
src/custom/...
MUI icons use dedicated module paths. js-yaml uses namespace imports. Lodash debounce uses the explicit .js path.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix

Suggested reviewers: leecalcote

Merge Risk: ⚪ Minimal · up to 3d2c3

The package entry points and import migrations are ready to merge without a supported merge-blocking risk.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: making the published package tree-shakeable.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Consumers could not tree-shake @sistent/sistent at all. Importing one
component from 0.22.6 pulls ~14,000 modules and 14.7 MB into a webpack build,
10,775 of those modules being @mui/icons-material. In layer5.io this was the
largest single contributor to build memory.

Three causes, all fixed here:

- `module` pointed at the CommonJS build. `main` and `module` were both
  `./dist/index.js`, so no bundler ever selected `dist/index.mjs`. `module`
  now points at the ESM build, and an `exports` map routes `import` and
  `require` to the matching build and declarations.

- There was no `sideEffects` field, so bundlers had to keep every export.
  The package has no top-level side effects (no CSS imports, no global
  registration), so it is now marked `sideEffects: false`.

- Six components imported icons from the `@mui/icons-material` barrel,
  which re-exports ~10,800 modules. They now import by path, and a
  `no-restricted-imports` rule keeps the barrel out.

Serving the ESM build exposed two imports that only worked through CJS
interop, and would have broken strict ESM consumers:

- `import jsyaml from 'js-yaml'` has no default export in js-yaml's ESM
  build; now `import * as jsyaml`.
- `lodash/debounce` has no extension and lodash has no exports map, which
  webpack rejects from an `.mjs` file (`fullySpecified`); now
  `lodash/debounce.js`.

Measured with webpack 5, a consumer that imports only `Box`:

                      published 0.22.6    this change*
  modules                       14,132           5,288
  @mui/icons-material           10,775              55
  output                      14.68 MB         2.27 MB

  * with the matching @sistent/mui-datatables deep-import fix
    (layer5io/mui-datatables), which removes the remaining barrel.

The build succeeds (ESM, CJS and declarations), all 515 tests pass, and lint
is clean. The public API is unchanged.

Not changed: `noExternal: [/^@meshery\/schemas/]` (c34bfaa) is what grew the
package from 2.3 MB in 0.18.0 to 9.3 MB in 0.18.1, but it was added to fix a
schema version mismatch in the Meshery UI, so un-bundling it needs a
maintainer decision rather than a drive-by change.

Signed-off-by: saurabhraghuvanshii <saurabhsraghuvanshi@gmail.com>
@saurabhraghuvanshii
saurabhraghuvanshii force-pushed the perf/tree-shakeable-package branch from 8b46a58 to d492352 Compare September 13, 2026 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants