PageSourceSearch

https://pitt-wu-blog.vercel.app/assets/js/de63f412.a9ac5cd3.js

js pitt-wu-blog.vercel.app collected 2026-10-03 07:30:14 UTC 7,294 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkdocusaurus_blog=globalThis.webpackChunkdocusaurus_blog||[]).push([[1912],{8292:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"Experience/SSR-SEO/lv2-ssr-implementation","title":"[Lv2] SSR Implementation: Data Fetching and SEO Meta Management","description":"A practical Nuxt SSR implementation pattern for dynamic pages: fetch data on server, render complete HTML, and generate route-specific metadata.","source":"@site/docs/Experience/SSR-SEO/lv2-ssr-implementation.md","sourceDirName":"Experience/SSR-SEO","slug":"/experience/ssr-seo/lv2-ssr-implementation","permalink":"/docs/experience/ssr-seo/lv2-ssr-implementation","draft":false,"unlisted":false,"editUrl":"https://github.com/wuzhe0912/blog-docusaurus/tree/master/docs/Experience/SSR-SEO/lv2-ssr-implementation.md","tags":[{"inline":true,"label":"Experience","permalink":"/docs/tags/experience"},{"inline":true,"label":"Interview","permalink":"/docs/tags/interview"},{"inline":true,"label":"SSR-SEO","permalink":"/docs/tags/ssr-seo"},{"inline":true,"label":"Lv2","permalink":"/docs/tags/lv-2"}],"version":"current","frontMatter":{"title":"[Lv2] SSR Implementation: Data Fetching and SEO Meta Management","slug":"/experience/ssr-seo/lv2-ssr-implementation","tags":["Experience","Interview","SSR-SEO","Lv2"]},"sidebar":"experience","previous":{"title":"[Lv2] Nuxt 3 Lifecycle and Hydration Fundamentals","permalink":"/docs/experience/ssr-seo/lv2-nuxt-lifecycle-hydration"},"next":{"title":"[Lv2] Nuxt 3 Server Features: Server Routes and Dynamic Sitemap","permalink":"/docs/experience/ssr-seo/lv2-nuxt-server-features"}}');var a=t(4848),s=t(8453);const i={title:"[Lv2] SSR Implementation: Data Fetching and SEO Meta Management",slug:"/experience/ssr-seo/lv2-ssr-implementation",tags:["Experience","Interview","SSR-SEO","Lv2"]},c=void 0,o={},l=[{value:"1. Interview focus",id:"1-interview-focus",level:2},{value:"2. SSR data fetching patterns",id:"2-ssr-data-fetching-patterns",level:2},{value:"<code>useFetch</code> for direct API usage",id:"usefetch-for-direct-api-usage",level:3},{value:"<code>useAsyncData</code> for custom logic",id:"useasyncdata-for-custom-logic",level:3},{value:"3. Dynamic head generation",id:"3-dynamic-head-generation",level:2},{value:"4. Error handling and status codes",id:"4-error-handling-and-status-codes",level:2},{value:"5. Performance controls",id:"5-performance-controls",level:2},{value:"6. Production checklist",id:"6-production-checklist",level:2},{value:"Interview-ready summary",id:"interview-ready-summary",level:2}];function d(e){const n={blockquote:"blockquote",code:"code",h2:"h2",h3:"h3",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(n.blockquote,{children:["\n",(0,a.jsx)(n.p,{children:"A practical Nuxt SSR implementation pattern for dynamic pages: fetch data on server, render complete HTML, and generate route-specific metadata."}),"\n"]}),"\n",(0,a.jsx)(n.hr,{}),"\n",(0,a.jsx)(n.h2,{id:"1-interview-focus",children:"1. Interview focus"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"Server-first data fetching strategy"}),"\n",(0,a.jsx)(n.li,{children:"Dynamic metadata from fetched content"}),"\n",(0,a.jsx)(n.li,{children:"Deduplication and caching for performance"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"2-ssr-data-fetching-patterns",children:"2. SSR data fetching patterns"}),"\n",(0,a.jsxs)(n.h3,{id:"usefetch-for-direct-api-usage",children:[(0,a.jsx)(n.code,{children:"useFetch"})," for direct API usage"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-ts",children:"const route = useRoute();\n\nconst { data: product, error } = await useFetch(`/api/products/${route.params.id}`, {\n  key: `product-${route.params.id}`,\n  server: true,\n  lazy: false,\n});\n"})}),"\n",(0,a.jsxs)(n.h3,{id:"useasyncdata-for-custom-logic",children:[(0,a.jsx)(n.code,{children:"useAsyncData"})," for custom logic"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-ts",children:"const { data } = await useAsyncData(`article-${route.params.slug}`, async () => {\n  const article = await $fetch(`/api/articles/${route.params.slug}`);\n  return normalizeArticle(article);\n});\n"})}),"\n",(0,a.jsx)(n.h2,{id:"3-dynamic-head-generation",children:"3. Dynamic head generation"}),"\n",(0,a.jsx)(n.p,{children:"Generate metadata from SSR-fetched content:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-ts",children:"useHead(() => ({\n  title: product.value?.name || 'Product',\n  meta: [\n    { name: 'description', content: product.value?.summary || '' },\n    { property: 'og:title', content: product.value?.name || '' },\n    { property: 'og:description', content: product.value?.summary || '' },\n    { property: 'og:image', content: product.value?.image || '' },\n  ],\n  link: [{ rel: 'canonical', href: `https://example.com/products/${route.params.id}` }],\n}));\n"})}),"\n",(0,a.jsx)(n.h2,{id:"4-error-handling-and-status-codes",children:"4. Error handling and status codes"}),"\n",(0,a.jsx)(n.p,{children:"For SEO-critical pages, return proper response codes."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-ts",children:"if (!product.value) {\n  throw createError({ statusCode: 404, statusMessage: 'Product Not Found' });\n}\n"})}
1),"\n",(0,a.jsx)(n.h2,{id:"5-performance-controls",children:"5. Performance controls"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Deduplicate same request keys"}),"\n",(0,a.jsx)(n.li,{children:"Cache stable responses where possible"}),"\n",(0,a.jsx)(n.li,{children:"Avoid blocking SSR with non-critical API calls"}),"\n",(0,a.jsx)(n.li,{children:"Move user-specific low-priority data to client fetch"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"6-production-checklist",children:"6. Production checklist"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"SSR HTML includes meaningful content before hydration"}),"\n",(0,a.jsx)(n.li,{children:"Page title and description are route-specific"}),"\n",(0,a.jsx)(n.li,{children:"Canonical URL matches public URL"}),"\n",(0,a.jsx)(n.li,{children:"404/410 pages return real status codes"}),"\n",(0,a.jsx)(n.li,{children:"Rendering remains stable under slow API conditions"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"interview-ready-summary",children:"Interview-ready summary"}),"\n",(0,a.jsxs)(n.blockquote,{children:["\n",(0,a.jsx)(n.p,{children:"I fetch SEO-critical content during SSR, derive metadata from that content, and enforce proper status codes. Then I optimize with request deduplication and selective caching to balance quality and speed."}),"\n"]})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>c});var r=t(6540);const a={},s=r.createContext(a);function i(e){const n=r.useContext(s);return r.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.