Skip to content

docs(next): keep a webpack Server Component from shipping every Core component - #11305

Open
cixzhang wants to merge 3 commits into
mainfrom
docs/next-webpack-root-import
Open

cixzhang wants to merge 3 commits into
mainfrom
docs/next-webpack-root-import

Conversation

@cixzhang

@cixzhang cixzhang commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Reader impact

Who: a Next.js app router project that builds with webpack (next build --webpack) and imports from the Core package root, such as import {Button} from '@astryxdesign/core', in a Server Component.

Before: that page loads every Astryx client component. In a one-button page built with Next.js 16.4.6 and webpack, first-load JS was 853.8 kB gzip. The same page with import {Button} from '@astryxdesign/core/Button' was 273.6 kB.

After: with the setting this PR documents, the root-import page is 257.2 kB gzip, the same as the subpath page. Turbopack (the Next.js 16 default), Vite, plain webpack, and imports in 'use client' files are not affected.

New public API: none.

Source of truth

  • Cause: Next.js's webpack client-entry step walks the import graph from each Server Component page. Through a module without 'use client', it follows every import, and each 'use client' module it reaches becomes a browser entry. Core's root index re-exports every component and has no directive, and most component modules are 'use client'. So one root import from a Server Component adds the whole library to the page.
  • experimental.optimizePackageImports is typed in next/dist/server/config-shared.d.ts (ExperimentalConfig). It rewrites root imports of the listed package to the modules they name, so the walk reaches only those.
  • Core's package.json exports has an entry per component (./Button and so on). astryx component <Name> prints that entry, and the shipped docs already use it in samples.

Correction

  • astryx docs styling/tokens-and-setup has a new section, nextjs-webpack. It shows the next.config.mjs setting, says why in one sentence, and recommends a component entry in Server Components.
  • apps/example-nextjs, apps/example-nextjs-tailwind and apps/example-nextjs-stylex set it in next.config.mjs. The theme preview starter app (packages/cli/assets/preview-app) is a copy of apps/example-nextjs, and a test keeps them the same, so it gets the same file.
  • apps/example-nextjs/README.md has a short step 4 for the config.
  • A [docs] patch changeset for @astryxdesign/cli, which ships the docs and the starter app.
  • Generated: the no-icon-set goldens (packages/cli/test/__golden__/no-icon-set/docs-tree.json, search-experimental.json, search-experimental.txt) list the new section. Their new "experimental" mentions are Next.js's own experimental config key, not an Astryx experimental surface, so they are not an isolation leak.

Not changed: apps/example-nextjs-source builds Core from source through withAstryx, and packages/core/README.md shows no Next.js config.

Evidence

Fixture: a copy of apps/example-nextjs with Core and the neutral theme packed from this branch, Next.js 16.4.6, next build --webpack. First-load JS is the gzip sum of every script each prerendered page loads.

Page Before After
Server Component, import {Button} from '@astryxdesign/core' 853.8 kB 257.2 kB
Server Component, import {Button} from '@astryxdesign/core/Button' 273.6 kB 257.2 kB
Example home page ('use client') 287.3 kB 268.6 kB

Rendered section (astryx docs styling/tokens-and-setup nextjs-webpack):

## Next.js with webpack

If your Next.js app builds with webpack (`next build --webpack`), add `@astryxdesign/core` to `experimental.optimizePackageImports`. With webpack, a Server Component that imports from the package root would otherwise ship every client component; this keeps first load to what the page uses. Turbopack, the default bundler in Next.js 16, needs no change, and the setting is safe to keep there.
...
In Server Components, also import each component from its own entry, for example `import {Button} from '@astryxdesign/core/Button'`. `astryx component <Name>` prints that entry. Files that start with `'use client'` are not affected.

Scope

Components: none

  • This PR changes documentation only, or names every necessary generated artifact (the CLI goldens above).
  • Runtime, API, visual, and policy changes were removed or split.
  • Public text and artifacts contain no internal Meta context.

The example and starter next.config.mjs files change build configuration only; no Core or CLI code changes.

