学完这篇你能把 PHP 的服务端渲染和 Vue/React 这类前端框架放进同一个站点里:首屏和搜索收录交给 PHP,重交互区域交给框架,不用整站重写成 SPA,也不用给服务器装 Node。
第一步:先划边界,别想着全站二选一
混合开发最常见的翻车方式是「一半页面 PHP、一半页面 SPA」,跳转两次白屏。正确做法按区域切,不按页面切:
- 交给 PHP 渲染:首页、版块页、帖子列表、帖子详情正文、问答聚合页。这些是搜索引擎和 AI 爬虫真正要读的内容。
- 交给前端框架:发帖编辑器、私信会话、通知下拉、礼物墙、后台的可视化配置面板。这些是登录后高频交互、对 SEO 无意义的区域。
判断标准一句话:游客不登录也要看到的内容,必须由 PHP 输出到 HTML 里。
第二步:PHP 端把数据「预埋」进页面
框架挂载前需要初始数据,否则首屏必然白屏一下。做法是在模板里输出一段 JSON:
<script>
window.__BOOT__ = <?= json_encode($bootData, JSON_UNESCAPED_UNICODE|JSON_HEX_TAG|JSON_HEX_AMP) ?>;
window.__CSRF__ = <?= json_encode($csrfToken) ?>;
</script>
`$bootData` 只放当前组件真正需要的字段,别把整张表塞进去。
注意:JSON 输出必须带 `JSON_HEX_TAG` 等转义标志。用户昵称里如果出现 `</script>`,不加转义就是现成的 XSS。
第三步:模板里留挂载点,同时输出首屏骨架
挂载点用一个空容器,容器内部直接写好服务端渲染的静态内容:
<div id="app-composer">
<!-- PHP 输出的首屏内容,框架接管后替换 -->
<form method="post" action="/post.php?action=reply">…</form>
</div>
框架 hydrate(或直接 mount)时替换掉内部节点。这样即使 JS 加载失败、用户网速很差,回复框依然能用原生表单提交。
注意:Clara BBS 这类系统是单模板响应式的,同一套视图同时适配手机和桌面。你的挂载点容器不要写死像素宽度,交给 CSS 容器查询或百分比,否则手机上会横向溢出。
第四步:构建放在本地,服务器只收产物
前端框架的构建不要指望服务器上跑。本地 `npm run build` 产出 `dist/`,把 JS/CSS 传到站点的静态目录(例如 `static/dist/`),PHP 模板里按文件名引用即可。
如果你的系统要求「无需 Composer、无需命令行」——这条依然成立:构建只在你的开发机上发生一次,服务器端只是分发静态文件。带 hash 的文件名建议读一个 `manifest.json`,模板里查表输出路径,避免每次改版都手改模板。
注意:改完前端产物记得刷新浏览器强缓存(Ctrl+F5)。带 hash 的产物不受影响,不带 hash 的老文件会被浏览器缓存住,看起来像「改了没生效」。
第五步:接口统一走 PHP 路由,安全基线别绕过
框架发起的请求,走的还是 PHP 入口(配合伪静态把非静态文件请求转发到 `index.php`,`.html` 后缀自动识别):
- 所有写操作带 CSRF token,从 `window.__CSRF__` 取,随请求头或表单字段回传;token 失效时提示用户刷新页面,不要静默失败。
- 输出到页面的用户内容做转义;富文本走白名单过滤。
- 上传走服务端的扩展名白名单 + 图片二次校验,前端 `accept` 属性只是提示,不是防线。
注意:上传失败排查先看两处——后台「允许的扩展名」和「附件允许的扩展名」是两个独立字段,别只改一个;再看 PHP 的 `upload_max_filesize` / `post_max_size` 是否大于文件体积(面板默认常是 2M,手机直拍的照片轻松超);最后确认 `uploads` 目录可写。
第六步:PHP 侧改动和前端改动,节奏不一样
这是混合开发最容易混乱的地方:
- PHP 侧改动:多数系统(如 Clara BBS)是运行时钩子机制、保存即生效,不需要编译、不需要清缓存。你在插件目录 `content/plugins` 加一个钩子逻辑,刷新页面就见效。
- 前端侧改动:必须重新构建 + 上传产物,改的是 `dist/`。
所以分工上,模板结构、接口、权限、钩子扩展放 PHP;纯交互逻辑放框架,两边通过「PHP 输出数据、框架回传接口」这条固定通道通信,别让前端直接读数据库结构。
第七步:守住 SEO / GEO 的输出面
如果站点开了 GEO(AI 引擎收录)相关能力,AI 爬虫抓走的正是 PHP 输出的那份 HTML。这意味着:
- 帖子正文、问答的「问题 + 最佳答案」必须在服务端 HTML 里,不能靠 JS 异步拉取。
- 结构化数据(`QAPage`、`acceptedAnswer`、`citation`)由 PHP 模板输出最稳。
- 权限版块的内容不要因为前端请求而泄露到游客可见面,服务端渲染时就得按权限过滤。
注意:把关键正文改成前端异步渲染,等于把收录面砍掉一半。混合开发里「哪些内容必须 SSR」这条线,比技术选型重要得多。
小结
- 按区域切,不按页面切;游客可见内容必须由 PHP 输出。
- 初始数据用 `window.__BOOT__` 预埋,注意 JSON 转义防 XSS。
- 挂载点里放可用的服务端骨架,JS 挂了也不影响基础操作。
- 构建在本地,服务器只收 `dist/` 静态文件。
- 接口统一走 PHP 入口,CSRF、转义、上传白名单一个都不能省。
- PHP 侧保存即生效,前端侧必须重新构建,团队里要写清楚这条分工线。
- 要 SEO / GEO 的内容留在服务端 HTML 里,别交给异步请求。