js和css文件位置对页面性能有什么影响?

互联网 20-11-18

CSS和JS文件的位置会影响页面效率。js脚本应放在底部,如果放在首部,当下载执行js时,会影响渲染行程绘制页面;而CSS应放在顶部,如果放在底部,页面可以逐步呈现,但在CSS下载并解析完毕后,已经呈现的文字和图片就要需要根据新的样式重绘。

js脚本文件的位置

js脚本应该放在底部,原因在于js线程与GUI渲染线程是互斥的关系,如果js放在首部,当下载执行js的时候,会影响渲染行程绘制页面,js的作用主要是处理交互,而交互必须得先让页面呈现才能进行,所以为了保证用户体验,尽量让页面先绘制出来。

CSS文件的位置

CSS 是页面渲染的关键因素之一,(当页面存在外链 CSS 时,)浏览器会等待全部的 CSS 下载及解析完成后再渲染页面。关键路径上的任何延迟都会影响首屏时间,因而我们需要尽快地将 CSS 传输到用户的设备,否则,(在页面渲染之前,)用户只能看到一个空白的屏幕。

CSS文件放在顶部一方面是因为放置顺序决定了下载的优先级,更关键的是浏览器的渲染机制。

css在加载过程中不会影响到DOM树的生成,但是会影响到Render树的生成,进而影响到layout,所以一般来说,style的link标签需要尽量放在head里面,因为在解析DOM树的时候是自上而下的,而css样式又是通过异步加载的,这样的话,解析DOM树下的body节点和加载css样式能尽可能的并行,加快Render树的生成的速度。

将CSS放在底部,页面可以逐步呈现,但在CSS下载并解析完毕后,已经呈现的文字和图片就要需要根据新的样式重绘,这是一种不好的用户体验。

js、css等脚本位置对性能的影响

用一句话概括就是: JS 全阻塞,CSS 半阻塞。(词是我发明的,方便记忆而已)

  • JS 会阻塞后续 DOM 解析以及其它资源(如 CSS,JS 或图片资源)的加载。

  • CSS 不会阻塞后续 DOM 结构的解析,不会阻塞其它资源(如图片)的加载,但是会阻塞 JS 文件的加载。

  • 现代浏览器很聪明,会进行 prefetch 优化,浏览器在获得 html 文档之后会对页面上引用的资源进行提前下载。(注意仅仅只是提前下载)

先用 Nodejs 搭建一个简单 http 服务器:

//test.jsconst http = require('http');const fs = require('fs');const hostname = '127.0.0.1';const port = 9000;http.createServer((req, res) => {     if(req.url === "/") {         fs.readFile("index.html", "utf-8", function(err, data) {             res.writeHead(200, { 'Content-Type': 'text/html' });  		res.write(data);  		res.end();	 	})     }else if(req.url === "/yellow.js") { 	//延迟 5s	fs.readFile("yellow.js", "utf-8", function(err, data) { 	    res.writeHead(200, { 'Content-Type': 'text/plain' }); 	    setTimeout(function () { 	    	res.write(data); 	    	res.end(); 	    }, 5000); 	})     }else if(req.url === "/blue.js") { 	//延迟 10s	fs.readFile("blue.js", "utf-8", function(err, data) { 	    res.writeHead(200, { 'Content-Type': 'text/plain' }); 	    setTimeout(function () { 	    	res.write(data); 	    	res.end(); 	    }, 10000); 	})     }else if(req.url === "/red.css") { 	//延迟 15s	fs.readFile("red.css", "utf-8", function(err, data) { 	    res.writeHead(200, { 'Content-Type': 'text/css' }); 	    setTimeout(function () { 	    	res.write(data); 	    	res.end(); 	    }, 15000); 	})     }else if(req.url === "/green.css") { 	//延迟 20s	fs.readFile("green.css", "utf-8", function(err, data) { 	    res.writeHead(200, { 'Content-Type': 'text/css' }); 	    setTimeout(function () { 	    	res.write(data); 	    	res.end(); 	    }, 20000); 	})     }}).listen(port, hostname, () => {   console.log('Server running at ' + hostname);});

首页的代码结构:

//index.html <!DOCTYPE html> <html> <head>     <meta charset="utf-8">     <meta http-equiv="cache-control" content="no-cache,no-store, must-revalidate" />     <meta http-equiv="X-UA-Compatible" content="IE=edge">     <title>测试浏览器渲染</title> </head> <body>     <p>First Line</p>     <script src="/yellow.js"></script>     <p>Second Line</p>     <link rel="stylesheet" href="/red.css">     <p>Third Line</p>     <script src="/blue.js"></script>     <p>Fourth Line</p>     <link rel="stylesheet" href="/green.css">     <img src="http://www.liuhaihua.cn/wp-content/uploads/2016/02/uuUFNjm.png">     <p>Fifth Line</p> </body> </html>

