Performance + Bundle-Size Playbook
Studio adds runtime weight to your app. @contentstack/studio-react is a few hundred KB compressed, and @contentstack/live-preview-utils adds more. For most sites that’s fine. It’s the cost of authorability. For weight-sensitive surfaces (landing pages, AMP-style targets, edge-deployed routes) you can drop the runtime cost substantially with a small set of patterns.
Do It With a Skill
register-component registers lazily by default, which is the single biggest lever on bundle size here.
curl -fsSL https://studio-documentation.contentstackapps.com/install.sh | sh
The rest of this page is measurement and judgement, and no skill substitutes for profiling your own build.
The Model
Studio’s runtime weight has three layers:
- Authoring weight: the canvas iframe, the section preview machinery, post-message channels. Loaded by <StudioCanvas /> on the canvas route only.
- Visitor weight: what <StudioComponent /> ships to real visitor pages. Lighter than <StudioCanvas />, but still meaningfully bigger than a hand-coded render.
- Component weight: your own registered components, plus any dependencies they pull in.
Layer 1 only loads on the canvas route. Stop worrying about that one. It’s not in visitor pages. Layers 2 and 3 are where the win is.
Recommended Patterns
Lazy-register heavy components
registerLazyComponent lets Studio defer the import until the component is actually placed on a page:
import { registerLazyComponent } from "@contentstack/studio-react";
registerLazyComponent(
{
type: "video-player",
displayName: "Video Player",
props: { /* … */ },
},
() => import("./components/VideoPlayer").then(m => m.default), // only fetched when used
);
Use this for anything > 50 KB minified or that pulls in a heavy dependency (a chart library, a video player, a rich text renderer). Pages that don’t use the component pay zero weight for it.
Code-split per-route
Studio’s <StudioComponent /> should not be in your shared bundle. Mount it from a route file that’s automatically code-split by your framework (Next.js App Router page.tsx, Remix route files, Astro pages). The framework’s per-route splitting handles this for you. Just don’t accidentally import @contentstack/studio-react from a top-level layout.
Server-side resolution where possible
csStudio.fetchCompositionData(queryOptions, options) (the SSR path) returns the full spec server-side. Render the result to HTML at request time. Ship hydration data only. The CSR useCompositionData hook is convenient but adds runtime cost. Use it only when SSR isn’t an option (auth-gated content, runtime-only data).
See configure-csr-vs-ssr for the wiring.
Don’t ship Live Preview to visitors
@contentstack/live-preview-utils is for editors, not visitors. Gate ContentstackLivePreview.init() behind a check:
if (process.env.NEXT_PUBLIC_ENABLE_LIVE_PREVIEW === "true") {
ContentstackLivePreview.init({ /* … */ });
}
Set the env var only in your preview/staging deployment. Production visitor pages never load the Live Preview channel, never pay its weight.
Measure before optimizing
Run a Next/Astro bundle analyzer or source-map-explorer against your production build. Confirm the actual weight Studio adds before guessing. Most of the time it’s smaller than you think. Sometimes a transitive dep blows up: measurement tells you which.
Patterns to Avoid
| Pattern | Why it bites |
|---|---|
| Importing @contentstack/studio-react from a top-level layout | Defeats code-splitting. Every route now ships Studio runtime |
| Eagerly registering every component up front | Defeats registerLazyComponent. Defeats per-route splitting |
| Bundling Live Preview into production builds | Editor-only weight in every visitor’s bundle |
| Using CSR useCompositionData for content that could be fetched server-side | Adds an extra round-trip + runtime cost. SSR is faster + lighter |
| Pre-loading all sections via linked_sections for SSR | Pulls down sections the route may never render. Only the sections in the composition’s UI tree are needed |
What’s Still Unsolved
- Tree-shaking Studio’s internal renderer. Some internal Studio modules can’t be tree-shaken effectively today. If your bundle analysis shows @contentstack/studio-react larger than expected, file an issue with your analyzer output. The SDK team prioritizes these.
- Edge-runtime size limits. Studio currently exceeds the Vercel Edge / Cloudflare Workers 1 MB limit on some configurations. For edge-deployed routes, use the Node runtime. See Production deployment edges.
See Also
- Configure CSR vs SSR: pick the right render path
- Optimizing load: lazy registration + bundle reference
- Production deployment edges: edge runtime + ISR considerations