Testing

  • pnpm check:knowledge: aligned.
  • Pre-commit checks (changesets, CLI structure, sync, setup contract and the rest): pass.
  • vitest run packages/cli/test/experimental-isolation.test.mjs --update: 46 passed, 5 snapshots updated (the goldens above).
  • vitest on packages/cli/api/docs/docs.test.mjs and the starter-app copy test in packages/cli/api/theme-edit/theme-preview.test.mjs: pass.
  • Prettier on all touched files: clean. ESLint on the doc file: clean.
  • pnpm specs:for --diff origin/main and pnpm review:pre: 0 findings; no concern-routed claim applies to a docs section.

@vercel

vercel Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Nov 12, 2026 2:37am UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 11, 2026
@astracat-bot

astracat-bot Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Nov 12, 2026, 2:45 AM UTC

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · 1f142ba

Storybook · Sandbox · built from this PR's head

Package size: @astryxdesign/cli 3.93 MB packed (+398 B); no new dependencies.

Not run on this PR: add ci:run-visual, ci:run-a11y or ci:run-rtl to run them.

Current run: CI concluded failure; parts of this report may be missing.


Generated by PR Enrichment workflow | View full report

@astracat-bot astracat-bot Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes. The Next.js webpack guidance is accurate and well placed; CI now confirms the CLI's experimental-isolation goldens need regenerating.

  • The new nextjs-webpack section is missing from packages/cli/test/__golden__/no-icon-set/docs-tree.json, and its experimental.optimizePackageImports wording adds a fourth result to astryx search experimental, so three snapshot tests in packages/cli/test/experimental-isolation.test.mjs fail in test-node (2/4): run vitest run packages/cli/test/experimental-isolation.test.mjs --update, commit the docs-tree.json and search-experimental golden changes, and note in the description that the new experimental mentions are Next.js's option, not an Astryx experimental surface.

test-node (4/4) also failed, but only on a temp-folder cleanup timeout in packed-gather-cache.test.mjs after all its tests passed, which this change does not touch; a re-run should clear it.

Claims and files checked
  • Claims
    • Changeset: the guide gains a Next.js with webpack section: verified (tokens-and-setup.doc.mjs:141-167).
    • Changeset: the section shows the optimizePackageImports setting in next.config.mjs: verified (tokens-and-setup.doc.mjs:149-161).
    • Changeset: it recommends a component entry such as @astryxdesign/core/Button in Server Components: verified (tokens-and-setup.doc.mjs:164).
    • Changeset: without either, a webpack build ships every client component to a page whose Server Component imports the package root: consistent with Core's root barrel, which has no 'use client' while component modules do (packages/core/src/index.ts, Button/Button.tsx:3); the sizes are the author's measurement.
    • Changeset: the theme preview starter has the same setting: verified (packages/cli/assets/preview-app/next.config.mjs:4-10).
    • Changeset and description: no API changes: verified.
    • Description: first-load sizes of 853.8, 273.6 and 257.2 kB: not reproduced; consistent with the mechanism.
    • Description: Turbopack, Vite, plain webpack and 'use client' files are not affected: consistent with the mechanism; not measured.
    • Description: optimizePackageImports is a Next.js experimental option that rewrites root imports to the modules they name: verified against Next's reference page for the option.
    • Description: Core has an entry per component, astryx component <Name> prints it, and shipped docs already use it: verified (packages/core/package.json ./Button; getting-started.doc.mjs:162).
    • Description: three example apps and the starter set the option, and a test keeps the starter equal to apps/example-nextjs: verified (theme-preview.test.mjs:713-724; the four files are identical).
    • Description: the example README gains step 4: verified (apps/example-nextjs/README.md:59-72).
    • Description: a [docs] patch changeset for @astryxdesign/cli, which ships the docs and the starter: verified (packages/cli/package.json files includes assets).
    • Description: apps/example-nextjs-source and the Core README are unchanged: verified.
    • Description: the pull request names every necessary generated artifact: false, the experimental-isolation goldens are missing.
    • Description: public text has no internal context: verified.
    • Description: the listed checks pass: not rerun; experimental-isolation.test.mjs, which fails in CI, is not among them.
  • Files
    • .changeset/next-webpack-optimize-package-imports.md: clear.
    • apps/example-nextjs-stylex/next.config.mjs: clear.
    • apps/example-nextjs-tailwind/next.config.mjs: clear.
    • apps/example-nextjs/README.md: clear.
    • apps/example-nextjs/next.config.mjs: clear.
    • packages/cli/assets/docs/tree/tokens-and-setup.doc.mjs: finding, the goldens above.
    • packages/cli/assets/preview-app/next.config.mjs: clear; identical to the example, as the copy test requires.

