Next.js 数据获取:使用 getServerSideProps 进行服务器端渲染 - 实践
<style>pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; line-height: 1.6 !important; padding: 16px !important; margin: 16px 0 !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; tab-size: 4 !important; -moz-tab-size: 4 !important; max-width: 100% !important; box-sizing: border-box !important }code { font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; overflow-wrap: normal !important; display: inline !important; background: rgba(0, 0, 0, 0) !important; border: none !important; padding: 0 !important; margin: 0 !important; line-height: inherit !important }
pre code { background: rgba(0, 0, 0, 0) !important; border: 0 !important; border-radius: 0 !important; display: block !important; line-height: 1.6 !important; margin: 0 !important; max-width: none !important; overflow: visible !important; padding: 0 !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; color: inherit !important }
.token.comment, .token.prolog, .token.doctype, .token.cdata { color: rgba(112, 128, 144, 1) !important; font-style: italic !important }
.token.punctuation { color: rgba(153, 153, 153, 1) !important }
.token.atrule, .token.attr-value, .token.keyword { color: rgba(0, 119, 170, 1) !important; font-weight: bold !important }
.token.function, .token.class-name { color: rgba(221, 74, 104, 1) !important; font-weight: bold !important }
.token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted { color: rgba(102, 153, 0, 1) !important }
.token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: rgba(153, 0, 85, 1) !important }
.cnblogs-markdown pre, .cnblogs-post-body pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; padding: 16px !important; margin: 16px 0 !important }
pre, pre, pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important }</style>
<style>pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; line-height: 1.6 !important; padding: 16px !important; margin: 16px 0 !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; tab-size: 4 !important; -moz-tab-size: 4 !important; max-width: 100% !important; box-sizing: border-box !important }
code { font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; overflow-wrap: normal !important; display: inline !important; background: rgba(0, 0, 0, 0) !important; border: none !important; padding: 0 !important; margin: 0 !important; line-height: inherit !important }
pre code { background: rgba(0, 0, 0, 0) !important; border: 0 !important; border-radius: 0 !important; display: block !important; line-height: 1.6 !important; margin: 0 !important; max-width: none !important; overflow: visible !important; padding: 0 !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; color: inherit !important }
.token.comment, .token.prolog, .token.doctype, .token.cdata { color: rgba(112, 128, 144, 1) !important; font-style: italic !important }
.token.punctuation { color: rgba(153, 153, 153, 1) !important }
.token.atrule, .token.attr-value, .token.keyword { color: rgba(0, 119, 170, 1) !important; font-weight: bold !important }
.token.function, .token.class-name { color: rgba(221, 74, 104, 1) !important; font-weight: bold !important }
.token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted { color: rgba(102, 153, 0, 1) !important }
.token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: rgba(153, 0, 85, 1) !important }
.cnblogs-markdown pre, .cnblogs-post-body pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; padding: 16px !important; margin: 16px 0 !important }
pre, pre, pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important }</style><div class="markdown_views prism-atom-one-light" id="content_views"><svg style="display: none" xmlns="http://www.w3.org/2000/svg"><path d="M5,0 0,2.5 5,5z" id="raphael-marker-block" stroke-linecap="round" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0)"></path></svg><h5>关键要点</h5><ul><li><strong>服务器端渲染(SSR)</strong> 是 Next.js 的核心功能,通过 <code>getServerSideProps</code> 在每次请求时动态生成页面,适合实时数据场景。</li><li><code>getServerSideProps</code> 运行于服务器端,用于获取动态数据并传递给页面组件,优化 SEO 和用户体验。</li><li>支持动态路由、环境变量和错误处理,适用于数据频繁变化的场景。</li><li>涵盖 SSR 和 <code>getServerSideProps</code> 的工作原理、使用场景、实现方法、优化技巧和常见问题解决方案。</li><li>提供详细代码示例和最佳实践,适合初学者和进阶开发者。</li></ul><h5>为什么需要这篇文章?</h5><p>服务器端渲染(Server-Side Rendering, SSR)是 Next.js 的重要特性,通过在每次请求时生成页面,确保内容实时更新,特别适合需要动态数据(如用户仪表板、实时库存)的场景。<code>getServerSideProps</code> 是 Pages Router(<code>pages/</code> 目录)中实现 SSR 的核心 API,允许开发者在服务器端获取数据并传递给页面组件。掌握 <code>getServerSideProps</code> 的使用方法,对于构建动态、SEO 友好的 Web 应用至关重要。本文将深入讲解 SSR 和 <code>getServerSideProps</code> 的工作原理,展示其在 Pages Router 中的实现方法,并提供实用示例和优化建议。</p><h5>目标</h5><ul><li>解释服务器端渲染和 <code>getServerSideProps</code> 的工作原理。</li><li>展示如何在 Pages Router 中使用 <code>getServerSideProps</code> 实现动态页面。</li><li>结合动态路由和环境变量处理复杂场景。</li><li>提供性能优化、错误处理和大型项目组织实践。</li><li>帮助开发者选择合适的 SSR 策略并构建高效应用。</li></ul><hr><h3>1. 引言</h3><p>Next.js 是一个基于 React 的全栈框架,其服务器端渲染(Server-Side Rendering, SSR)功能通过在每次请求时动态生成页面,提供了实时数据更新和 SEO 优化的能力。<code>getServerSideProps</code> 是 Next.js Pages Router(<code>pages/</code> 目录)中的核心 API,用于在服务器端获取数据并将其作为 props 传递给页面组件。与静态生成(SSG)不同,SSR 适合数据频繁变化或需要用户特定内容的场景,如用户仪表板、实时搜索结果或电商库存页面。</p><p><code>getServerSideProps</code> 在每次请求时运行,允许开发者直接访问服务器资源(如数据库、API)并生成动态 HTML。本文将详细讲解 SSR 和 <code>getServerSideProps</code> 的工作原理,展示其在 Pages Router 中的使用方法,结合动态路由、环境变量和错误处理,展示如何构建动态页面,并通过代码示例、最佳实践和常见问题解决方案,帮助开发者掌握这一功能。</p><p>通过本文,您将学会:</p><ul><li>理解服务器端渲染和 <code>getServerSideProps</code> 的运行机制。</li><li>在 Pages Router 中使用 <code>getServerSideProps</code> 实现动态页面。</li><li>结合动态路由处理个性化内容。</li><li>优化 SSR 性能、处理错误并组织大型项目的数据获取逻辑。</li><li>选择合适的 SSR 策略并构建高效、可扩展的应用。</li></ul><h3>2. 服务器端渲染与 getServerSideProps 的基本原理</h3><h4>2.1 服务器端渲染(SSR)概述</h4><p>服务器端渲染是指在每次用户请求时,服务器动态生成 HTML 并返回给浏览器。SSR 的优势包括:</p><ul><li><strong>实时数据</strong>:每次请求获取最新数据,适合动态内容。</li><li><strong>SEO 友好</strong>:生成完整的 HTML,易于搜索引擎爬取。</li><li><strong>个性化内容</strong>:根据用户身份(如 cookies、认证令牌)生成页面。</li><li><strong>用户体验</strong>:首屏内容直接显示,无需客户端加载。</li></ul><p>SSR 的缺点是增加服务器负载,适合数据频繁变化或需要实时更新的场景。Next.js 通过 <code>getServerSideProps</code> 实现 SSR。</p><h4>2.2 getServerSideProps 的工作原理</h4><p><code>getServerSideProps</code> 是一个异步函数,运行于服务器端,在每次请求时执行,用于获取数据并返回 props。</p><ul><li><strong>运行环境</strong>:服务器端(每次请求)。</li><li><strong>上下文参数</strong>:<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token punctuation">{</span>
params<span class="token punctuation">,</span> <span class="token comment">// 动态路由参数</span>
req<span class="token punctuation">,</span> <span class="token comment">// HTTP 请求对象</span>
res<span class="token punctuation">,</span> <span class="token comment">// HTTP 响应对象</span>
query<span class="token punctuation">,</span> <span class="token comment">// 查询字符串</span>
preview<span class="token punctuation">,</span> <span class="token comment">// 预览模式标志</span>
previewData <span class="token comment">// 预览模式数据</span>
<span class="token punctuation">}</span></code></pre>
</li><li><strong>返回值</strong>:<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token punctuation">{</span>
props<span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token comment">// 传递给页面组件的 props</span>
notFound<span class="token operator">?</span><span class="token operator">:</span> boolean<span class="token punctuation">,</span> <span class="token comment">// 触发 404</span>
redirect<span class="token operator">?</span><span class="token operator">:</span> <span class="token punctuation">{</span> destination<span class="token operator">:</span> string<span class="token punctuation">,</span> permanent<span class="token operator">:</span> boolean
<span class="token punctuation">}</span> <span class="token comment">// 重定向</span>
<span class="token punctuation">}</span></code></pre>
</li><li><strong>限制</strong>:
<ul><li>仅在 Pages Router 的页面文件中使用(<code>pages/*.js</code>)。</li><li>不能在组件或客户端代码中使用。</li><li>无法访问浏览器 API(如 <code>window</code>)。</li></ul></li></ul><h4>2.3 与其他数据获取方法的比较</h4><table><thead><tr><th><strong>方法</strong></th><th><strong>运行时间</strong></th><th><strong>适用场景</strong></th><th><strong>优点</strong></th><th><strong>缺点</strong></th></tr></thead><tbody><tr><td><code>getServerSideProps</code></td><td>请求时</td><td>动态内容、实时数据</td><td>实时更新、SEO 友好</td><td>增加服务器负载</td></tr><tr><td><code>getStaticProps</code></td><td>构建时</td><td>静态内容、SEO 优先</td><td>高性能、低服务器负载</td><td>动态内容需 ISR 或重新构建</td></tr><tr><td><code>getInitialProps</code></td><td>构建时/请求时</td><td>兼容旧项目</td><td>灵活性高</td><td>性能较差,已不推荐</td></tr><tr><td>客户端获取(如 SWR)</td><td>客户端运行时</td><td>交互式 UI、动态更新</td><td>适合客户端交互</td><td>SEO 较差,增加客户端负担</td></tr></tbody></table><h3>3. 使用 getServerSideProps 实现服务器端渲染</h3><p><code>getServerSideProps</code> 在 Pages Router 中用于生成动态页面,适合实时数据场景。</p><h4>3.1 基本使用</h4><ul><li><p><strong>项目结构</strong>:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code>pages/
├── index.js # /
├── dashboard.js # /dashboard</code></pre>
</li><li><p><strong>代码示例</strong>(<code>pages/dashboard.js</code>):</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token parameter">context</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 模拟获取用户数据</span>
<span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token string">'https://api.example.com/user'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
headers<span class="token operator">:</span> <span class="token punctuation">{</span>
cookie<span class="token operator">:</span> context<span class="token punctuation">.</span>req<span class="token punctuation">.</span>headers<span class="token punctuation">.</span>cookie <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> user <span class="token operator">=</span> <span class="token keyword">await</span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
props<span class="token operator">:</span> <span class="token punctuation">{</span>
user<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Dashboard</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> user
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>main className<span class="token operator">=</span><span class="token string">"flex min-h-screen flex-col items-center justify-center p-8"</span><span class="token operator">></span>
<span class="token operator"><</span>h1 className<span class="token operator">=</span><span class="token string">"text-4xl font-bold"</span><span class="token operator">></span>用户仪表板<span class="token operator"><</span>
<span class="token operator">/</span>h1<span class="token operator">></span>
<span class="token operator"><</span>p<span class="token operator">></span>欢迎<span class="token punctuation">,</span> <span class="token punctuation">{</span>user<span class="token punctuation">.</span>name
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>p<span class="token operator">></span>
<span class="token operator"><</span>p<span class="token operator">></span>邮箱<span class="token operator">:</span> <span class="token punctuation">{</span>user<span class="token punctuation">.</span>email
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>p<span class="token operator">></span>
<span class="token operator"><</span>
<span class="token operator">/</span>main<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li><li><p><strong>效果</strong>:</p><ul><li>每次请求时从 API 获取用户数据,生成动态 HTML。</li><li>页面显示用户特定内容,支持 SEO。</li></ul></li></ul><h4>3.2 处理错误和 404</h4><ul><li><p><strong>代码示例</strong>(<code>pages/profile/.js</code>):</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> params
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://api.example.com/users/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>params<span class="token punctuation">.</span>id
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> user <span class="token operator">=</span> <span class="token keyword">await</span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
notFound<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token comment">// 触发 404</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
props<span class="token operator">:</span> <span class="token punctuation">{</span>
user<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Profile</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> user
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>main className<span class="token operator">=</span><span class="token string">"p-8"</span><span class="token operator">></span>
<span class="token operator"><</span>h1 className<span class="token operator">=</span><span class="token string">"text-4xl font-bold"</span><span class="token operator">></span>
<span class="token punctuation">{</span>user<span class="token punctuation">.</span>name
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>h1<span class="token operator">></span>
<span class="token operator"><</span>p<span class="token operator">></span>邮箱<span class="token operator">:</span> <span class="token punctuation">{</span>user<span class="token punctuation">.</span>email
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>p<span class="token operator">></span>
<span class="token operator"><</span>
<span class="token operator">/</span>main<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li><li><p><strong>效果</strong>:</p><ul><li>如果用户不存在,页面返回 404。</li></ul></li></ul><h4>3.3 重定向</h4><ul><li><p><strong>代码示例</strong>:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> params<span class="token punctuation">,</span> req
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> user <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetchUser</span><span class="token punctuation">(</span>params<span class="token punctuation">.</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>user<span class="token punctuation">.</span>isAuthenticated<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
redirect<span class="token operator">:</span> <span class="token punctuation">{</span>
destination<span class="token operator">:</span> <span class="token string">'/login'</span><span class="token punctuation">,</span>
permanent<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 临时重定向</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
props<span class="token operator">:</span> <span class="token punctuation">{</span> user
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li><li><p><strong>效果</strong>:</p><ul><li>未认证用户重定向到登录页面。</li></ul></li></ul><h4>3.4 访问请求上下文</h4><p><code>getServerSideProps</code> 可通过上下文访问请求信息(如 cookies、查询参数)。</p><ul><li><p><strong>代码示例</strong>:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> req<span class="token punctuation">,</span> query
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> token <span class="token operator">=</span> req<span class="token punctuation">.</span>cookies<span class="token punctuation">.</span>token <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> searchTerm <span class="token operator">=</span> query<span class="token punctuation">.</span>search <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://api.example.com/search?q=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>searchTerm
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
headers<span class="token operator">:</span> <span class="token punctuation">{</span> Authorization<span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Bearer </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> results <span class="token operator">=</span> <span class="token keyword">await</span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
props<span class="token operator">:</span> <span class="token punctuation">{</span>
results<span class="token punctuation">,</span>
searchTerm<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Search</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> results<span class="token punctuation">,</span> searchTerm
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>main className<span class="token operator">=</span><span class="token string">"p-8"</span><span class="token operator">></span>
<span class="token operator"><</span>h1 className<span class="token operator">=</span><span class="token string">"text-4xl font-bold"</span><span class="token operator">></span>搜索<span class="token operator">:</span> <span class="token punctuation">{</span>searchTerm
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>h1<span class="token operator">></span>
<span class="token operator"><</span>ul<span class="token operator">></span>
<span class="token punctuation">{</span>results<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">item</span><span class="token punctuation">)</span> <span class="token operator">=></span>
<span class="token punctuation">(</span>
<span class="token operator"><</span>li key<span class="token operator">=</span><span class="token punctuation">{</span>item<span class="token punctuation">.</span>id
<span class="token punctuation">}</span><span class="token operator">></span>
<span class="token punctuation">{</span>item<span class="token punctuation">.</span>title
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>li<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token operator"><</span>
<span class="token operator">/</span>ul<span class="token operator">></span>
<span class="token operator"><</span>
<span class="token operator">/</span>main<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li><li><p><strong>效果</strong>:</p><ul><li>根据查询参数和 cookies 获取搜索结果,生成动态页面。</li></ul></li></ul><h3>4. 结合动态路由</h3><p><code>getServerSideProps</code> 支持动态路由,通过 <code>params</code> 获取路由参数。</p><ul><li><p><strong>项目结构</strong>:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code>pages/
├── products/
│ ├── .js # /products/:id</code></pre>
</li><li><p><strong>代码示例</strong>(<code>pages/products/.js</code>):</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> params
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://api.example.com/products/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>params<span class="token punctuation">.</span>id
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> product <span class="token operator">=</span> <span class="token keyword">await</span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>product<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> notFound<span class="token operator">:</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
props<span class="token operator">:</span> <span class="token punctuation">{</span>
product<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Product</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> product
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>main className<span class="token operator">=</span><span class="token string">"p-8"</span><span class="token operator">></span>
<span class="token operator"><</span>h1 className<span class="token operator">=</span><span class="token string">"text-4xl font-bold"</span><span class="token operator">></span>
<span class="token punctuation">{</span>product<span class="token punctuation">.</span>name
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>h1<span class="token operator">></span>
<span class="token operator"><</span>p<span class="token operator">></span>价格<span class="token operator">:</span> <span class="token punctuation">{</span>product<span class="token punctuation">.</span>price
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>p<span class="token operator">></span>
<span class="token operator"><</span>p<span class="token operator">></span>描述<span class="token operator">:</span> <span class="token punctuation">{</span>product<span class="token punctuation">.</span>description
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>p<span class="token operator">></span>
<span class="token operator"><</span>
<span class="token operator">/</span>main<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li><li><p><strong>效果</strong>:</p><ul><li>每次请求 <code>/products/123</code> 时,服务器动态获取产品数据并渲染页面。</li></ul></li></ul><h3>5. 优化与配置</h3><h4>5.1 性能优化</h4><ul><li><p><strong>缓存响应</strong>:</p><ul><li>使用 HTTP 缓存头或 CDN 缓存:<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> res
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token string">'https://api.example.com/data'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
headers<span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token string">'Cache-Control'</span><span class="token operator">:</span> <span class="token string">'s-maxage=60, stale-while-revalidate'</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=></span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 设置响应缓存</span>
res<span class="token punctuation">.</span><span class="token function">setHeader</span><span class="token punctuation">(</span><span class="token string">'Cache-Control'</span><span class="token punctuation">,</span> <span class="token string">'s-maxage=60, stale-while-revalidate'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> props<span class="token operator">:</span> <span class="token punctuation">{</span> data
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li></ul></li><li><p><strong>减少数据请求</strong>:</p><ul><li>合并多个 API 调用:<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>user<span class="token punctuation">,</span> settings<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">await</span> Promise<span class="token punctuation">.</span><span class="token function">all</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
<span class="token function">fetch</span><span class="token punctuation">(</span><span class="token string">'https://api.example.com/user'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=></span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token function">fetch</span><span class="token punctuation">(</span><span class="token string">'https://api.example.com/settings'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=></span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
props<span class="token operator">:</span> <span class="token punctuation">{</span> user<span class="token punctuation">,</span> settings
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li></ul></li><li><p><strong>客户端缓存</strong>:</p><ul><li>结合客户端数据获取(如 SWR)减少重复请求:<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">import</span> useSWR <span class="token keyword">from</span> <span class="token string">'swr'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">fetcher</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token operator">=></span>
<span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=></span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Page</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> initialData
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> data
<span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useSWR</span><span class="token punctuation">(</span><span class="token string">'/api/data'</span><span class="token punctuation">,</span> fetcher<span class="token punctuation">,</span> <span class="token punctuation">{</span> initialData
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token operator"><</span>div<span class="token operator">></span>
<span class="token punctuation">{</span>data<span class="token punctuation">.</span>message
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>div<span class="token operator">></span>
<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li></ul></li></ul><h4>5.2 环境变量</h4><p>为数据获取配置 API 端点:</p><ul><li><strong>.env.local</strong>:<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code>API_URL=https://api.example.com</code></pre>
</li><li><strong>使用</strong>:<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">API_URL</span>
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/data</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token keyword">await</span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> props<span class="token operator">:</span> <span class="token punctuation">{</span> data
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li></ul><h4>5.3 错误处理</h4><ul><li><p><strong>捕获异常</strong>:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token string">'https://api.example.com/data'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token keyword">await</span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> props<span class="token operator">:</span> <span class="token punctuation">{</span> data
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">'获取数据失败:'</span><span class="token punctuation">,</span> error<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> notFound<span class="token operator">:</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
</li><li><p><strong>自定义错误页面</strong>:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetchData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>data<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
redirect<span class="token operator">:</span> <span class="token punctuation">{</span>
destination<span class="token operator">:</span> <span class="token string">'/error'</span><span class="token punctuation">,</span>
permanent<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> props<span class="token operator">:</span> <span class="token punctuation">{</span> data
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li></ul><h3>6. 使用场景</h3><h4>6.1 用户仪表板</h4><ul><li><strong>需求</strong>:根据用户身份渲染仪表板。</li><li><strong>代码示例</strong>(<code>pages/dashboard.js</code>):<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> req
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> token <span class="token operator">=</span> req<span class="token punctuation">.</span>cookies<span class="token punctuation">.</span>token<span class="token punctuation">;</span>
<span class="token keyword">const</span> user <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://api.example.com/user</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
headers<span class="token operator">:</span> <span class="token punctuation">{</span> Authorization<span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Bearer </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=></span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
redirect<span class="token operator">:</span> <span class="token punctuation">{</span> destination<span class="token operator">:</span> <span class="token string">'/login'</span><span class="token punctuation">,</span> permanent<span class="token operator">:</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
props<span class="token operator">:</span> <span class="token punctuation">{</span> user
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Dashboard</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> user
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>main className<span class="token operator">=</span><span class="token string">"p-8"</span><span class="token operator">></span>
<span class="token operator"><</span>h1<span class="token operator">></span>欢迎<span class="token punctuation">,</span> <span class="token punctuation">{</span>user<span class="token punctuation">.</span>name
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>h1<span class="token operator">></span>
<span class="token operator"><</span>p<span class="token operator">></span>您的角色<span class="token operator">:</span> <span class="token punctuation">{</span>user<span class="token punctuation">.</span>role
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>p<span class="token operator">></span>
<span class="token operator"><</span>
<span class="token operator">/</span>main<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li></ul><h4>6.2 实时搜索结果</h4><ul><li><strong>需求</strong>:根据查询参数显示搜索结果。</li><li><strong>代码示例</strong>(<code>pages/search.js</code>):<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> query
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> searchTerm <span class="token operator">=</span> query<span class="token punctuation">.</span>q <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> results <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://api.example.com/search?q=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>searchTerm
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=></span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
props<span class="token operator">:</span> <span class="token punctuation">{</span>
results<span class="token punctuation">,</span>
searchTerm<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Search</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> results<span class="token punctuation">,</span> searchTerm
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>main className<span class="token operator">=</span><span class="token string">"p-8"</span><span class="token operator">></span>
<span class="token operator"><</span>h1<span class="token operator">></span>搜索<span class="token operator">:</span> <span class="token punctuation">{</span>searchTerm
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>h1<span class="token operator">></span>
<span class="token operator"><</span>ul<span class="token operator">></span>
<span class="token punctuation">{</span>results<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">item</span><span class="token punctuation">)</span> <span class="token operator">=></span>
<span class="token punctuation">(</span>
<span class="token operator"><</span>li key<span class="token operator">=</span><span class="token punctuation">{</span>item<span class="token punctuation">.</span>id
<span class="token punctuation">}</span><span class="token operator">></span>
<span class="token punctuation">{</span>item<span class="token punctuation">.</span>title
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>li<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token operator"><</span>
<span class="token operator">/</span>ul<span class="token operator">></span>
<span class="token operator"><</span>
<span class="token operator">/</span>main<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li></ul><h4>6.3 动态产品页面</h4><ul><li><strong>需求</strong>:为电商网站生成产品详情页。</li><li><strong>代码示例</strong>(<code>pages/products/.js</code>):<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> params
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> product <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://api.example.com/products/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>params<span class="token punctuation">.</span>id
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=></span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>product<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> notFound<span class="token operator">:</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
props<span class="token operator">:</span> <span class="token punctuation">{</span> product
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Product</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> product
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>main className<span class="token operator">=</span><span class="token string">"p-8"</span><span class="token operator">></span>
<span class="token operator"><</span>h1<span class="token operator">></span>
<span class="token punctuation">{</span>product<span class="token punctuation">.</span>name
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>h1<span class="token operator">></span>
<span class="token operator"><</span>p<span class="token operator">></span>价格<span class="token operator">:</span> <span class="token punctuation">{</span>product<span class="token punctuation">.</span>price
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>p<span class="token operator">></span>
<span class="token operator"><</span>
<span class="token operator">/</span>main<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li></ul><h3>7. 最佳实践</h3><ul><li><p><strong>模块化数据获取</strong>:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token comment">// lib/fetchData.js</span>
<span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fetchUser</span><span class="token punctuation">(</span><span class="token parameter">id</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://api.example.com/users/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>id
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li><li><p><strong>类型安全</strong>(TypeScript):</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">interface</span> <span class="token class-name">User</span> <span class="token punctuation">{</span>
id<span class="token operator">:</span> string<span class="token punctuation">;</span>
name<span class="token operator">:</span> string<span class="token punctuation">;</span>
email<span class="token operator">:</span> string<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getServerSideProps</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> params
<span class="token punctuation">}</span><span class="token operator">:</span> <span class="token punctuation">{</span> params<span class="token operator">:</span> <span class="token punctuation">{</span> id<span class="token operator">:</span> string
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> user<span class="token operator">:</span> User <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetchUser</span><span class="token punctuation">(</span>params<span class="token punctuation">.</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> props<span class="token operator">:</span> <span class="token punctuation">{</span> user
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li><li><p><strong>性能优化</strong>:</p><ul><li>使用 HTTP 缓存或 CDN。</li><li>合并 API 请求。</li><li>结合客户端缓存(如 SWR)。</li></ul></li><li><p><strong>SEO 优化</strong>:</p><ul><li>使用 <code>Head</code> 组件设置元数据:<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token keyword">import</span> Head <span class="token keyword">from</span> <span class="token string">'next/head'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Page</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> data
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>
<span class="token operator">></span>
<span class="token operator"><</span>Head<span class="token operator">></span>
<span class="token operator"><</span>title<span class="token operator">></span>
<span class="token punctuation">{</span>data<span class="token punctuation">.</span>title
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>title<span class="token operator">></span>
<span class="token operator"><</span>meta name<span class="token operator">=</span><span class="token string">"description"</span> content<span class="token operator">=</span><span class="token punctuation">{</span>data<span class="token punctuation">.</span>description
<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span>
<span class="token operator"><</span>
<span class="token operator">/</span>Head<span class="token operator">></span>
<span class="token operator"><</span>main<span class="token operator">></span>
<span class="token operator"><</span>h1<span class="token operator">></span>
<span class="token punctuation">{</span>data<span class="token punctuation">.</span>title
<span class="token punctuation">}</span><span class="token operator"><</span>
<span class="token operator">/</span>h1<span class="token operator">></span>
<span class="token operator"><</span>
<span class="token operator">/</span>main<span class="token operator">></span>
<span class="token operator"><</span>
<span class="token operator">/</span><span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li></ul></li></ul><h3>8. 常见问题及解决方案</h3><table><thead><tr><th><strong>问题</strong></th><th><strong>解决方案</strong></th></tr></thead><tbody><tr><td><code>getServerSideProps</code> 未执行</td><td>确保函数在页面文件中导出,检查文件名是否正确。</td></tr><tr><td>数据未实时更新</td><td>验证 API 端点和数据源,确保请求正确。</td></tr><tr><td>服务器负载过高</td><td>使用缓存(HTTP 缓存或 CDN),或考虑 SSG/ISR。</td></tr><tr><td>API 请求失败</td><td>添加错误处理,使用 <code>try-catch</code> 或 <code>notFound</code>。</td></tr><tr><td>动态路由参数丢失</td><td>检查 <code>params</code> 是否正确传递,验证路由配置。</td></tr></tbody></table><h3>9. 大型项目中的组织</h3><p>对于大型项目,推荐以下结构:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code>pages/
├── dashboard.js
├── products/
│ ├── .js
├── lib/
│ ├── fetchData.js
├── styles/
│ ├── globals.css</code></pre>
<ul><li><p><strong>模块化数据获取</strong>:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-js"><span class="token comment">// lib/fetchData.js</span>
<span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fetchProduct</span><span class="token punctuation">(</span><span class="token parameter">id</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">API_URL</span>
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/products/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>id
<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li><li><p><strong>全局样式</strong>:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-css"><span class="token comment">/* styles/globals.css */</span>
<span class="token selector">body</span> <span class="token punctuation">{</span>
<span class="token property">margin</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token property">font-family</span><span class="token punctuation">:</span> Arial<span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li><li><p><strong>类型定义</strong>:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-ts"><span class="token comment">// types/product.ts</span>
<span class="token keyword">export</span> <span class="token keyword">interface</span> <span class="token class-name">Product</span> <span class="token punctuation">{</span>
id<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
price<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</li></ul><h3>10. 下一步</h3><p>掌握 <code>getServerSideProps</code> 后,您可以:</p><ul><li>结合客户端数据获取(如 SWR)优化交互。</li><li>集成认证系统(如 NextAuth.js)支持用户特定内容。</li><li>配置 CDN 优化 SSR 性能。</li><li>部署应用并测试动态页面和 SEO。</li></ul><h3>总结</h3><p>Next.js 的 <code>getServerSideProps</code> 是实现服务器端渲染的核心工具,通过在每次请求时获取数据并生成动态 HTML,提供了实时更新和 SEO 优势。本文通过详细代码示例,讲解了 <code>getServerSideProps</code> 的工作原理和使用方法,结合动态路由、环境变量和错误处理展示了其灵活性。性能优化、错误处理和最佳实践进一步帮助开发者构建高效、可扩展的应用。掌握 <code>getServerSideProps</code> 将为您的 Next.js 开发提供强大支持,助力构建动态、用户友好的 Web 应用。</p></div><br><br>
来源:https://www.cnblogs.com/yfceshi/p/19030665
頁:
[1]