你的单页应用是不是让爬虫“空手而归”?

你上线了一个 Vue 博客,配了漂亮的动画和懒加载,结果搜自己文章标题——首页都排不进前二十。
不是流量没来,是爬虫压根没看清你写了啥。它打开页面,只看到 <div id="app"></div>,然后默默关掉。

为什么 Webpack 打包的网站对爬虫不友好?

现代前端框架默认走客户端渲染(CSR)。Webpack 把所有逻辑打包成 bundle.js,等浏览器下载、执行完,页面才真正“长出来”。
但爬虫不这么干。谷歌虽能跑 JS,但会跳过耗时操作、延迟加载、异步接口调用。它更愿意信第一眼看到的 HTML。
你的 <title>mounted() 里 set 的,产品列表靠 fetch() 拉的,meta 描述藏在 Vue Router 的 beforeEach 里——这些,爬虫大概率直接略过。

一个真实案例:朋友做的装修设计展示站,用 Vue + Webpack 打包。搜索控制台抓取结果显示,首页 HTML 里只有导航栏、loading 图标和一个空 #app。几十个案例页,全被当成“无内容页面”,收录量几乎为零。

方法一:服务端渲染(SSR)是终极解决方案吗?

SSR 的逻辑很直白:用户或爬虫一请求,服务器就先把页面“画好”,把带内容的 HTML 直接吐出去。Next.js、Nuxt.js 这类框架已经把这步封装得挺顺手。
爬虫拿到的就是成品网页——有标题、有段落、有图片 alt,该有的都有。收录快、摘要准,SEO 基础分直接拉满。

但它不是银弹。每次访问都要服务器跑一遍渲染,对高并发或计算密集型页面,响应可能变慢。如果你的网站更新频率低(比如企业官网),或者内容基本静态,SSR 就有点“大炮打蚊子”。
先问自己一句:我最缺的是排名,还是首屏快 50ms?

方法二:如何用“预渲染”低成本解决问题?

预渲染适合这类场景:内容不会天天变,但又不能接受 SSR 的运维成本。比如公司介绍、服务说明、博客归档页。
构建时,用 Puppeteer 自动访问 /about/blog/2024-01-01 这些路由,等 JS 渲染完,把最终 HTML 存成 about.htmlblog-2024-01-01.html
部署时,Nginx 或 Vercel 直接把这些文件当静态资源返回。用户和爬虫看到的,都是“即开即读”的完整页面。

关键动作就两步:

  • 在 Webpack 配置里加 prerender-spa-plugin(Vue CLI 用户可直接配 vue.config.js);
  • 明确告诉插件:“请预渲染这几个路径”,别漏掉核心落地页。

方法三:动态渲染:如何区别对待爬虫和用户?

动态渲染像一个“智能门卫”:它看 User-Agent,发现是 GooglebotBingbot,立刻转去 SSR 服务生成 HTML;普通用户,则照常加载你的 bundle.js
适合那种内容实时变动、又必须上搜索结果的场景,比如新闻聚合页、活动倒计时页。

实现方式不一定要买第三方服务。如果你用的是 Express 或 Nginx,加几行 UA 判断 + 反向代理规则就能搭起来。重点是别让爬虫版本和用户版本“长得不一样”——比如爬虫看到的是旧价格,用户点进去却是新活动,搜索引擎会认为你在作弊。

方法四:怎样优化基础HTML结构助力爬虫?

别等 SSR,今天就能改。打开你项目的 public/index.html(或 src/index.html),盯住这几处:

  • <title> 标签里别留空,也别写“Loading…”——直接填上主关键词,比如“前端性能优化指南 | XX 技术博客”;
  • <meta name="description"> 同理,写一句人话摘要,别依赖 JS 注入;
  • 导航菜单用 <a href="/contact">联系我们</a>,不是 <div @click="goTo('/contact')">联系我们</div>
  • 正文里该用 <h1> 的地方别用 <div class="h1-style">,语义标签是爬虫的路标。

方法五:如何用站点地图和链接引导爬虫?

爬虫不是瞎逛,它靠线索找路。

  • 生成 XML 站点地图(sitemap.xml),列全你希望被收录的页面 URL,丢到根目录;
  • robots.txt 里加一行:Sitemap: https://yoursite.com/sitemap.xml
  • 别把所有入口都塞进 SPA 路由里。在 index.html 底部加几个静态 <a> 链接,比如“最新文章”“热门案例”“关于我们”,指向真实 URL。这些链接就像给爬虫留的后门,它顺着就能摸进你的内容腹地。

今天下班前就能执行的一个操作

打开 Chrome,访问 Google Search Console → 左侧选“URL 检查工具” → 输入你网站一个内容页地址(比如 /blog/webpack-seo-tips)→ 点击“测试实际网址” → 切到“抓取的 HTML”标签页。

如果看到的只有 <div id="app"></div> 和一串 script 标签,问题就坐实了。
接下来,马上做两件事:

  1. 打开你项目的 public/index.html,把 <title><meta name="description"> 改成静态、具体、带关键词的内容;
  2. 打开终端,运行 npm install --save-dev prerender-spa-plugin,然后按你脚手架文档(Vue CLI / CRA / Vite)配置插件,先给首页生成一个预渲染快照,本地起服务看看效果。