• 技术文章 >web前端 >前端问答

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

    青灯夜游青灯夜游2020-11-30 14:27:25原创58

    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 半阻塞。(词是我发明的,方便记忆而已)

    下面开始我就一边测试,一边解释上述测试的结果:

    测试的浏览器是 Chrome,版本号为 55.0.2883.95 (64-bit)

    先用 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。

    之后将所有文件放到同个目录下,在控制台输入 node test.js,打开浏览器访问 127.0.0.1:9000 就可以访问。

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

    1.png

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

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

    接着是第一点规则:

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

    2.png

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

    这个很好理解:

    其次第二点:

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

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

    3.gif

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

    这个也好理解:JS 代码在执行前,浏览器必须保证在 JS 之前的所有 CSS 样式都解析完成,不然不就乱套了,前面的 CSS 样式可能会覆盖 JS 文件中定义的元素样式,这是 CSS 阻塞后续 JS 执行的根本原因。

    最后这里说明下为什么最后 body 的背景色没有变成绿色:因为 js 定义的样式在内联样式,优先级高于在 CSS 文件中定义的样式,所以不是 green.css 没有加载,而是没有生效。看下图就知道了:(green 和 red 样式都被划掉了)

    4.png

    所以知道了上述的结论之后,我们在开发的时候应该尽可能地:

    其他:

    上面介绍了 JS 会阻塞后续 DOM 解析以及其它资源(如 CSS,JS 或图片资源)的加载,这是在没有考虑到 defer, async 的情况下。

    当浏览器碰到 script 脚本的时候:(不考虑浏览器的 prefetch)

    1. 没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,当然还得等待前面的 CSS 文件渲染完。
    2. <script async src="script.js"></script>

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

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

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

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

    5.png

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

    总结:

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

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

    本文原创发布php中文网,转载请注明出处,感谢您的尊重!
    专题推荐:js css
    上一篇:react开发预加载哪三个js文件? 下一篇:怎么在html页面写css样式表
    第14期线上培训班

    相关文章推荐

    • css如何实现圆形头像• bootstrap 如何修改css样式• css如何改变文本框颜色• css怎么设置字体为宋体• css3 @media怎么不起作用?是什么原因?

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网