一、为什么 Vue 需要专门做 SEO
Vue 默认是客户端渲染 SPA,首屏 HTML 几乎为空,爬虫抓取不到内容;即使 Googlebot 能执行 JS,也存在“渲染预算”与加载延迟问题
二、技术落地 4 条路线
场景 | 技术选型 | 实现要点 | 适用 |
内容更新频繁、SEO 高要求 | Nuxt3 SSR | npx nuxi@latest init my-seo-app ;useHead() 设置 title/meta;useAsyncData() |
企业官网、电商 |
内容相对静态 | Nuxt3 SSG | nuxt generate 一键生成纯静态文件;部署到 CDN 即可 |
博客、文档 |
只想给几个关键路由做 SEO | 预渲染 | npm i prerender-spa-plugin -D ;在 vue.config.js 中配置需要预渲染的路由即可 缺点:CSS和JS不可用 |
活动页、落地页 |
已开发完的 SPA 不想重构 | 动态渲染 | 用 Puppeteer/Rendertron 针对爬虫返回静态 HTML;配合 Nginx UA 判断(最好选择:Puppeteer) | 旧项目应急 |
三、用 Puppeteer针对爬虫返回静态 HTML;配合 Nginx UA 判断
描述:• 真人访问 → 正常返回 SPA 的 index.html
• 爬虫访问 → 由 Rendertron(或 Puppeteer)渲染成静态 HTML 后返回
3.1 Puppeteer 渲染服务(Node)
# 安装
npm i express puppeteer
server.js
const express = require('express');
const puppeteer = require('puppeteer');
const app = express();
let browser;
(async () => {
browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
})();
app.get('/render', async (req, res) => {
const { url } = req.query;
if (!url) return res.status(400).send('url required');
const page = await browser.newPage();
await page.setUserAgent('Mozilla/5.0 (compatible; PuppeteerRender/1.0)');
await page.goto(url, { waitUntil: 'networkidle2' });
const html = await page.content();
await page.close();
res.set('Cache-Control', 'public, max-age=300'); // 5 分钟 CDN 缓存
res.send(html);
});
app.listen(3001, () => console.log('Puppeteer render service on 3001'));
运行:
node server.js
测试:浏览器: http://localhost:3001/render?url=https://www.baidu.com(自己网址)
或者 :curl http://localhost:3001/render?url=https://www.baidu.com(自己网址)
查看内容和浏览器渲染一样即可
3.2 nginx配置
map $http_user_agent $is_bot {
default 0;
~*Googlebot 1;
~*Baiduspider 1;
~*bingbot 1;
~*Slurp 1;
~*DuckDuckBot 1;
}
server
{
listen 80;
listen 443 ssl http2 ;
server_name baidu.com;
index index.html index.htm default.htm default.html;
root /www/wwwroot/www_t.baidu.com;
try_files $uri $uri/ /index.html;
#CERT-APPLY-CHECK--START
# 用于SSL证书申请时的文件验证相关配置 -- 请勿删除并保持这段设置在优先级高的位置
include /www/server/panel/vhost/nginx/well-known/tw.yougo.vip.conf;
#CERT-APPLY-CHECK--END
#REWRITE-END
location / {
proxy_set_header X-Original-Host $host;
proxy_set_header X-Original-Request-URI $request_uri;
proxy_set_header User-Agent $http_user_agent;
# 1. 如果是爬虫 → 代理到 Puppeteer
if ($is_bot) {
proxy_pass http://127.0.0.1:3001/render?url=$scheme://$host$request_uri;
# 传递必要头部
break;
}
# 2. 真实用户 → SPA
try_files $uri $uri/ /index.html;
}
#禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
#一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
}
#禁止在证书验证目录放入敏感文件
if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
return 403;
}
location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
error_log /dev/null;
access_log /dev/null;
}
location ~ .*\\.(js|css)?$
{
expires 12h;
error_log /dev/null;
access_log /dev/null;
}
access_log /www/wwwlogs/tw.yougo.vip.log;
error_log /www/wwwlogs/tw.yougo.vip.error.log;
}
主要的配置点是:
map $http_user_agent $is_bot {
default 0;
~*Googlebot 1;
~*Baiduspider 1;
~*bingbot 1;
~*Slurp 1;
~*DuckDuckBot 1;
}
location / {
proxy_set_header X-Original-Host $host;
proxy_set_header X-Original-Request-URI $request_uri;
proxy_set_header User-Agent $http_user_agent;
# 1. 如果是爬虫 → 代理到 Puppeteer
if ($is_bot) {
#proxy_pass http://localhost:3001/render?url=$scheme://$host$request_uri;
proxy_pass http://127.0.0.1:3001/render?url=$scheme://$host$request_uri;
# 传递必要头部
break;
}
# 2. 真实用户 → SPA
try_files $uri $uri/ /index.html;
}
配置即可(注意配置时,不要使用localhost 这样nginx解析会出错)
测试:使用POSTMan测试
主要是User-Agent Mozilla/5.0 (compatible; Baiduspider/2.0)
这样就可以模拟百度爬虫,进行访问