All quizzesHard
Edge & Streaming
Preview — 3 of 10 questions
How do you use Nitro plugin hooks to intercept and modify server-rendered HTML responses?
javascript
// server/plugins/html-transform.ts
export default defineNitroPlugin((nitroApp) => {
// Hook into HTML rendering — runs after Vue SSR, before sending to client
nitroApp.hooks.hook('render:html', (html, { event }) => {
// html object has: htmlAttrs, head, bodyAttrs, bodyAppended, body
// Inject a nonce for CSP compliance
const nonce = generateNonce()
event.context.cspNonce = nonce
// Add CSP nonce to inline scripts
html.head = html.head.map((tag) =>
tag.replace('<script', `<script nonce="${nonce}"`)
)
// Inject performance mark
html.bodyAppended.push(
`<script nonce="${nonce}">performance.mark('nuxt-end')</script>`
)
})
// Hook into every request
nitroApp.hooks.hook('request', async (event) => {
const start = Date.now()
// Attach request context
event.context.requestId = crypto.randomUUID()
event.context.startTime = start
console.log(`[${event.context.requestId}] ${getMethod(event)} ${getRequestURL(event)}`)
})
// Hook into responses
nitroApp.hooks.hook('afterResponse', (event) => {
const duration = Date.now() - event.context.startTime
console.log(`[${event.context.requestId}] completed in ${duration}ms`)
})
// Hook into errors
nitroApp.hooks.hook('render:response', (response, { event }) => {
// Modify response before sending
if (response.headers) {
response.headers['X-Request-Id'] = event.context.requestId
}
})
})AUse afterEach hook in nuxt.config.ts — it runs after every SSR render
BOverride the _render.ts file in .nuxt/ directory with custom HTML processing
CUse defineNitroPlugin with the render:html hook to intercept and mutate the HTML output before it is sent to the client
DUse a Nuxt plugin with mode: 'server' and return a transformed HTML string
What are the specific constraints when deploying a Nuxt app to edge runtimes (Cloudflare Workers, Vercel Edge)?
javascript
// nuxt.config.ts — deploy to Cloudflare Workers
export default defineNuxtConfig({
nitro: {
preset: 'cloudflare'
}
})
// What works on edge:
// ✅ Web Crypto API (crypto.subtle)
// ✅ fetch() — standard Web API
// ✅ Response, Request, Headers — standard
// ✅ Cloudflare KV, R2, D1 (via bindings)
// ✅ Environment variables via platform bindings
// ✅ TextEncoder/TextDecoder
// What DOESN'T work on Cloudflare Workers:
// ❌ fs/promises — no filesystem
// ❌ path, os — Node.js built-ins
// ❌ child_process — no process spawning
// ❌ net, http, tls — raw TCP not allowed
// ❌ WebSockets (Worker-side, except via CF's WebSocket API)
// server/api/edge-safe.ts — edge-compatible server route
export default defineEventHandler(async (event) => {
// ✅ Use Web Crypto instead of Node crypto
const key = await crypto.subtle.importKey(
'raw',
new TextEncoder().encode('secret'),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
)
const signature = await crypto.subtle.sign(
'HMAC',
key,
new TextEncoder().encode(JSON.stringify({ userId: '123' }))
)
// ✅ Web standard base64
return { token: btoa(String.fromCharCode(...new Uint8Array(signature))) }
})
// nuxt.config.ts — mark dependencies as Node.js-only (exclude from edge bundle)
export default defineNuxtConfig({
nitro: {
preset: 'cloudflare',
rollupConfig: {
external: ['pg', 'ioredis'] // These cannot run on edge — use REST APIs instead
}
}
})AEdge runtimes support all Node.js APIs — they are identical to Node.js servers
BEdge functions cannot access environment variables — use client-side storage instead
CEdge runtimes only support static file serving — no server-side logic is possible
DEdge runtimes run V8 isolates — they lack Node.js built-ins (no fs, net, child_process), have limited CPU time, constrained memory, and require all code to be bundled into a single script
What is streaming SSR and how does it improve perceived performance?
javascript
// Nuxt 3 streaming is handled by Nitro — here's the underlying concept:
// Traditional SSR flow:
// 1. Server waits for ALL async data (useFetch, useAsyncData)
// 2. Renders FULL HTML string
// 3. Sends ENTIRE response at once
// Time to first byte (TTFB) = slowest data source
// Streaming SSR flow:
// 1. Server renders HTML SHELL immediately (header, layout)
// 2. Sends shell to browser → browser starts rendering, loads CSS/JS
// 3. As async data resolves, streams additional HTML chunks
// 4. Browser seamlessly inserts chunks into correct positions
// Nuxt config — enable experimental streaming
export default defineNuxtConfig({
experimental: {
inlineSSRStyles: true // Inline critical CSS for faster FCP
}
})AStreaming SSR splits the JavaScript bundle into chunks that download in parallel
BStreaming compresses the SSR HTML using gzip before transmission
CStreaming SSR sends HTML to the browser progressively as Vue renders each component tree segment — allowing browsers to start rendering and fetching critical resources before the full HTML is ready
DStreaming SSR is the same as ISR — both involve incremental page generation
Sign up free to play
Answer all 10 questions (7 more), see explanations for every answer, and track your score.