技术 SEO:服务端渲染、站点地图与访问性能
这一节先在本机得到四个可以核对的结果:公开示例返回200且HTML包含正文,不存在地址返回404,私有报告地址返回401,站点地图只列公开页。 然后再看性能图,判断首页慢在什么地方。它们不会直接带来排名,但能让你知道搜索工具和读者请求页面时拿到的究竟是什么。
准备Node.js 22、终端与浏览器即可,不需要Search Console、域名或任何客户资料。下面的小站只供练习,不接模型、登录系统和支付;私有路径仅用固定401演示访问分类,不是完整身份认证。
运行一份正文已经在HTML里的小站
新建空目录clearcopy-seo-demo,在其中保存server.mjs,复制完整代码:
import http from 'node:http';
const origin = 'http://127.0.0.1:4337';
const path = '/guides/packing-example/';
const page = `<!doctype html>
<html lang="en"><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Packing-list app description example | ClearCopy</title>
<link rel="canonical" href="${origin}${path}">
<main><h1>Remove an unsupported sync claim</h1>
<p>Product facts: offline packing lists, trips, checkboxes, reuse.</p>
<p>Draft: Sync your packing list across all devices.</p>
<p>Rewrite: Reuse your packing list for future trips.</p>
<p>The supplied app facts do not include cloud sync.</p>
<a href="/">Back to the demo home</a></main></html>`;
http.createServer((request, response) => {
const url = new URL(request.url, origin);
response.setHeader('Content-Type', 'text/html; charset=utf-8');
if (url.pathname === path) return response.end(page);
if (url.pathname === '/') {
return response.end(`<h1>ClearCopy demo</h1>
<a href="${path}">Read the packing-list example</a>`);
}
if (url.pathname === '/sitemap.txt') {
response.setHeader('Content-Type', 'text/plain; charset=utf-8');
return response.end(`${origin}/\n${origin}${path}\n`);
}
if (url.pathname.startsWith('/private/')) {
response.statusCode = 401;
response.setHeader('Cache-Control', 'private, no-store');
return response.end('Sign in required');
}
response.statusCode = 404;
response.end('<h1>Page not found</h1><a href="/">Home</a>');
}).listen(4337, '127.0.0.1', () => console.log(origin));
运行node server.mjs,看到http://127.0.0.1:4337后,在浏览器打开它,点击Read the packing-list example。你应看到功能事实、错误同步宣称、改写与解释,网址末尾是/guides/packing-example/。
如果端口被占用,先停止本练习上一次的进程;也可以把代码中的4337统一换成另一个空闲端口。不要停止不属于这次练习的业务服务。
不执行页面脚本,也能找到那句解释
另开终端,运行:
curl -i http://127.0.0.1:4337/guides/packing-example/
响应应包含200 OK,并能直接找到The supplied app facts do not include cloud sync.。curl不会执行页面JavaScript,所以这句已经在服务器返回的HTML里。
Google的JavaScript处理说明将抓取、渲染与索引区分开来。这里先让阅读正文直接存在于响应里,方便核对;不是说客户端渲染一定不能索引。用户输入、实时任务状态仍然可以用脚本处理,不需要为了SEO移除交互。
移到Astro项目时,将示例正文放在页面模板或服务端取得的已发布内容中。不要先返回一个空main,再等需要登录的API补公开文章。你可以对自己的本地或测试站重复同一条请求,把URL换成真实公开文章路径,看关键例句是否还在。
用三个地址排除“全部返回首页”
分别请求以下地址:
curl -i http://127.0.0.1:4337/not-a-page
curl -i http://127.0.0.1:4337/private/report-demo
curl http://127.0.0.1:4337/sitemap.txt
第一条应返回404并显示回首页的入口,不能因为有一个友好页面就改回200。第二条返回401,正文没有客户报告,并带私有、不存储的缓存策略。第三条只列根首页和公开样例,不出现/private/。
真实项目里的私有报告还要核对本人身份和访问权限。本例只让你观察未登录时的响应,不能拿固定401代替已登录用户之间的隔离。也不能只靠robots文件隐藏地址来保护文案,任何人仍可以直接请求被写出的URL。
先做两行能维护的站点地图
本例采用纯文本地图,完整内容是:
http://127.0.0.1:4337/
http://127.0.0.1:4337/guides/packing-example/
Google创建站点地图说明允许每行一个绝对URL的文本格式。网站只有几页时,这比先写复杂XML生成器更容易检查。正式站点将主机替换为自己的HTTPS域名;不要提交localhost,它不对搜索引擎公开。
在Astro中可把正式版保存到public/sitemap.txt。如果项目已由插件生成XML地图,就维护现有地图,不再创建两套互相矛盾的清单。以后从后台生成时,只从“已发布、公开、可访问”的记录取地址,下架时同步移出。
地图表达希望发现哪些页,不保证收录。站内仍保留普通链接,本例首页就能点到样例;用户和抓取工具不必先猜它的地址。
对着性能图,先分清两组数字
配图是web.dev公开的Chrome Performance示例。左侧显示Local LCP 0.80秒,旁边Field第75百分位为3.36秒,不是ClearCopy或本次本地站的成绩。它说明同一个页面在你的电脑上很快,不等于真实用户环境同样快。
打开自己的教学页面,在Chrome开发者工具进入 Performance,查看本地指标并重新加载。注意被识别为最大内容的元素,是文字还是图片。然后去PageSpeed Insights输入你自己公开的测试URL;本地地址不能在这个公网工具里测。没有真实用户数据时,工具可能只给实验室诊断,不要补造Field数字。
若大图占据首屏并被识别为LCP元素,先按显示尺寸压缩、写清宽高,避免正文等装饰图下载后才出现。若关键正文受脚本等待阻塞,回到HTML检查。每次只改一项,再用相同设备与网络条件复测;模型处理报告的12秒等待另计,不归功于图片优化。
最后保存四项实际结果:200含解释句、404缺页、401无报告、地图仅两个公开地址。关闭服务器用Ctrl-C。你已完成一次本地技术检查;部署后再对正式公开页面复查,而不把本地四项通过写成Google已经收录。