问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

关于CSS、JS 内联 或 外链 的优缺点以及对网页加载速度的影响&提升网页加载速度

发布网友 发布时间:2022-04-18 00:28

我来回答

2个回答

懂视网 时间:2022-04-18 04:49

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 文档之后会对页面上引用的资源进行提前下载。(注意仅仅只是提前下载)

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

    测试的浏览器是 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, 图片))。

    这个很好理解:

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

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

  • 其次第二点:

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

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

    3.gif

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

  • 在加载完 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 的加载。

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

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

    4.png

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

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

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

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

  • 其他:

    上面介绍了 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 解析。

    总结:

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

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

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

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

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

    热心网友 时间:2022-04-18 01:57

    内联在某些情况下有个好处就是“缓存” 外链太多的话也会影响到速度,因为增加了浏览器加载时的请求“迸发数”(浏览器同一时间的链接请求) link的href地址,script的src链接,包括img的src链接基础上都是页面加载时就请求的 比如某浏览器的并发上限是3个,图片如果不可避免,我们只考虑link和script,你可以去想想如果当link大于3的时候剩下的样式他会怎么去排队请求和加载,有的网站加载时 你会看到先是无样式的排版,然后才很快正常,有的甚至直接无样式了,这种状况代码问题外也基本上只可能在外链样式的情况下产生,出现一定的体验问题 当然,一切都不绝对,关键看具体的页面内容和结构的情况,有时候我们需要为重点而舍弃,有时候其实怎么样做关系都不大

    采纳哦
    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
    为什么来大姨妈胸会胀 少儿学什么舞蹈 青年学什么舞蹈好 成年人学什么舞蹈 福州企业最低工资标准 2013年厦门的底薪是多少 生产要素的需求有哪些性质 生产要素的需求有何特点? 什么是生产要素需求 微观经济学要素需求什么是条件要素需求?它和要素需求有什么不同?_百度... 钳型电流表测电流慢是什么原因? 之前老的钳形表要淘汰了,想买数字钳形表,功能更多样,但是品牌有好的推荐吗? 我国第一次派人参加残疾人奥运会是在哪一年? 第一届冬季残疾人奥林匹克运动会在哪年举行的? 残奥会始于那一年 中国举办残奥会是哪一年 第一届冬季残奥会在哪举行 第一节残奥会是在哪举行的? 第一届残奥会在哪举行 第一届冬季残疾人奥林匹克运动会在哪个国家哪年举行 第一届冬季残奥会是在哪年举办的 残奥会是几年一届?第一届在哪举办的? 第一届伤残人士奥运会在哪一年举行? 中国银行银联二维码支付活动 上海有哪些商家 人生百味是什么意思 人间百味,吹来云彩的爱心,落下人间烟火? 都说人生百味、这百味是什么味? 都说人生百味。到底是哪百味? 人生百味世事无常沧桑变化,人情冷暖世态炎凉这就是冷暖人生路,这是我一个网友说的话,这张图片是他QQ clannad全CG存档怎么用?全是不懂的字啊!!! 初中有没有去同学家或兄弟家,然后偷摸的经历 我偷了同学的手机,被他们发现了,我该怎么办 ? 如果你的孩子偷了同学的东西,家长要如何跟老师说,承认错误 我堂弟从初一上册偷拿同学东西(钱,手机,之类的)一直到初二上册,有一次还拿过? 我侄子是问题少年有小偷小摸的习惯,去上初中才一个星期就偷同学的钱,现在不在学校,如果不管,会害人 为什么参与到同学们抽烟喝酒当中就比在家偷摸尝试更容易上瘾? 同学有小偷小摸的行为,我怎么办 高中生在校已记过一次后又去偷拿同学零食吃会被开除吗? 6.正读初中的魏某曾被评为“三好学生”,但是自从结识了社会上游手好闲的“朋友”后,他开始小偷小摸, css和 js 对网站优化有哪些不好的地方? 我的手机设置的该设置了,也下载了豌豆荚,为什么还是连接不了电脑? 奥斯卡值多少钱? 奥斯卡奖杯的介绍 贞度叔陵将有异志翻译 奥斯卡奖杯是什么样子的 孔愉字敬康文言文翻译 乐羊子妻传翻译和原文 贞观政要 贪鄙原文及翻译 奥斯卡奖的奖杯 求&lt;&lt;左传 僖公 11年&gt;&gt;的全文翻译