Skip to content

perf(directives): skip needless Babel work in compiler transforms - #2329

Open
lxsmnsyc wants to merge 1 commit into
mainfrom
perf/compiler-transforms
Open

lxsmnsyc wants to merge 1 commit into
mainfrom
perf/compiler-transforms

Conversation

@lxsmnsyc

Copy link
Copy Markdown
Member

Makes the server function and lazy transforms do less Babel work. Most modules now skip Babel entirely, and modules with many server functions compile about 4 times faster.

Changes

  • The server function transform returns early when a module does not contain "use server". Before, every src/** module was parsed, transformed and printed twice (client and server), and the output was thrown away.
  • The lazy plugin appends export const id$$ = "..." as a string instead of prepending it with Babel. No existing code moves, so it returns map: null. Babel now runs only when the module calls lazy(.
  • transformFunction registers the hoisted serverFn_N declaration instead of crawling the program scope once per server function.
  • removeUnusedVariables crawls once and uses a worklist. Removing a declaration dereferences the bindings it read, and bindings left with no references are queued. This replaces the loop of full traversals and crawls.
  • assertNoMethodDirectives and collectMisplacedDirectives are merged into validateDirectivePlacement, which does one traversal.

Fixes found along the way

In a module with a server function, these used to crash the compile:

  • An unused for...of or for...in loop variable.
  • A chain of unused declarations that starts from an import, such as const first = db; const second = first;.

Benchmarks

Per-file compile time for the directives transform:

Input Before After
150 components, 30 inline server functions (server) 196 ms 47 ms
Same (client) 182 ms 40 ms
"use server" module, 60 exports (server) 58 ms 7.4 ms
~200 line component with no directive ~4 ms skipped

Testing

  • New specs cover chained unused declarations, redeclared var, and unused loop variables. lazy.spec.ts covers the appended id, the lazy import rewrite and the skip cases.
  • A differential check compiled every repo file that contains "use server", the spec inputs, and extra removal cases with the old and new compiler, in both modes and both envs. Output was identical except for the inputs that crash the old compiler.
  • vitest run passes (166 tests). tsc --noEmit is clean.
  • The basic and todomvc fixtures build.

🤖 Generated with Claude Code

- Skip the server function transform for modules that do not contain the directive.
- Append the lazy module id as a string instead of parsing with Babel. Babel now runs only when the module calls `lazy(`.
- Register each hoisted server function declaration instead of crawling the whole program scope per function.
- Remove unused declarations with a worklist in one pass instead of repeated traversals and crawls.
- Merge the two directive placement checks into one traversal.
- Keep unused `for...in` and `for...of` loop variables, which used to crash the compile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Sep 29, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 050c81e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@solidjs/start Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Sep 29, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@solidjs/start@2329

commit: 050c81e

@netlify

netlify Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for solid-start-landing-page ready!

Name Link
🔨 Latest commit 050c81e
🔍 Latest deploy log https://app.netlify.com/projects/solid-start-landing-page/deploys/6abb62deb3aebe0008b5527b
😎 Deploy Preview https://deploy-preview-2329--solid-start-landing-page.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

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.

1 participant