Split renderComponent out of renderer.ts to reduce import footprint#21286
Split renderComponent out of renderer.ts to reduce import footprint#21286NullVoxPopuli-ai-agent wants to merge 4 commits intoemberjs:mainfrom
Conversation
There was a problem hiding this comment.
do we have to import from the resolver?
can the non-renderComponent renderer be moved to a different file?
There was a problem hiding this comment.
Done — moved the classic Renderer (along with ClassicRootState, DynamicScope, View) into its own classic-renderer.ts.
renderer.ts is now a thin re-export shim with zero heavy imports. All internal consumers updated to import directly from the source files (render-component.ts or classic-renderer.ts).
135b116 to
015ece7
Compare
smol-est-ember-app results after this PRTested with NullVoxPopuli/smol-est-ember-app ( Bundle breakdown after: The PR was slimmed down to just the essential changes:
|
Replace all internal barrel imports (from `@ember/-internals/glimmer`,
`@ember/-internals/environment`, etc.) with direct imports from the
specific source files that define what is needed. Also replace all
`export *` patterns in `@ember` packages with explicit named exports.
- Update ~40 source files to import from specific lib paths instead of
barrel `index.ts` files
- Replace `export *` with named exports in `@ember/-internals/environment`,
`@ember/engine/parent`, `@ember/template-compiler/*`, `ember-template-compiler`,
and `ember-testing`
- Replace `import * as environment` with named `{ hasDOM }` import in
`@ember/application/instance`
- Add deep import path entries to `@ember/-internals/package.json` exports map
- Add `@glimmer/opcode-compiler` dependency to `ember-template-compiler`
Test files are intentionally left unchanged as they may use barrel imports.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three changes work together to let bundlers tree-shake heavy deps from the renderComponent path: 1. Extract renderComponent/BaseRenderer to render-component.ts Rollup groups code by source file into shared chunks. Splitting renderComponent out of renderer.ts (which also has the classic Renderer with routing/outlet/curly deps) produces a separate, small shared chunk (~15KB vs ~183KB). 2. Lazy Glimmer global context (glimmer-global-context.ts) The setGlobalContext() call previously lived in environment.ts, which eagerly imports @ember/-internals/metal, @ember/array, and @ember/-internals/views. The new module provides lightweight fallback implementations (simple obj[key], Boolean(), etc.) that are replaced with full Ember implementations when environment.ts loads during classic Ember app boot. 3. Direct import in @ember/renderer The public @ember/renderer entry imports directly from render-component.ts instead of the @ember/-internals/glimmer barrel, so the barrel's other exports don't pull in their deps. Tested with NullVoxPopuli/smol-est-ember-app (renderComponent only): Before: 181KB raw / 58KB gzip After: 120KB raw / 38KB gzip Eliminated from bundle: routing, container, views, service, rsvp. Reduced: @ember/object+metal 84KB→13KB, @ember/array 18KB→0.2KB. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
015ece7 to
d56d02a
Compare
The runloop eagerly imported flushAsyncObservers from @ember/-internals/metal, pulling the entire observer/meta system (~42KB) into any bundle that uses the runloop. Making it lazy (registered by environment.ts during full Ember boot) breaks this dependency for standalone renderComponent. smol-est-ember-app: 120KB/38KB → 112KB/35KB gzipped Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updated results after merging barrel removal + lazy observer flushingCombined the barrel removal from #21295 and added lazy smol-est-ember-app bundle size
What's eliminatedrouting, @ember/object, @ember/-internals/metal, @ember/-internals/meta, @ember/array, container, views, service, rsvp — all gone. What remains (irreducible core)This is the core Glimmer rendering engine + Ember's runloop scheduler. Further reduction would require changes to the VM itself (e.g., replacing backburner with a lighter scheduler for standalone use), which is out of scope for this PR. |
…lt as default } Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Reduces the bundle footprint of
import { renderComponent } from '@ember/renderer'by ~35% (58KB → 38KB gzipped) through three changes:Extract renderComponent/BaseRenderer to
render-component.ts— Rollup groups code by source file into shared chunks. SplittingrenderComponentout ofrenderer.tsproduces a separate ~15KB chunk instead of sharing a ~183KB mega-chunk with the classic Renderer.Lazy Glimmer global context (
glimmer-global-context.ts) — ThesetGlobalContext()call previously lived inenvironment.ts, which eagerly imports@ember/-internals/metal,@ember/array, and@ember/-internals/views. The new module provides lightweight fallbacks (simpleobj[key],Boolean(), etc.) that are replaced with full Ember implementations whenenvironment.tsloads during classic app boot.Direct import in
@ember/renderer— Imports directly fromrender-component.tsinstead of the@ember/-internals/glimmerbarrel.smol-est-ember-app results
Test plan
🤖 Generated with Claude Code