同构的字面意思是一套代码跑两个环境:服务器上组件渲染成 HTML 字符串给首屏,浏览器里同一组件再执行一次完成水合接管交互。路由、数据获取、组件本身都是同一份,差异只在入口与环境隔离:你的代码里不该有 window 是默认存在的假设。
它的收益是 SSR 与 CSR 的优点叠加——首屏快、SEO 好同时交互流畅;代价是工程复杂度上一个台阶:构建要处理双入口、依赖要区分是否能服务端运行、数据预取要在两端表现一致。Next.js 与 Nuxt 的很大一部分价值,就是把这些同构细节封装成你不用操心的约定。
// 同构组件:同一个函数在服务器与浏览器都能跑 function App(props) { // 环境差异收敛到上层,组件本身保持纯净 return '<div class="user"><h1>' + props.user.name + '</h1>' + '<p>注册于 ' + props.user.joined + '</p></div>'; } // 服务端入口:渲染成 HTML 字符串 if (typeof window === 'undefined') { html = App({ user: { name: '张三', joined: '2024-01' } }); // 嵌入首屏 } else { // 浏览器入口:拿到服务端数据后水合接管 var initial = window.__INITIAL__; // 从 HTML 里恢复状态 container.innerHTML = App(initial); // 实际框架是比对已有 DOM 而非重建 }