【HTML并不简单】笔记1-常用rel总结:nofollow、noopener、opener、noreferrer,relList

文章目录

《HTML并不简单:Web前端开发精进秘籍》张鑫旭,一些摘要:

HTML,这门语言的知识体系非常庞杂,涉及Web交互开发、SEO(搜索引擎优化)​、安全、无障碍访问等各个领域,并不仅仅是单纯的标签结构。

大家之所以对HTML有错误认知,一是因为不关心,二是因为认为它可替代,三是因为它缺少好的科普著作。
过去,这是前端开发中的常识,而如今却是冷知识,知者甚少。

一方面是因为前端知识图谱更广了,从业者学习的精力有限,无暇顾及这部分内容;另一方面是产品形态更加多样化,例如移动端产品、工具类产品是不需要SEO知识的;当然,还有一部分原因是,这些知识的匮乏对业务收益的影响是不可见的,或者可以通过其他策略规避因开发人员不懂rel="nofollow"给产品带来的损失。


a元素,想要跳转到某个页面,使用href属性即可。若想新窗口打开目标页面,则:

javascript 复制代码
<a href="/" target="_blank">首页</a>

即可。


a元素支持rel属性。
HTML 属性:rel - HTML(超文本标记语言) | MDN (mozilla.org)

我们这里关注几个值:

  • nofollow
  • noopeneropener
  • noreferrer

rel="nofollow"

给a元素设置rel="nofollow"是SEO中的常用策略,用来告诉搜索引擎不要追踪这个链接。一般情况下,有两种情况需要设置此属性:

  • 目标页面是无效信息,或含有敏感信息
  • 目标是外站,不希望共享权重

不希望共享权重的详细描述:

SEO中有个策略,如果一个权重很高的网站,直接外链一个权重不高的中小网站,同时没有设置rel="nofollow",那么这个中小网站的权重有一定的概率会被提高

如果不想权重外泄,可以设置此属性。

相关链接:

何为Nofollow及如何正确地使用? - 知乎 (zhihu.com)

如何用其他方法规避不懂rel="nofollow"带来的损失?

方法:将所有的外链都换成本站地址进行中转

专门申请一个域名,A网站想要外联B网站,点击B网站先跳到中转站,再跳去B网站。这样可以避免权重外泄,也可以统计外链的点击量。

CSDN就是这样做的:

javascript 复制代码
https://link.csdn.net/?from_id=xxxxxxxx&target=https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F315000749

rel="noopener"与rel="opener"

省流版:如果是不信任 的链接地址,只要是新窗口打开的target="blank",一定要设置rel="noopener"

有场景如下:

主页面有一个"登录"按钮,点击后会开启一个新窗口进行登录,现在希望用户登录成功后,主页面自动刷新,该如何实现?

或许可以用以下方法:

  • visibilitychange事件
  • postMessage实现跨页面通信
javascript 复制代码
document.addEventListener('visibilitychange',function(){
	if(document.visibilitychange==='visible'){
		// 登陆成功
	}
})

但是这两种方法,要么有运行冗余外加执行时机滞后的问题,要么学习成本高,不好。

本小节的rel='opener'就可以精确又轻松地实现上述需求:

html 复制代码
<a href="/" target="_blank" rel="opener">登录</a>

在登录成功后,执行:

javascript 复制代码
window.opener.location.reload()

但是,这样会有安全隐患。window对象的权限太高了,不仅挂载在window对象上的属性和方法可以被执行,任何document对象的属性和方法也可以被执行,因为document对象可以通过window.document访问。

有可能出现被恶意修改主页面内容,或被人通过window.opener.document.cookie获取用户的敏感信息并进行身份伪造等。

作者写了一个页面来演示这种情况:https://www.htmlapi.cn/2/1-1.html

在2021年以前,很多浏览器针对新窗口打开的链接,都是默认放开window.opener的,即,如有链接如下:

html 复制代码
<a href="https://www.aaa.com" target="_blank">登录</a>

那么,此网站www.aaa.com可以通过window.opener对来源页面为所欲为,无论是跳转到恶意网站、注入恶意信息、伪造用户身份,都是有可能的。

因此,那时有一个技术常识,设置了target="blank"的外站一定要设置rel="noopener",这样,外站页面的window.operer就是null,也就没有安全隐患了。

不过,从2020年开始,许多浏览器设置target="blank"的链接元素默认不再是operer,而是noopener。但是,我们还是要手动设置rel="noopener",以防万一。

对于上述场景的需求,让我们看看gpt怎么说:

  1. 在主页面中,创建一个链接,点击该链接会在新窗口中打开登录页面:
html 复制代码
<a href="/login" target="_blank" rel="noopener noreferrer">登录</a>
  1. 在新窗口的登录成功后的处理逻辑中,添加一行代码,用于刷新主页面:
javascript 复制代码
if (window.opener) {
  window.opener.location.reload();
}

这段代码检查window.opener是否存在,如果存在(即当前窗口是由另一个窗口打开的),则刷新打开当前窗口的窗口。

请注意,出于安全原因,你应该总是在使用target="_blank"时添加rel="noopener noreferrer"属性。这可以防止新窗口通过window.opener修改打开它的窗口的location,并防止Referer Header泄露信息。