以及其它 CSS 和 JS 文件:

//yellow.js document.body.style.cssText = "background: yellow !important";  //blue.js document.body.style.cssText = "background: blue !important";
//red.css body {     background:red !important; }  //green.css body {     background: green !important; }

说明下:yellow.js 和 blue.js 下载时间分别为 5s 和 10s,red.css 和 green.css 下载时间分别为 15s 和 20s。

先来看第三点结论:现代浏览器很聪明,会进行 prefetch 优化,浏览器在获得 html 文档之后会对页面上引用的资源进行提前下载。(注意仅仅只是提前下载)

很好理解,从图中可以看出:CSS、JS、图片在浏览器在拿到 html 文档之后会将页面上引用资源几乎同时下载,但具体什么时候执行要看 html 的结构,注意我这里使用的是 Chrome 浏览器,其它浏览器可能会有差别。

还有就是一个奇怪的现象,Chrome 浏览器有时会对 img 进行 prefetch,有时则不会。

接着是第一点规则:

JS 会阻塞后续 DOM 解析以及其它资源(如 CSS,JS 或图片资源)的加载。

从上图可以看出,当浏览器解析到 yellow.js 这行时候会等待 yellow.js 加载,阻塞后续 DOM 结构的解析(包括 DOM 结构,其他所有资源(CSS, JS, 图片))。

这个很好理解:

  • JS 运行在浏览器中,是单线程的,每个 window 一个 JS 线程,所以当然会阻塞后续 DOM 树的解析咯。

  • JS 有可能会修改 DOM 结构,给 DOM 添加样式等等,所以这就意味着在当前 JS 加载执行完成前,后续资源的加载可能是没有意义的。

其次第二点:

这个就相对比较复杂点,让我先上测试结果的图:

从图中可以得出以下总结:

  • 在加载完 yellow.js 后,当在下载 red.css 时候并不会阻塞 DOM 解析,并且由于第一点规则,当解析到 blue.js 这行的时候,同样会阻塞后续 DOM 解析。

  • 由于我们设置的 red.css 下载时间为 15s 而 blue.js 为 10s,而从前面第三条规则的图中也可以看到,blue.js 在 10s 左右下载完而 red.css 在 15s 左右下载完毕。

  • 最后在 15s 时候页面变为了蓝色,这说明了 CSS 阻塞了 JS 的加载,后续的 JS 文件虽然提前下载完毕了,但还是要等前面 CSS 文件加载完后才能执行。

  • 后续当 blue.js 加载完之后可以看到,green.css 的下载并不会影响到后续 img 的加载,所以说明 CSS 文件下载并不会影响后续图片等其它资源以及 DOM 的加载。

  • 将样式或 CSS 文件定义在 head 中,并且在处理此类请求的时候应该尽快能够响应(CDN 什么的),如果像上面请求一个 CSS 文件都要 10s 的话,那你这页面估计没多少人有耐心等下去。

  • 将 JS 脚本文件放在 body 底部,让 DOM 结构能优先渲染出来,避免 DOM 被阻塞。

  • 当编写比较耗时的 JS 代码时候尽可能使用异步的方式进行加载,比如 setTimeout, ajax 等等,同样也是为了避免页面渲染耗时过长,影响用户体验。

其他:

  1. <script async src="script.js"></script>

    有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(下载异步,执行同步)。
  2. <script defer src="script.js"></script>

    有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。

从使用的角度来看,首先把脚本丢到 body 底部是比较好的优化选择,此法可保证非脚本的其他一切元素能够以最快的速度得到加载和解析。

上述的三点用图可表示为:

蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;绿色线代表 HTML 解析。

总结:

  • 由于现代浏览器都存在 prefetch,所以 defer, async 可能并没有太多的用途,可以作为了解扩展知识,仅仅将脚本文件放到 body 底部就可以起到很不错的优化效果。

  • defer 和 async 都是异步加载脚本文件。

  • 慎用 async,因为它完全不考虑依赖关系,只要下载完后就加载,不考虑此时页面样式先后的加载顺序,不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics。

  • 耗时较长的脚本代码可以使用 defer 来推迟执行。

更多编程相关知识,请访问:编程视频!!

以上就是js和css文件位置对页面性能有什么影响?的详细内容,更多内容请关注技术你好其它相关文章!

来源链接:
免责声明:
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表本站的观点或立场
标签: css
上一篇:php获取远程图片并下载保存到本地的方法分析 下一篇:react开发预加载哪三个js文件?

相关资讯