Tree-Shaking Verification
Research validating that unused layer components cost effectively nothing at runtime — the foundation of the unified pantry architecture.
How Nuxt auto-import works
Nuxt does not globally import all discovered components. It uses a compile-time transform: when the template compiler encounters a component tag, it injects a specific import for that component. Components never referenced in any template never get an import statement — they are completely excluded from the production bundle.
"Contrary to a classic global declaration, Nuxt preserves typings, IDEs completions and hints, and only includes what is used in your production code."
— Nuxt documentation
The .nuxt/components.d.ts file lists all available components for IDE autocompletion, but this is a type declaration file only — it has no effect on what gets bundled.
What gets excluded
For any component that is never referenced in a template:
JavaScript & templates
Completely excluded. Nuxt never injects the import, so Vite/Rollup never sees the code.
Scoped CSS (<style scoped>)
Excluded. Never imported, and Vite's cssScopeTo feature (v5.2.2+) provides a second layer of elimination.
Unscoped CSS (<style>)
Excluded. Never imported means never processed by Vite — even global styles inside unused SFCs are dropped.
What's always included
Some assets are unconditional — they ship regardless of which components a consumer uses.
Layer CSS entries (shared.css)
CSS registered in the layer's nuxt.config.ts css array is unconditional. This is intentional — it provides base styles, font imports, and Tailwind directives every consumer needs.
Tailwind theme extensions & plugins
The layer's tailwind.config.js merges into the consumer's config. All theme tokens (colors, spacing, type scale) are available whether or not the components that use them are imported.
Tailwind utilities from unused component source files
Tailwind's JIT scans source files matching content globs, not the bundle. Classes in unused component files may generate a few extra utility declarations. Marginal — typically bytes.
The Tailwind caveat is marginal — a handful of extra CSS utility declarations, typically bytes — but it's technically not zero.
Vue 3 tree-shaking by design
Vue 3 was architected from the ground up for tree-shaking. defineComponent and SFC compilation produce tree-shakeable output. Combined with Nuxt's per-component auto-import — which avoids barrel file re-export issues — unused components are cleanly eliminated.
As of our current toolchain (Vite 7.3.1, @vitejs/plugin-vue 6.0.4), the cssScopeTo feature is active. Even conditionally-imported-but-unused components can have their scoped styles tree-shaken — a second layer of protection beyond Nuxt's import-level elimination.
Conclusion
The claim that "Nuxt tree-shakes aggressively, so unused components cost nothing at runtime" is accurate. The unified pantry model — stocking all visual components in the layer regardless of how many projects use them — is well-supported by the toolchain. The only non-zero cost is Tailwind's content scanning generating utility classes from unused component source files, which is negligible in practice.
Sources
- Nuxt Auto-imports DocumentationOfficial docs
- Nuxt Components DirectoryOfficial docs
- Vue 3 Global API TreeshakingMigration guide
- Scoped style tree-shaking — vite-plugin-vue #533Vite PR
- Nuxt Layers UnwrappedCommunity deep-dive
Research conducted March 2026. Full source document in brand/tree_shaking_verification.md.