rel="noreferrer"

首先要了解document.referrer这个API。

document.referrer可以返回当前页面的来源地址(当前页面的上一个页面)。用户可以直接在浏览器的地址栏输入URL地址进行访问。若通过设置了rel='noreferrer'的链接元素访问,那么document.referrer就是空字符串。

如edge首页:

如我从内容管理访问我自己的文章:

所有知名的网站分析工具,如百度统计和谷歌分析,都是通过document.referrer来判断多少 PV(页面访问量) 来自搜索引擎,多少PV来自社交媒体,以及多少PV来自直接访问的。

我们可以借用document.referrer来完成一些开发任务,与细节体验相关。有两个例子。

例一:

在移动端开发中,页面左上角往往会有一个"返回"按钮,但如果用户是通过点击某个分享链接进入的,那么这个返回的逻辑就不对,因为并没有上一页,此时这个"返回"按钮显示为"主页"按钮更合适。此时,我们就可以使用document.referrer来优化此细节,如果document.referrer是空字符串,则点击左上角的按钮会回到首页;如果不是,则会返回上一页。

例二:

在某列表页面,点击任意列表会进入详情页,然后希望再次返回(通过页面内链接,而非浏览器的"后退"按钮)到列表页的时候,页面依然定位在之前的滚动位置,但如果是从其他页面进入的,则滚动置顶。

可以通过在路由里加参数实现,若从列表项返回则:

html 复制代码
<a href='/list.html?from=detail'>返回列表<a>

若从其他地方返回,则没有此参数:

html 复制代码
<a href='/list.html?from=detail'>返回列表<a>

但是这样不够优雅,产生了副作用。可以使用浏览器自带的API:

javascript 复制代码
if(/detail\.html/.test(document.referrer)){
 // 为true说明来源页面,即上一个页面是detail.html,即从详情页来的,执行滚动还原
}

例如,如果用户从"http://example.com/detail.html"页面导航到当前页面,那么这个`if`语句将为`true`,并执行其内部的代码。如果用户从"http://example.com/otherpage.html"或直接在浏览器中输入URL来访问当前页面,那么这个if语句将为false,并跳过其内部的代码。

作者提供的例子:https://www.htmlapi.cn/2/1-2.html

那么,我们要在什么时候给链接设置rel="noreferrer"

  • 自己产品的链接都不要设置:设置了会影响用户访问路径的追踪,进而影响页面的流失率等数据的统计
  • 外站链接,作者建议都设置:URL中含有大量信息,甚至有隐私内容,如搜索结果落地页的URL会包含搜索关键词,最好不要泄露
  • 若产品是社交媒体,可以不设置:如微博、知乎等。这种产品以社交为主,更看重信息传播。暴露referrer信息有助于第三方网站溯源,间接增加访问量和热度。

(如上述截图,CSDN也没有设置)

注意,我们会经常看见如下代码,即noopener和noreferrer同时设置:

javascript 复制代码
<a href='xxxx' target="_blank" rel="noopener noreferrer">外部网站<a>

但是,社交媒体就不担心隐私泄露了吗?实际上,rel="noreferrer"的确存在不足,其设置与否的效果就像是0和1,并没有折中的说法,也就是说,无法兼顾信息传播和隐私保护

于是,2016年,各大浏览器开发商陆续支持一个新的HTML属性,referrerpolicy,可以兼顾信息传播和隐私保护,之后会讲。

还有一种少见的场景:

链接地址直接是外部图片,而这个图片设置了防外链,此时,给链接元素设置rel="noreferrer"有可能让图片可以访问。如:https://www.htmlapi.cn/2/1-3.html

原因:

防止热链的策略通常是通过检查HTTP的Referer头来实现的。当你从一个网页访问另一个网页时,你的浏览器会发送一个Referer头,告诉服务器你是从哪个页面跳转过来的。如果服务器发现Referer头不是它期望的值(例如,不是同一域名下的页面),那么它可能会拒绝提供服务,例如不返回图片内容。
rel="noreferrer"属性会告诉浏览器在请求资源时不要发送Referer头。 这样,即使图片的服务器设置了防止热链的策略,也无法检查Referer头,因此可能会正常提供服务。

对于作者例子https://www.htmlapi.cn/2/1-3.html,若图片被浏览器缓存了,点第一个链接也可以访问到图片(点完第二个再点第一个就可以访问了,因为缓存了)。

relList对象

对于rel="noopener noreferrer",我们发现rel属性支持使用空格分隔多个值。相似地,class也可以。

class可以用classList.remove移除某个类。rel也可以:使用relList.remove移除某个rel。

它们有专门的接口interface:DOMTokenList 。

DOMTokenList - Web API | MDN (mozilla.org)

rel属性要比很多人预想的要强大得多,具有其他HTML属性所没有的、独立的API。

相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang2 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
2401_858286113 小时前
L7.【LeetCode笔记】相交链表
笔记·leetcode·链表
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、5 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
龙中舞王5 小时前
Unity学习笔记(2):场景绘制
笔记·学习·unity
青椒大仙KI116 小时前
24/11/7 算法笔记 PCA主成分分析
笔记·算法·信息可视化
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