对于属性 rel 可以参考 MDN文档 上面描述了这个属性在各种标签下可选的值。对于<a> 的 rel 属性标签主要关注这四个值:
- nofollow 表示当前文档的原作者或出版商不认可被引用的文件。
- external 它表示引用的文档不是当前网站的一部分。这可以与属性选择器一起使用,使外部链接的样式向用户表明他们将离开当前网站。
- noopener 元素的属性noopener关键字指示浏览器导航到目标资源,而不授予新的浏览上下文对打开它的文档的访问权限 - 通过不在打开的窗口上设置属性。
- noreferrer包括这个值使得 referrer 未知(不会包含 Referer 标头),并创建一个顶级的浏览上下文,就像 noopener 也被设置一样。
浏览器安全相关
noopener用于浏览器安全防护,防止钓鱼攻击。 当链接使用 target="_blank" 打开新页面时,新页面可以使用以下语句控制父页面:
if (window.opener) {
window.opener.location="https://nenufm.com?referrer="+document.referrer;
}链接加上rel="noopener"后,则新页面被限制访问window.opener。
noreferrer 与noopener类似,设置了rel="noreferrer"后,链接的新页面被限制访问window.opener。同时,新页面无法获取document.referrer信息,该信息包含了来源页面的地址。因为一些旧的浏览器不支持noopener,所以为也兼容,会同时设置两个属性值rel="noopener noreferrer"。
SEO 优化相关
nofollow 用于告知搜索引擎,当前链接不需要追踪,或者我不想表达对这个链接目标的认可。它更像是一个给搜索引擎的链接关系提示,而不是浏览器安全能力。以前我会把它理解成“绝对不追踪、不传递权重”,现在看这个说法过于绝对。以 Google 的文档表述为准,nofollow、ugc、sponsored 这些值是帮助搜索引擎理解出站链接性质的标记,搜索引擎会按自己的规则处理。
- 反垃圾链接 网站通常有留言功能,一些人会利用这个功能,在评论的时候,留下自己站点的链接。加上nofollow进行屏蔽后,可以防止当前站点的权重流失。
- 节约蜘蛛资源 每个站点,搜索引擎每天派出的爬虫数是一定的。尽量把爬虫引导到有用的链接上,有利于重要页面的收录。不过不要把
nofollow当作站点结构优化的主工具,站内重要页面仍然应该靠清晰导航、列表页、分类页和站点地图组织。
external 用来说明链接目标不是当前站点的一部分。它本身不会让链接在新窗口打开,真正控制新窗口的是 target="_blank"。所以如果只是希望外部链接新开窗口,仍然要写 target="_blank";如果要表达“这是外部链接”,再配合 rel="external"。
Google 搜索文档参考
对于希望 Google 无任何限定条件便直接提取和解析的常规链接,无需添加 rel 属性。
rel="sponsored" 标记广告链接或付费展示位置链接(通常称为“付费链接”)以前推荐使用 nofollow 属性仍可以使用该属性进行标记,但更建议使用 sponsored 标记。
rel="ugc" 标记用户生成的内容(例如评论和论坛帖子)的链接。
rel="nofollow" 如果其他值不适用,并且希望 Google 不跟踪您网站上的出站链接,或不从您的网站上抓取链接页,使用 nofollow。
总结
日常在使用中对于文章中所引用的链接,添加 rel="noopener" 就足够了。在 wordpress 中会对所有文章中的网站外部链接都添加 rel="noopener",这并不会影响网站的 SEO。对于页面上那种必须展示、但不需要表达认可的外部链接,例如备案地址,可以添加 rel="noopener nofollow",把它作为一个“不希望搜索引擎跟随这个出站链接”的提示。
更新:从这次博客迁移得到的经验
2026 年重新整理博客时,我对这几个概念有了更清晰的边界:rel 只描述“当前页面和链接目标之间的关系”,它不是站点级爬虫控制工具,也不是页面索引控制工具。要不要抓取一个路径,主要看 robots.txt;要不要把一个页面放进搜索结果,主要看页面上的 noindex 或响应头;要告诉搜索引擎站点有哪些公开页面,主要靠 sitemap.xml。
这次我把博客的 robots.txt 调整成了三层:
User-Agent: Googlebot
User-Agent: Bingbot
Allow: /
User-Agent: GPTBot
User-Agent: ClaudeBot
Allow: /
Allow: /blog/page/
Allow: /blog/category/
Allow: /blog/categories
Allow: /blog/tag/
Disallow: /blog/
User-Agent: *
Allow: /这里的思路不是“全站屏蔽 AI”,而是只禁止 AI 抓取文章正文路径,仍然允许访问首页、分类、标签、分页这些站点界面。搜索引擎仍然允许正常抓取。原因是我希望普通搜索引擎能索引公开文章,但不希望 AI 训练类爬虫直接批量抓正文。需要注意的是,robots.txt 只对遵守协议的爬虫有效,它不是访问控制,也不是版权保护。
同时我也重新看了 sitemap.xml。以前我很容易把所有博客文章都写成:
<changefreq>weekly</changefreq>
<priority>0.7</priority>现在觉得这种写法不太符合个人博客实际。这个站点的文章多数是历史内容,不会每周更新;真正更重要的是首页、博客列表、分类入口和准确的 lastmod。Google 文档也明确提到,Google 会忽略 priority 和 changefreq,更看重准确可信的 lastmod。所以站点地图里更适合这样表达层级:
- 首页权重最高。
/blog是完整内容索引,权重仅次于首页。- 分类入口和分类页属于中高权重。
- 分页归档只是浏览辅助,权重不应该高于分类页和单篇文章。
- 单篇文章按更新时间分层,最近更新的文章可以略高,老文章不要假装每周更新。
- 隐私政策这种必要但不适合作为搜索入口的页面,可以放低权重,甚至配合
noindex,但不要用rel来表达页面不索引。
最后回到 a 标签本身,我现在会这样用:
- 普通正文引用外部资料:
target="_blank" rel="noopener"。 - 不想暴露来源页面给对方统计:
rel="noreferrer",但要知道它会影响对方看到的来源信息。 - 付费、广告、赞助链接:优先
rel="sponsored",必要时可组合nofollow。 - 用户生成内容里的链接:
rel="ugc"。 - 不想表达认可、不希望搜索引擎跟随的出站链接:
rel="nofollow"。 - 站内重要页面:不要随便加
nofollow,更应该通过导航、分类、标签和 sitemap 让搜索引擎自然理解结构。
也就是说,rel 解决的是链接关系;robots.txt 解决的是抓取边界;noindex 解决的是索引边界;sitemap.xml 解决的是公开 URL 发现和更新时间提示。把这四个工具混在一起,往往会得到看似“优化”但实际相互打架的配置。
更新:这次 Next.js 博客 SEO 实际补了什么
这次给当前博客做 SEO 检查时,我发现基础设施已经有了:robots.txt、sitemap.xml、feed.xml 都能生成,公开内容也已经按 access: public 过滤。真正缺的是页面级信息不够完整。文章页只有 title 和 description,列表页、分类页、标签页也基本依赖全局标题。搜索引擎能抓到页面,但很难从页面头部直接理解“这是哪一篇文章、规范地址是什么、社交分享图是什么、这页是否应该索引”。
这次实际补的不是“玄学关键词”,而是几类可以验证的元数据。
第一类是规范 URL。每个关键页面都补了 canonical:首页是 /,文章页是 /blog/:slug,分类页是 /blog/category/:area,标签页是 /blog/tag/:tag。这样即使以后有旧路径、分页路径或外部参数,搜索引擎也能看到我希望它归并到哪个主地址。旧的 /content/* 和 /page/:page 兼容路由也改成了永久重定向,意思是:这些旧地址已经迁移完成,不是临时跳转。
第二类是分享和摘要信息。文章页现在会根据文章 frontmatter 生成 Open Graph 和 Twitter card:标题用文章标题,描述优先用 description,图片优先用 thumbnail,没有合适图片时退回站点默认头像。这个东西对搜索排序本身不一定有直接帮助,但对微信、聊天工具、社交平台、收藏工具和各种阅读器的展示很重要。它解决的是“别人看到这条链接时像不像一篇完整文章”的问题。
第三类是结构化数据。文章页补了 BlogPosting JSON-LD,大致包含:
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "文章标题",
"description": "文章描述",
"datePublished": "发布时间",
"dateModified": "更新时间",
"author": {
"@type": "Person",
"name": "作者"
}
}这不是给用户看的内容,而是给搜索引擎、阅读工具和其它机器读者看的结构化说明。它比单纯从 HTML 正文里猜测文章标题、发布时间、作者更明确。
第四类是索引策略。不是所有页面都适合进入搜索结果。文章页、首页、博客列表、分类页适合索引;分页页和标签页更像浏览辅助,容易制造大量相似页面,所以这次设置为 noindex, follow:不希望它们作为搜索结果入口,但仍然允许搜索引擎顺着页面里的链接发现文章。隐私政策也是同样思路:允许访问,但不需要作为搜索入口。
第五类是内容元数据。代码层的 SEO 补完后,如果文章本身缺 description,搜索摘要仍然会很弱。这次顺手把公开文章里缺失的 description 和 summary 补齐了;但没有为没有合适图片的文章硬编 thumbnail。没有图时使用默认图兜底,比随便塞一张不相关图片更稳。
所以现在我对个人博客 SEO 的理解更接近一张分工表:
rel:描述单个链接和目标页面的关系。robots.txt:告诉爬虫哪些路径可以抓,哪些路径不希望抓。noindex:告诉搜索引擎当前页面不应该进入搜索结果。sitemap.xml:列出公开 URL 和可信更新时间,帮助发现页面。canonical:告诉搜索引擎当前页面应该归并到哪个规范 URL。Open Graph / Twitter card:让链接在社交、聊天和阅读工具里展示得更完整。JSON-LD:用结构化数据告诉机器这是一篇博客文章,以及标题、作者、时间、图片是什么。description / summary:给搜索摘要、站内搜索、RSS 和分享卡片一个稳定的文字来源。
这些东西各自解决的问题不同。小博客不需要把 SEO 做复杂,但至少要避免三个坑:不要把 rel 当成页面索引控制;不要把 robots.txt 当成内容保护;不要只有 sitemap,却没有文章级 canonical、description 和结构化信息。