Conversation
Every heavy leaf (google-libphonenumber, country-flag-icons, i18n-iso-countries,
country-locale-map, react-day-picker, chart.js, @tanstack/react-table) was in
the static import closure of dist/index.js, so import('@konstructio/ui') paid
for PhoneNumberInput, the date pickers, the charts and VirtualizedTable even
when a screen rendered none of them.
PhoneNumberInput, DatePicker, PieChart, LineChart and VirtualizedTable are now
thin wrappers that render their implementation through React.lazy inside a
Suspense boundary with a same-footprint aria-busy fallback. DateRangePicker
lazy-loads only the react-day-picker grid. Filter's getLocale loads
country-locale-map on first use and falls back to en-US, which is also the
result for the default countryCode. Public exports, props and types are
unchanged and no wrapper touches window at module scope.
Static closure of dist/index.js: 3,950.7 KB (369 files) -> 955.5 KB (340
files). Tests that render a lazy component now await the first query and warm
the content module in beforeAll. The PieChart canvas gets an accessible name,
which the role=img element lacked.
This branch has not been deployed
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.
Why
import('@konstructio/ui')pulled the whole barrel's dependency graph statically. The static import closure ofdist/index.js(following everyimport … from './x.js'recursively) was 3,950 KB across 369 files, dominated by leaves most screens never render:libphonenumber-*.jsgoogle-libphonenumber(PhoneNumberInput)phone-number.provider-*.jscountry-flag-iconsReact flags +i18n-iso-countries(PhoneNumberInput)utils-*.jscountry-locale-map(Filter date dropdown label formatting)dist-*.jschart.js+react-chartjs-2(PieChart, LineChart)DayPicker-*.jsreact-day-picker(DatePicker, DateRangePicker)table.provider-*.js@tanstack/react-table(VirtualizedTable)FlagSelectorList-*.js@tanstack/react-virtualflag list (PhoneNumberInput)What
Heavy leaves are now loaded lazily inside the library. Public API is unchanged: same named exports from the root barrel, same props, same types.
PhoneNumberInput,DatePicker,PieChart,LineChart,VirtualizedTableare thin wrappers that render their implementation (components/<Name>Content) throughReact.lazyinside aSuspenseboundary. Fallbacks keep the DOM footprint (label + input-sized box, calendar-sized card, chartheight,<section class="kvt">) and are markedaria-busy.DateRangePickerkeeps presets/inputs/month headers static and lazy-loads only thereact-day-pickergrid (CalendarMonthContent); the placeholder height is derived from the month's week count.Filter'sgetLocaleloadscountry-locale-mapon first use (useLocalehook); until it resolves it returnsen-US, which is also the result for the defaultcountryCode="US", so the common case renders identically.VirtualizedTablestatics (TruncateText,Actions,Events) are imported by file so the static graph no longer reaches the tanstack-backed context barrel.DatePicker.types.tsimportscountries-and-timezonesasimport type(it was only ever used in a type position).PieChart's canvas now has an accessible name (title/subtitle, orPie chart) — therole="img"canvas had no alternative text before.No wrapper touches
window/documentat module scope, so the wrappers stay SSR-safe for the Next.js host; during SSR React renders the Suspense fallback (or the content when streaming) and hydrates the lazy chunk on the client.Result
Static closure of
dist/index.js: 3,950.7 KB (369 files) → 955.5 KB (340 files), −76 %. Totaldist/*.jsis unchanged (3,610 KB); the difference is now reachable only throughimport():libphonenumber-*.js,phone-number.provider-*.js,FlagSelectorList-*.js,country-locale-map-*.js,DayPicker-*.js, the chart.js chunk,table.provider-*.js.Remaining static weight is core UI and out of scope here:
motion/react(160 KB, Modal/ButtonGroup/DateRangePicker — candidate forLazyMotion+m),react-router-dombundled into the Breadcrumb chunk (56 KB — it is a peer dependency but not in rollupexternal),tailwind-merge(42 KB), floating-ui/radix,prop-typesviareact-feather(22 KB).Caveats
aria-busyplaceholder on the first mount of a lazy component (later mounts are synchronous once the chunk is cached).awaitthe first query (findBy*); the affected suites do that and warm the content module inbeforeAllso cold module transforms do not eat thefindBytimeout.DateRangePicker › should keep the built-in windows when presets is omittedfails onmaintoo (off by exactly one hour, DST-dependent) and is untouched here.Validation
npm run lint— passnpm run check:types— passnpm run check:prettier— passnpm run test— see PR checks (locally only the pre-existing DST failure above)npm run build— pass; verifieddist/index.jshas no static path to the chunks listed above and each wrapper emits a realimport()to its content chunk.