Repository navigation
fix(build): emit every per-component entry point - #3237
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`components/color-picker`, `components/filter` and `components/tree` failed
to import in 11.0.0-alpha.4 (the package root worked).
Root cause: the library build used only the `components/index.js` barrel as
its entry. Under `preserveModules`, an `index` that only re-exports
(`export { default } from './tree'`) is not emitted when it is merely
reachable from the barrel; Rollup binds the barrel's import straight through
to `./tree`. With no built `index.js`, `generate-entry-shims` skipped the
folder, so `dist/es/components/tree.js` (the target of the `./components/*`
export) did not exist. `tsc` still emitted `index.d.ts`, so types resolved
and the import failed only at runtime.
The same root cause also affected:
- `components/grid` and `utilities/hooks`: not reachable from the barrel,
so they had no JS at all (types only).
- `components/menu-dropdown`, `page-header`, `popover`, `progress-ring`:
named exports the barrel doesn't use (`DropdownNubbinPositions`,
`ListItem`, `ListItemLabel`, `Info`, `Title`, `DetailRow`, `DetailBlock`,
`PopoverNubbinPositions`, `THEME_OPTIONS`) were tree-shaken from the
deep-import module despite being declared in its types.
Fix: make every `components/*/index` and `utilities/*/index` an explicit
build entry. Rollup always emits entries in full. The shim generator now
re-exports `default` only when the index has one; `utilities/hooks` is
named-only, and a missing `default` re-export is an ESM link error.
Regression test: `scripts/check-package-exports.mjs` (`npm run
test:exports`, run at the end of `npm run build`, so CI and publish both
run it) lists every directory index in the source tree and imports it
through the package's own `exports` map. Each must resolve its types under
the import and require conditions, load via ESM `import()` and CJS
`require()`, and supply at runtime every value export its types declare.
Against the previous build it reports all of the above.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Niznikr
force-pushed
the
fix/build-per-component-entries
branch
from
October 21, 2026 20:29
5b281b3 to
e5a94ab
Compare
interactivellama
approved these changes
Oct 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #
Additional description
Symptom: In
11.0.0-alpha.4, importing@salesforce/design-system-react/components/color-picker,.../filteror.../treefails. Importing from the package root works.Root cause: The library build had a single entry, the
components/index.jsbarrel. WithpreserveModules, Rollup does not emit anindexthat only re-exports (export { default } from './tree') if the barrel is the only thing that reaches it. Rollup links the barrel's import straight to./treeinstead. Because there was no builtindex.js,generate-entry-shimsskipped the folder. That meantdist/es/components/tree.jsanddist/cjs/components/tree.cjs, the files the./components/*export points to, were never created.tscstill emittedindex.d.ts, so types resolved and the import failed only at runtime.The same cause broke more than the three reported entries:
components/color-picker,filter,treecomponents/grid,utilities/hookscomponents/menu-dropdownDropdownNubbinPositions,ListItem,ListItemLabelcomponents/page-headerInfo,Title,DetailRow,DetailBlockcomponents/popoverPopoverNubbinPositionscomponents/progress-ringTHEME_OPTIONSThe missing named exports were declared in each entry's
.d.ts. The barrel doesn't use them, so they were tree-shaken out of the deep-import module.Fix:
vite.config.ts: everycomponents/*/indexandutilities/*/indexis now an explicit build entry. Rollup always emits entries in full.scripts/generate-entry-shims.mjs: the shim re-exportsdefaultonly when the index has one.utilities/hookshas only named exports, and re-exporting adefaultthat doesn't exist is an ESM link error. Without this change, thehooksshim the build now generates would fail to load.Build output changes: I diffed
dist/before and after.indexfiles and shims for the seven entry points in the table.__esModule(standard interop marker for entry chunks).Regression test:
scripts/check-package-exports.mjs(npm run test:exports) runs as the last step ofnpm run build, so both CI (test:ci) and the publish workflow run it. It lists every directory with anindexin the source tree, so an entry the build fails to emit is reported, not skipped. It imports each one through the package's own name, which applies the realexportsmap. Each entry must:importandrequireconditions (moduleResolution: bundler, as in our tsconfig);import()and CJSrequire();Result: 57/57 entry points pass. On the unfixed build it reports 18 failures, which cover every row in the table above.
Not breaking. This only restores entry points and exports that the types already declared. Note that
components/gridnow ships JS as well as types. It isn't in the barrel, but its.d.tswas already published.CONTRIBUTOR checklist (do not remove)
Please complete for every pull request.
Green gate — all of these must pass locally (CI runs the same):
npm run lintpasses with 0 errors (npm run lint:fixto auto-fix). Warnings are the tracked gradual-migration backlog; do not add new errors.npm run typecheckis clean (tsc --noEmit).npm test -- --runpasses — this runs both Vitest projects (jsdomunit+ real-browserbrowser) and the story HTML snapshots. If you changed rendered markup on purpose, update snapshots withnpm test -- --run -uand review the diff.npm run buildsucceeds (type-check + Vite library build +.d.ts+ entry shims).Behavior & docs:
components/button/__tests__). New props and bug fixes should get a regression test. Tests that genuinely need a real browser (focus traversal, layout/measurement, canvas) go in a*.browser.test.jsxfile (thebrowserproject); everything else is jsdom. — The regression test is a Node script, not Vitest. It has to run against the builtdist/with real Node and TypeScript module resolution, which the Vite resolver would bypass.npm run storybook→ http://localhost:6007/. Confirm the story actually renders and behaves (deprecated Storyshots/Karma are gone; there is no separate browser-tests server). — N/A, build-only changeonRenderContent/onRenderVisualPicker,iconprops,events), not assumptions — a common source of "component looks broken" reports has been stories authored against the wrong API. Cross-check againstcomponents/<name>/__examples__. — N/A.d.ts(they're generated by the build); JS consumers rely on them via editor type-acquisition. — No type changes. The runtime now matches the published types.REVIEWER checklist (do not remove)
CIworkflow: lint, typecheck, test, build). Chromatic visual review, if configured, has been checked.components/__tests__/__snapshots__/story-snapshots.test.jsx.snap).@salesforce/design-system-react/components/<name>and nested paths resolve for ESM, CJS, and types). Removing/renaming a public component or export is a breaking change →feat!:/BREAKING CHANGE:and a major version bump.