fix(build): resolve app imports of astryx to source in withAstryx - #5932
Open
PRIEYAN wants to merge 1 commit into
Open
fix(build): resolve app imports of astryx to source in withAstryx#5932PRIEYAN wants to merge 1 commit into
PRIEYAN wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The scoped rule withAstryx installs carries the `source` condition on
`Rule.resolve`, but `Rule.test` matches the module being processed and
`Rule.resolve` governs the requests that module makes. An app's own
`@astryxdesign/*` imports are issued from its sources, outside
node_modules, so they never match the rule and resolve through `default`
to dist.
The dist runtime emits `x`-prefixed atomic class names while the PostCSS
pass compiles the library from source and emits `astryx`-prefixed rules.
The two sets are disjoint, so the build exits 0, the route prerenders, a
full stylesheet is served, and the page renders unstyled with nothing
logged. apps/example-nextjs-source uses `withAstryx({})` as written, so
following it ships an unstyled site.
Widening the global conditionNames fixes resolution but breaks React's
JSX resolution and mis-resolves third-party packages that also publish a
`source` condition, which is what the scoped rule exists to avoid.
Webpack rules cannot key on the request string, so map the packages'
`source` export targets to aliases instead: resolution follows the astryx
packages themselves and the global conditions stay as Next resolved them.
Subpaths get an entry each, since `@astryxdesign/core/AlertDialog` is as
much a documented entry point as the root.
Fixes facebook#5920
PRIEYAN
force-pushed
the
fix/withastryx-source-condition-by-request
branch
from
September 2, 2026 19:17
d924b3b to
c018a31
Compare
cixzhang
requested changes
Sep 3, 2026
cixzhang
left a comment
Contributor
There was a problem hiding this comment.
Thanks for fixing the silent unstyled build. One compatibility issue still blocks this: an ordinary caller alias such as {'@astryxdesign/core': customPath} loses to the generated exact aliases, so composed Next configs silently load Astryx source instead of the caller's implementation. Please preserve both exact and prefix caller aliases; a resolver-level regression test would cover the real behavior.
Also please run Prettier on the two changed source files.
[Reviewed by Robohands]
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.
withAstryx()installs a rule that carries thesourcecondition onRule.resolve, scopedby
testtonode_modules/@astryxdesign/. ButRule.testmatches the module beingprocessed and
Rule.resolvegoverns the requests that module makes, so the rule onlycovers astryx-to-astryx imports. An app's own
@astryxdesign/*imports are issued from itssources, outside
node_modules, so they never match and resolve throughdefaultto dist.Dist's runtime emits
x-prefixed atomic class names while the PostCSS pass compiles thelibrary from source and emits
astryx-prefixed rules. The two sets share no class names, sothe build exits 0, the route prerenders, a full-size stylesheet is served, and the page
renders unstyled with nothing logged.
apps/example-nextjs-sourceuseswithAstryx({})aswritten, so a team following it ships an unstyled site.
Widening the global
conditionNamesdoes fix resolution, but it breaks React's JSXresolution and mis-resolves third-party packages that also publish a
sourcecondition(
lexical) — which is exactly what the scoped rule exists to prevent. Webpack rules cannotkey on the request string, so there is no rule shape that expresses "requests for
@astryxdesign/*from app code". Instead this reads thesourcetargets out of eachinstalled astryx package's export map and sets them as
resolve.aliasentries: resolutionfollows the astryx packages themselves and the global conditions stay as Next resolved them.
Subpaths get an entry each, since
@astryxdesign/core/AlertDialogis as much a documentedentry point as the root — aliasing only the root would leave 119 subpaths on dist and produce
a mixed bundle. A user-supplied alias still wins, and packages that are absent or ship no
sourcecondition keep normal resolution.Note that
require.resolve('@astryxdesign/core/package.json')throwsERR_PACKAGE_PATH_NOT_EXPORTED— core'sexportshas no./package.jsonkey — so themanifest lookup walks
node_modulesthe way Node resolves a bare specifier.On verification, being precise about what I did and did not run. I added
packages/build/src/next.test.mjs, 9 assertions over the configwithAstryx()emits againsta fixture package laid out the way npm installs one. It fails on 5 of them before this change
and passes all 9 after. I could not run it through the repo's own vitest —
pnpm installpulls the full monorepo toolchain and I deliberately kept build tooling off this machine — so
I executed the same assertions directly against the module under Node; CI will be the first
run through vitest proper.
check:changesets,check:cli-structure,check:portable-scripts,check:executable-bitsandcheck:use-clientpass locally.I have not reproduced the unstyled-page symptom end to end. There is no
next buildhere, sothe class-prefix mismatch itself is verified from the resolution semantics and the reporter's
measurements rather than observed. The reporter has a harness that automates this across every
documented setup and both bundlers; pointing it at this branch would be a stronger signal than
anything I can produce locally.
Turbopack is untouched —
withAstryx()writesnextConfig.webpack, which Turbopack ignores,and that is filed separately as #5921.
Fixes #5920