← Back to Web application starters · project planning pack
See how it helps
Fast Vue interfaces and consistent rendering
Improves slow Vue views by reducing unnecessary work and keeping server-generated pages consistent with the browser’s first render.
vue-performance-ssr
Agents using this skill
When is it useful?
Use when large tables, heavy dialogs or server-rendered pages feel sluggish or change unexpectedly during startup.
What does it help you do?
- Reduces unnecessary component updates and uses suitable handling for large read-only datasets.
- Loads heavy secondary features when needed and keeps large lists manageable.
- Finds mismatched initial content and request-shared state that can affect server-rendered pages.
Try asking this
Improve a Vue product table with thousands of records and a rich editor dialog. Measure updates, defer the editor load and check the initial server-rendered page. Compare table interaction before and after optimization and inspect the initial bundle. The editor loads when needed, while server and client render the same initial content.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Vue Performance & SSR
Keep Vue interfaces fast and predictable by reducing reactivity overhead, stabilizing component props, splitting heavy bundles, and keeping server and client rendering consistent.
1. Reactivity and rendering efficiency
- Keep props stable: avoid passing newly constructed object/array literals or inline values that change every parent render when child updates are expensive. For active-item lists (such as
<ListItem :is-active="item.id === activeId">), pass the boolean:is-activeprop rather than:active-id="activeId", so changingactiveIdre-renders only the 2 affected items instead of all $N$ items. - Avoid deep reactivity on large or opaque data: use
shallowRef()for large arrays of read-only records (hundreds or thousands of rows), geojson/chart datasets, or third-party SDK instances (markRaw()for non-reactive objects stored inside reactive state). v-memoandv-once: in hot list templates where item rendering is expensive, usev-memo="[item.id, item.updatedAt, item.id === selectedId]"to skip virtual DOM diffing when dependencies have not changed. Usev-onceonly for strictly static subtrees.- Large lists: never combine
v-ifandv-foron the same element — pre-filter the list in acomputedproperty. For lists over ~500 visible DOM rows, prefer pagination, windowed rendering or virtual scrolling (vue-virtual-scroller/@tanstack/vue-virtual).
2. Bundle size and async components
- Lazy-load heavy, below-the-fold or modal-only components (rich text editors, chart libraries, PDF viewers, code editors) with
defineAsyncComponent(() => import('./HeavyEditor.vue'))and provide a lightweight loading/error fallback. - Import specific utilities and icons rather than pulling entire barrel bundles into initial routes when tree-shaking is not guaranteed.
3. SSR and hydration mismatch prevention
- When the app uses SSR (Nuxt, Inertia SSR, or custom
createSSRApp), the initial client render must produce identical DOM structure and text to the server HTML:- Never read
window,document,localStorage,navigatoror viewport dimensions inside<script setup>top-level execution orcomputedproperties used during initial render — defer browser-only reads toonMounted(). - Avoid non-deterministic values during render (
Math.random(),new Date()formatted with client-local timezone, auto-incrementing counters); useuseId()(Vue 3.5+) for SSR-safe accessible element IDs. - Keep valid HTML nesting (
<div>inside<p>,<tbody>omitted in<table>, or interactive<button>nested inside<button>/<a>causes the browser HTML parser to repair the DOM and breaks hydration).
- Never read
- Avoid cross-request state pollution: in SSR, module-level
ref()orreactive()singletons are shared across all incoming server requests and leak user data! Create app, router and Pinia instances per request, and keep state inside components, Pinia stores or request-scopedprovide/inject.
Before you finish
- Large read-only datasets or third-party instances use
shallowRef/markRawwhere appropriate. - List items receive stable
:keys and primitive/stable props that avoid re-rendering the entire list on selection change. - Heavy modal or secondary libraries are lazy-loaded with
defineAsyncComponentor route-level code splitting. - In SSR apps, no browser globals, random IDs or module-level mutable singletons run during server render.
Included files 2
LICENSE.txtSKILL.md
