Skip to content

Import protection dominates production build time on large module graphs (88% of plugin time, 8m45s client build on CI) #7605

@daveycodez

Description

@daveycodez

Which project does this relate to?

Start

Describe the bug

Production builds of our docs site (~7,300 client modules, large MDX content collection via fumadocs) take 8m 45s for the client environment alone on 4-core GitHub Actions runners. Rolldown's plugin timing report attributes the overwhelming majority of that to import protection:

[PLUGIN_TIMINGS] Your build spent significant time in plugins. Here is a breakdown:
  - tanstack-start-core:import-protection (88%)
  - fumadocs-mdx:mdx (12%)
✓ built in 8m 45s

The SSR pass shows the same profile:

[PLUGIN_TIMINGS] Your build spent significant time in plugins. Here is a breakdown:
  - tanstack-start-core:import-protection-transform-cache (50%)
  - tanstack-start-core:import-protection (43%)
  - fumadocs-mdx:mdx (7%)

The same build on an M-series MacBook completes in ~16s with the identical 88% plugin share, so the absolute cost appears dominated by per-import this.resolve() calls issued for every import of every transformed module. These scale linearly (or worse) with module-graph size and amplify badly on slower CI filesystems. This concern was also flagged during review of #6722 ("the transform hook now resolves all import sources… N resolve calls per transformed file. For large codebases, this could impact latency").

Setting importProtection: { enabled: false } for production builds restores the build to roughly 1 minute on the same CI runner.

Impact

  • CI build time went from ~4 min to ~12 min once our content collection grew (~250 MDX pages)
  • Cost is invisible without PLUGIN_TIMINGS — most users will just see "builds got slow"

Possible directions

  • Skip resolve for bare/external specifiers that can't be project-local violations
  • Batch or cache resolves across the module graph (the transform cache exists but resolution still dominates)
  • In build mode, rely solely on post-bundle analysis: build mode already defers violation checks until after tree-shaking (fix: import protection robustness #6746), so the per-module transform-time resolution work seems avoidable

Your Example Website or App

https://github.com/better-auth-ui/better-auth-ui (apps/docs)

Complete minimal reproducer

https://github.com/better-auth-ui/better-auth-ui

Steps to Reproduce the Bug

  1. bun install
  2. cd apps/docs && bun vite build
  3. Observe PLUGIN_TIMINGS breakdown; on a 4-core machine the client build takes several minutes
  4. Add importProtection: { enabled: false } to tanstackStart() and rebuild — build completes in a fraction of the time

Expected behavior

See above

Screenshots or Videos

No response

Platform

  • Packages: @tanstack/react-start 1.168.25, @tanstack/start-plugin-core 1.171.17 (latest at time of writing)
  • Bundler: Vite 8.0.16 (Rolldown)
  • OS: reproduced on macOS (relative share) and ubuntu-latest GitHub Actions (absolute blowup)

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions