Next.js 14:如何在CSR页面加载构建时生成的SG页面
实现方案(Next.js 14)
1. 先确保静态生成(SG)页面完成预构建
在app/SG/[id]/product/page.tsx中配置静态生成参数,让Next.js在构建阶段预先生成所有需要的静态页面:
// app/SG/[id]/product/page.tsx export async function generateStaticParams() { // 这里返回所有要预生成的id列表,可从数据库、配置文件等渠道获取 return [ { id: '1' }, { id: '2' }, { id: '3' } ]; } export default function ProductPage({ params }: { params: { id: string } }) { return ( <div className="product-content"> <h1>产品 {params.id}</h1> <p>这是静态生成的产品 {params.id} 详情内容</p> </div> ); }
执行next build后,Next.js会自动在构建产物中生成对应id的静态HTML文件,访问路径为/SG/{id}/product。
2. 编写CSR页面的结构与切换逻辑
在app/CSR/page.tsx中实现客户端组件,渲染带data-id的内容容器,同时完成静态HTML的加载与切换:
// app/CSR/page.tsx 'use client'; import { useEffect, useState } from 'react'; export default function CSRPage() { const [currentId, setCurrentId] = useState('1'); const contentCache = new Map<string, string>(); // 缓存已加载的静态内容,避免重复请求 useEffect(() => { loadStaticContent(currentId); }, [currentId]); const loadStaticContent = async (id: string) => { const container = document.querySelector('[data-id="product-container"]'); if (!container) return; // 优先读取缓存 if (contentCache.has(id)) { container.innerHTML = contentCache.get(id)!; container.setAttribute('data-id', `product-container-${id}`); return; } try { // 请求对应id的静态页面 const response = await fetch(`/SG/${id}/product`); if (!response.ok) throw new Error('静态页面加载失败'); const html = await response.text(); // 提取静态页面body内的内容,避免替换CSR页面的全局结构 const tempDiv = document.createElement('div'); tempDiv.innerHTML = html; const content = tempDiv.querySelector('body')?.innerHTML || ''; // 更新容器内容与属性 container.innerHTML = content; container.setAttribute('data-id', `product-container-${id}`); contentCache.set(id, content); } catch (err) { console.error('加载静态内容出错:', err); container.innerHTML = `<p>加载产品 ${id} 失败,请稍后重试</p>`; } }; return ( <div> <h1>CSR 产品切换页面</h1> <div className="id-switcher"> <button onClick={() => setCurrentId('1')}>产品1</button> <button onClick={() => setCurrentId('2')}>产品2</button> <button onClick={() => setCurrentId('3')}>产品3</button> </div> {/* 静态内容容器,初始标记data-id */} <div data-id="product-container"></div> </div> ); }
3. 核心逻辑说明
- 静态页面请求:通过
fetch直接访问构建好的静态页面路径,Next.js会返回预生成的HTML文件,无需服务器动态渲染。 - 内容提取与替换:因为静态页面是完整的HTML文档,所以用临时div解析后提取
body内的内容,避免破坏CSR页面的全局结构。 - 缓存优化:用
Map存储已加载的HTML内容,减少重复网络请求,提升切换速度。 - 属性同步:每次切换id后更新容器的
data-id属性,方便后续逻辑识别当前加载的内容标识。
4. 注意事项
- 如果静态页面包含客户端脚本(比如React hydration逻辑),注入到CSR页面后可能与现有客户端逻辑冲突,建议静态页面仅保留纯静态内容,或确保脚本不会重复执行。
- 确保
next.config.js未禁用静态生成相关配置,Next.js 14 App Router默认支持静态生成,无需额外配置。
内容的提问来源于stack exchange,提问作者yayuyo
相关产品推荐
相关产品推荐

