最近遇到一个问题,就是我的个人网站需要接入第三方百度统计,因我的文章图片有来自第三方微信后台上传的文章,所以使用<meta name="referrer" content="no-referrer">
解决图片访问403的问题,但是此时这个导致我百度统计失败了,于是去查询了一下referrer
这个特性。
正文开始...
referrer
这个主要主要是来防护CORS
跨站请求伪造的一个标识,对于来源于自身服务器,会默认在请求头中带入refer
信息
什么意思,具体看下下面
当我们在html的header
中使用<meta name="referrer" content="no-referrer">
请求头的General
中
Referrer Policy: no-referrer
在request
中整个Referer
信息会被删除
如果我们没有加meta
标签no-referrer
那么此时你会发现默认请求头里是
Status Code: 200 OK
Referrer Policy: strict-origin-when-cross-origin
然后请求头request-header
里面就会携带了Referer
Referer: http://localhost:8080/
关于referrer
的更多信息可以参考http referer策略
我的网站需要不带referrer
,因为微信
图片如果带了当前站点的referrer
就会有问题,所以此时怎么加上百度统计代码呢?
由于最初是这样加入统计的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="referrer" content="no-referrer" />
<title>js执行顺序</title>
<style>
* {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div id="app">
<h1>js执行顺序</h1>
</div>
<script src="https://hm.baidu.com/hm.js?c7002d193ba43df9317b7fc847709213"></script>
</body>
</html>
这样的做法是我们通用的方式,就是script
脚本放入body
中,但是这样会导致百度统计不到,因为meta
中已经使用no-referrer
了,那怎么办呢?我网页中又需要加no-referrer
,不加这个,会导致第三方图片显示不出来。
页面渲染
此时我们需要了解另外外一个知识,就是浏览器页面是怎么渲染的
我们写一段测试代码
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <meta name="referrer" content="no-referrer" /> -->
<title>js执行顺序</title>
<script>
alert(111);
</script>
<style>
* {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div id="app">
<h1>js执行顺序</h1>
</div>
<script src="https://hm.baidu.com/hm.js?c7002d193ba43df9317b7fc847709213"></script>
</body>
html
页面渲染是根据标签顺序同步渲染的,而且script
标签会阻塞Dom
的渲染
此时你会看到页面弹框,但是html
内容并没有完全渲染出来
当我确认弹框后,页面才显示出来
我们在header
中加入一行css
代码
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <meta name="referrer" content="no-referrer" /> -->
<title>js执行顺序</title>
<style>
body {
background-color: red;
}
</style>
<style>
* {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div id="app">
<h1>js执行顺序</h1>
</div>
<script>
alert(111);
</script>
<script src="https://hm.baidu.com/hm.js?c7002d193ba43df9317b7fc847709213"></script>
</body>
我们会发现,页面先绘制成了红色,然后再执行script
脚本,最后页面内容显示出来了
html
标签会按照顺序执行,背景先是变成了红色,然后内容没有立即显示出来,执行script
脚本后,才显示了页面内容,这就证明了js
会阻塞页面的解析,所以在文章开头,我们要设置referrer
,那么我们先执行script
统计脚本,然后再设置meta
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://hm.baidu.com/hm.js?c7002d193ba43df9317b7fc847709213"></script>
<meta name="referrer" content="no-referrer" />
<title>js执行顺序</title>
<style>
body {
background-color: red;
}
</style>
<style>
* {
padding: 0;
margin: 0;
}
</style>
</head>
所以我们看到百度统计脚本是像正常默认的,但是其他基本就是no-referrer
其他脚本,因为header
设置了meta
所以解决百度统计代码
失效的办法就是在设置meta
之前执行就行
CSS会阻塞页面解析吗
在以前面试中,就曾经有问到这个问题,css
到底会不会阻塞dom
的解析,这时常是一个令人模糊的问题
举个例子证实一下自己的猜想
新建一个index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>js执行顺序</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="app">hello word</div>
</body>
</html>
然后我引入index.css
我在index.css
写入测试代码
.app {
background-color: red;
}
aaa
你会发现,我在css
文件中写入了一段非css
的代码
但是页面依旧能够正常渲染
所以从以上可以证明,css
并不会阻塞是dom解析
,dom解析
与css渲染
是并行的,css
负责渲染标签
样式,html
只是负责解析内容标签,css渲染
,html解析
主要是在GUI
线程里面,GUI线程
主要是构建DOM Tree
,Style Tree
,Render Tree
布局以及绘制。
我们经常会在面试中被问到JS
为什么是单线程的,有时会被问得哑口无言。
我们想想JS祖师爷
在设计这门语言肯定有其初衷和取舍,浏览器是多进程的,浏览器的每一个窗口就是一个进程,而进程之间都应该是互相独立的,而每一个进程里面的线程是独立,所以js
设计时就是单线程的,每个线程之间互不影响
所以JS
设计就是单线程的,通常来讲为了弥补单线程的缺陷,所以有了同步任务与异步任务的设计,在浏览器渲染页面,解析dom Tree
,绘制css tree
,通常在主线程
执行栈中优先执行同步任务
,主线程执行栈执行完了,然后再执行异步任务
,异步任务主要会进入队列中,遵循先进先出原则,直到队列执行完毕为止。
css会阻塞js执行吗?
我们做个实验,在style
标签前后都引入一段js
执行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <meta name="referrer" content="no-referrer" /> -->
<title>js执行顺序</title>
<script>
var start = new Date().getTime();
console.log("before css");
</script>
<link rel="stylesheet" href="./index.css" />
<!-- <link
href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.0/css/bootstrap.css"
rel="stylesheet"
/> -->
<script>
var end = new Date().getTime();
console.log(end - start, "difftime");
console.log("after css");
</script>
</head>
<body>
<div class="app">hello word</div>
<script>
const app = document.getElementsByClassName("app")[0];
app.style.backgroundColor = "green";
</script>
</body>
</html>
引入index.css
引入bootstrap.css
我们引入bootstrap.css
与引入我们自己的index.css
,自此你会发现,最后执行的时间很明显,引入bootstrap
的css打印的时间差明显是要大于体积小的css的
所以css
是会阻塞js
的执行的
但是一般情况,我们不会这么干,一般都会在header
中引入css
,在body
结束标签引入脚本
也就大概会是下面这样
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div id="app"></div>
<script>
console.log('hello')
</script>
</body>
</html>
总结
当你百度统计失效时,如果网站
meta
使用了no-referrer
,如果是在统计脚本之前执行,那么此时需要先执行统计脚本,然后再设置meta
js会阻塞
dom tree
解析,css
不会阻塞dom tree
解析,css只会影响dom tree
的绘制css
的加载是会阻塞js
的运行的,css体积
越小影响越小外部资源的最佳方式,
header
引入外链css
,body
结束标签引入script
脚本本文示例code example