中小团队首选prerender.io或其开源版;需完全可控且已有chrome环境则用headless chrome+自定义脚本;切勿从零自建爬虫式服务。

预渲染服务怎么选:Prerender.io、Chrome Headless 还是自建?
直接结论:对中小团队,用 prerender.io 或其开源版(prerender Node.js 服务)最省心;想完全可控且已有 Chrome 环境,选 Headless Chrome + 自定义脚本;别碰从零写爬虫式预渲染服务——维护成本远超收益。
常见错误是把 prerender-spa-plugin 当成线上服务用:它只在构建时跑一次,无法响应 URL 参数变化或用户登录态,上线后就失效。真正动态快照必须靠运行时服务。
-
prerender服务默认监听_escaped_fragment_=,但现代爬虫(Googlebot v4+)已不依赖这个,需配userAgent白名单识别真实爬虫 -
Headless Chrome渲染更准,但内存占用高,单实例并发建议 ≤3;用puppeteer-cluster可横向扩展,但得自己管进程生命周期 - 所有方案都绕不开「等待时机」问题:不能只等
DOMContentLoaded,要等数据请求完成。推荐用window.prerenderReady = false+ 手动置true控制出口
动态HTML快照的缓存键怎么设计才不翻车?
缓存键错一个字符,就可能把用户 A 的个人页快照返回给用户 B。核心原则:缓存键必须包含所有影响 HTML 输出的变量,且不可伪造。
典型漏项:locale、is_logged_in、device_type(移动端/桌面端结构常不同)、url_query(尤其是分页、筛选参数)。纯靠 URL 路径做 key 是最大陷阱。
- 正确示例:
prerender:en:mobile:/product?id=123&ref=seo,其中en和mobile来自请求头,ref=seo表明这是为爬虫生成的快照 - 禁止把 session ID、CSRF token 这类敏感字段塞进缓存 key——它们不该出现在快照里,应由客户端 JS 补充
- 缓存过期不能只设 TTL,必须加业务钩子:CMS 更新文章时,主动清掉
prerender:*:/article/:id这类通配 key
如何让预渲染快照和真实页面 DOM 完全一致?
不一致的后果很直接:React/Vue 水合失败、CLS 值爆表、骨架屏闪动。关键不是“看起来像”,而是“结构、class、属性、顺序”四个维度完全相同。
最容易被忽略的是:服务端预渲染时,process.env.NODE_ENV 是 production,而本地开发常是 development,导致某些 dev-only 组件没渲染出来。
- 检查点:打开预渲染生成的 HTML 文件,搜索
data-server-rendered属性(Vue)或data-reactroot(React),确认存在且值为true - 动态 class 名(如
clsx或twMerge)必须在服务端和客户端使用完全相同的输入参数,否则 class 名哈希会不同 - 时间相关字段(如 “刚刚发布”)必须在预渲染时冻结时间戳,用
Date.now()替换为固定值,避免快照秒级失效
服务端如何安全接入预渲染快照?
别用 Nginx 的 try_files 直接 fallback 到预渲染目录——这会让所有 404 请求都走快照逻辑,暴露未授权页面。
正经做法是在 Node.js 或 PHP 入口层做精准拦截:只对已知 SEO 路由、且 User-Agent 匹配爬虫列表的请求,才代理到预渲染服务。
- Node.js 示例:用
isbot库识别爬虫,再判断req.url是否在白名单内,两者都满足才调axios.get('http://prerender:3000', { params: { url: req.url } }) - PHP 示例:Apache
.htaccess中用RewriteCond %{HTTP_USER_AGENT} (Googlebot|Bingbot) [NC]+RewriteRule ^(.*)$ http://prerender:3000/?url=%{REQUEST_URI} [P,L] - 务必设置
Cache-Control: public, max-age=3600在预渲染响应头里,但仅限于静态内容页;用户中心页这类绝对不能加
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











