Lazy‑Loading StencilJS Components: When and How to Split Your Bundle
Learn how to enable component‑level lazy loading in StencilJS, verify the generated chunks, and understand when the trade‑off makes sense.
12 Sept 2026, 06:42 UTC

Problem: Initial bundle grows with every component
When you add a new StencilJS component to a page, its JavaScript, styles, and any assets are bundled into the main application file by default. As the component library expands, the initial download can become large enough to delay first paint, especially on slower networks. The goal is to keep the core bundle small while still making the component available when it is actually needed.
Enable lazy loading with the lazy flag
StencilJS lets you mark a component for lazy loading by adding lazy: true to its @Component decorator. The compiler then treats that component as a separate asynchronous chunk.
import { Component, h } from '@stencil/core';
@Component({
tag: 'my-lazy-comp',
styleUrl: 'my-lazy-comp.css',
lazy: true // <— enables code‑splitting
})
export class MyLazyComp {
render() {
return Hello from a lazy‑loaded component;
}
}
No other changes to the component’s API are required; you continue to use it in templates exactly as before.
What the compiler generates
During a build (npm run build) Stencil emits two kinds of files in the build/ directory:
- The main bundle (e.g.,
main.js) that contains the application bootstrap and all non‑lazy components. - One separate file per lazy component, named after its tag (e.g.,
my-lazy-comp.js). This file holds the component’s class, its scoped styles, and any child components that are also marked lazy.
At runtime, when the template first encounters <my-lazy-comp></my-lazy-comp>, Stencil injects a dynamic import:
import('./my-lazy-comp.js').then(module => {
// component definition is now available
});
The network request for my-lazy-comp.js occurs only after the element is added to the DOM, keeping the initial payload smaller.
Verifying the split in dev and prod
You can confirm that lazy loading works without needing to claim any personal test results. Follow these steps:
- Build the project: Run
npm run build(ornpm run startfor a dev server that also emits the same chunks). - Inspect the output: Open the
build/folder and verify the presence of a file matching the lazy component’s tag, e.g.,my-lazy-comp.js, alongsidemain.js. - Serve the build: Use a static server such as
serve buildor the dev server (npm run start). - Open Chrome DevTools → Network: Disable cache, reload the page, and look for a request to
my-lazy-comp.js. It should appear only after the component’s tag is encountered in the HTML (you can trigger it via a button that conditionally renders the component). - Confirm execution timing: Add a temporary log inside the component’s lifecycle:
componentWillLoad() {
console.log('Lazy component loaded');
}
The log should appear in the console after the network request for my-lazy-comp.js finishes, indicating the code was loaded on demand.
Trade‑off: when not to lazy load
Lazy loading is beneficial for components that appear below the fold, behind user interactions, or in routes that are not visited immediately. Applying it to components required for the initial view can cause:
- A flash of unstyled content while the chunk is fetched.
- Noticeable delay if the network is slow, degrading perceived performance.
- Potential breakage if the component performs global side‑effects (e.g., mutating
window, registering events) that must run before first paint, because those effects are postponed until the chunk loads.
For such critical components, keep lazy: false (the default) or consider alternative optimizations like code‑splitting at the route level.
Actionable checklist
- Identify components that are not needed for the first paint.
- Add
lazy: trueto their@Componentdecorator. - Run
npm run buildand verify a separate chunk appears inbuild/. - Serve the build and use the Network tab to confirm the chunk loads only when the component is inserted into the DOM.
- If you see a flash or delay for a component that should be immediate, remove the lazy flag or move the component to a higher priority chunk.
By following these steps you can deliberately control bundle size, improve loading times, and avoid the pitfalls of premature lazy loading in a StencilJS application.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.