These four chapters are short and dense, and they are quoted almost verbatim in interviews: "what does Vue escape for you", "how do you optimise a large list", "what is props stability". Learn them as lists.
.prod.js files; with Vite the build command and import.meta.env.MODE handle it; with webpack set NODE_ENV=production.app.config.errorHandler receives component errors; Sentry and Bugsnag offer official Vue integrations.app.config.performance = true, which uses performance.mark) for updates.import(), defineAsyncComponent, and route-level splitting.active to each list item rather than the selected id, so only two items re-render), v-once for never-changing content, v-memo to skip a subtree unless listed values changed, and computed stability (since 3.4 a computed only triggers when its value changes, so return primitives or stable references).vue-virtual-scroller, vue-virtual-scroll-grid, vueuc/VVirtualList), reduce reactivity overhead for large immutable data with shallowRef/shallowReactive, and avoid unnecessary component abstractions (renderless wrappers and higher-order components cost an instance each, which hurts inside big lists).App.vue, targeting #main (tabindex="-1"), focused on route change.header/banner, nav, main, footer/contentinfo, aside/complementary, form, search, role="region") with role attributes for older assistive technology.<label for> or aria-label/aria-labelledby; aria-describedby for instructions; a placeholder is not a label; hide content with a .visually-hidden class rather than display: none when screen readers should still read it; aria-hidden="true" for decorative content; <button type="button"> unless it submits; functional images get meaningful alt.eslint-plugin-vuejs-accessibility.{{ }} interpolation is HTML-escaped; attribute bindings are escaped too (including quotes), so :title="userInput" is safe.v-html or <component :is> with user templates (sanitise, or avoid); URL injection via :href="userUrl" with javascript: schemes (sanitise on the backend or with a library such as sanitize-url); style injection via :style="userStyles" enabling clickjacking with position: fixed (bind only specific properties through an object); JavaScript injection via @click="userProvided" or :onclick (never bind user strings as handlers). SSR adds the risk of leaking server data into the rendered HTML.Props stability and v-memo, the two update-performance techniques people misremember:
<script setup lang="ts">
const items = ref<{ id: number, name: string }[]>([])
const activeId = ref<number>()
</script>
<template>
<!-- ✗ every item re-renders when activeId changes: each receives a new activeId prop -->
<!-- <ListItem v-for="item in items" :key="item.id" :item="item" :active-id="activeId" /> -->
<!-- ✓ props stability: only the two affected items get a changed `active` boolean -->
<ListItem v-for="item in items" :key="item.id" :item="item" :active="item.id === activeId" />
<!-- v-memo: skip the subtree unless the listed values changed -->
<div v-for="item in items" :key="item.id" v-memo="[item.id === activeId]">
<p>{{ item.name }}</p>
</div>
</template>
Style injection, contained:
<!-- ✗ user controls position/z-index: can overlay a login button (clickjacking) -->
<!-- <a :style="userProvidedStyles"> -->
<!-- ✓ only the properties you allow -->
<a :style="{ color: userProvidedColor, background: userProvidedBackground }">
Vue escapes text and attribute values, so <a :href="url"> renders the string safely, but a javascript: URL is still a valid string and will execute when clicked. Escaping is not sanitisation; URLs and any v-html content need their own validation.
activeId prop, count renders with onRenderTriggered, then switch to the active boolean and count again.:href to javascript:alert(1) and click it; then run it through sanitize-url."Vue escapes what it renders: text interpolation is HTML-escaped and attribute bindings are escaped including quotes, so injecting markup through data does not work. It cannot protect against things that are valid as data but dangerous as behaviour: v-html with user content, a javascript: URL in :href, a user-controlled :style object that positions an element over a button, or binding user strings as event handlers. And the first rule is never to compile a user-provided template. Those need sanitisation, allow-lists and, in SSR, care about what server data ends up in the HTML."
Nothing yet. Notes filed here show up on this page and the section overview.
Scaling up — SFC, tooling, routing, state, testing, SSR
What the guide says about single-file components and their CSS features, the recommended toolchain, routing and state management at the Vue level, the testing pyramid it proposes, and the SSR chapter's rules for SSR-friendly code.
TypeScript with Vue
The TypeScript chapters — project setup and tsconfig, typing props, emits, refs, computed, event handlers, provide/inject and template refs with the Composition API, the Options API equivalents, and the utility types.