Automated review (maintainer link)

@cixzhang
cixzhang marked this pull request as ready for review November 12, 2026 01:04
@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec 1f142ba

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI. The Next.js webpack guidance fits the shipped docs' purpose, and the experimental-isolation goldens now record the new nextjs-webpack section, which fixes the one finding from the last review. CI has not run in full on this head: the required test, build and docsite-test checks report "Heavy CI deferred" by design, and the CLI test shards that check these goldens run in the pre-merge re-run of all jobs.

Claims and files checked
  • Claims
    • Changeset: the guide gains a Next.js with webpack section: verified (tokens-and-setup.doc.mjs:141-167).
    • Changeset: the section shows the optimizePackageImports setting in next.config.mjs: verified (tokens-and-setup.doc.mjs:149-161).
    • Changeset: it recommends a component entry such as @astryxdesign/core/Button in Server Components: verified (tokens-and-setup.doc.mjs:164).
    • Changeset: without either, a webpack build ships every client component to a page whose Server Component imports the package root: consistent with Core's directive-less root barrel (packages/core/src/index.ts) and component modules that start with 'use client' (Button/Button.tsx:3); the sizes are the author's measurement.
    • Changeset: the theme preview starter has the same setting: verified (packages/cli/assets/preview-app/next.config.mjs:4-10).
    • Changeset and description: no API changes: verified.
    • Description: first-load sizes of 853.8, 273.6, 257.2, 287.3 and 268.6 kB: not reproduced; consistent with the mechanism.
    • Description: Turbopack, Vite, plain webpack and 'use client' files do not have the every-component cost: consistent with the mechanism; not measured.
    • Description: Next.js declares the option in its config types and rewrites root imports to the modules they name: not checked here; the guidance rests on the author's measurement.
    • Description: Core has an entry per component, astryx component <Name> prints it, and shipped docs already use it: verified (packages/core/package.json ./Button; component.mjs:283; getting-started.doc.mjs:162).
    • Description: three example apps and the starter set the option, and a test keeps the starter equal to apps/example-nextjs: verified (the four files are identical; theme-preview.test.mjs:713-724).
    • Description: the example README gains step 4: verified (apps/example-nextjs/README.md:59-72).
    • Description: a [docs] patch changeset for @astryxdesign/cli, which ships the docs and the starter: verified; the changeset check passes in CI.
    • Description: the goldens list the new section, and their new experimental mentions are Next.js's config key: verified (docs-tree.json:1239-1250, both search-experimental goldens).
    • Description: apps/example-nextjs-source (built through withAstryx) and the Core README are unchanged and show no such config: verified.
    • Description: the pull request is documentation plus named generated artifacts, with no runtime, API, visual or policy change and no internal context: verified.
    • Description: the listed local checks pass: not rerun; Lint and the CLI smoke test pass in CI, and the five updated snapshots match the five snapshot assertions over the three goldens.
  • Files
    • .changeset/next-webpack-optimize-package-imports.md: clear.
    • apps/example-nextjs-stylex/next.config.mjs: clear.
    • apps/example-nextjs-tailwind/next.config.mjs: clear.
    • apps/example-nextjs/README.md: clear.
    • apps/example-nextjs/next.config.mjs: clear.
    • packages/cli/assets/docs/tree/tokens-and-setup.doc.mjs: clear.
    • packages/cli/assets/preview-app/next.config.mjs: clear; identical to the example, as the copy test requires.
    • packages/cli/test/__golden__/no-icon-set/docs-tree.json: clear; matches the test's sentence rule for the new section.
    • packages/cli/test/__golden__/no-icon-set/search-experimental.json: clear.
    • packages/cli/test/__golden__/no-icon-set/search-experimental.txt: clear.

Automated review (maintainer link)

@cixzhang
cixzhang marked this pull request as draft November 12, 2026 07:37
@cixzhang
cixzhang marked this pull request as ready for review November 12, 2026 07:37

This branch was successfully deployed

1 active deployment
Preview — 1f142ba5 Deployed Nov 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant