避免内嵌/嵌入代码∞
✎您有三种基本方法可以在您的页面上包含CSS或JavaScript:
1)内联: CSS内部定义一个style
属性和JavaScript内部的一个onclick
属性,例如在任何HTML标签中;
2)嵌入式: CSS在<style>
标签内部定义,JavaScript内部<script>
标记;
3)外部: CSS中从加载<link>
和从JavaScript的src
所述的属性<script>
标记。
前两个选项尽管减少了HTTP请求的数量,实际上增加了您的HTML文档的大小。但是,当您拥有小资产并且提出请求的成本更高时,这可能是有用的。在这种情况下,运行测试来评估速度是否有实际的提升。另外请务必评估页面及其受众的目的:如果您希望人们只访问一次,例如对于您从未期望返回访问者的一些临时活动,内联/嵌入式代码将有助于减少HTTP请求数量。
>避免在HTML中间手动创建CSS / JS(首选使用工具自动化此过程)。
第三个选项不仅改善了代码的组织,而且使浏览器可以缓存代码。对于大多数情况,此选项应该是首选的,特别是在处理大文件和大量页面时。
风格顶部,脚本底部∞
✎当我们放置样式表时,<head>
我们允许页面逐渐呈现,这给我们的用户印象是页面正在快速加载。
<head>
<meta charset="UTF-8">
<title>Browser Diet</title>
<!-- CSS -->
<link rel="stylesheet" href="style.css" media="all">
</head>
但是如果我们将它们放在页面的末尾,页面将不会被渲染,直到下载并应用CSS。
另一方面,当处理JavaScript时,将脚本放置在页面底部是重要的,因为它们在加载和执行时阻止渲染。
<body>
<p>Lorem ipsum dolor sit amet.</p>
<!-- JS -->
<script src="script.js"></script>
</body>
> 参考文献
尝试异步∞
✎要解释这个属性对于更好的性能是有用的,最好先了解当我们不使用它时会发生什么。
<script src="example.js"></script>
在这种形式中,页面必须等待脚本被完全下载,解析和执行,然后才能解析并呈现任何以下的HTML。这可以显着增加页面的加载时间。有时可能需要这种行为,但通常不需要。
<script async src="example.js"></script>
该脚本被异步下载,而页面的其余部分继续被解析。一旦下载完成,该脚本就被保证被执行。请记住,不会以特定的顺序执行多个异步脚本。
> 参考文献
CSS
缩小您的样式表∞
✎为了维护可读的代码,写一个注释并使用缩进是个好主意:
.center {
width: 960px;
margin: 0 auto;
}
/* --- Structure --- */
.intro {
margin: 100px;
position: relative;
}
但是对于浏览器来说,这些都不重要。为此,请务必记住通过自动化工具来缩小CSS。
.center{width:960px;margin:0 auto}.intro{margin:100px;position:relative}
这将从文件大小中擦除字节,从而导致更快的下载,解析和执行。
组合多个css文件∞
✎组织和维护风格的另一个最佳做法是将它们分成模块化组件。
<link rel="stylesheet" href="structure.css" media="all">
<link rel="stylesheet" href="banner.css" media="all">
<link rel="stylesheet" href="layout.css" media="all">
<link rel="stylesheet" href="component.css" media="all">
<link rel="stylesheet" href="plugin.css" media="all">
但是,这些文件中的每一个都需要HTTP请求(我们知道浏览器只能并行下载有限数量的资源)。
<link rel="stylesheet" href="main.css" media="all">
所以结合你的CSS。拥有较少数量的文件将导致更少的请求数量和更快的加载页面。
想要拥有两个世界的最好的?通过构建工具自动执行此过程。
喜欢<链路>过@import∞
✎在页面中包含一个外部样式表有两种方法:通过<link>
标签:
<link rel="stylesheet" href="style.css">
或通过@import
指令(在外部样式表或内联<style>
标签中):
@import url('style.css');
当您通过外部样式表使用第二个选项时,浏览器不能并行下载资产,这可能会阻止其他资产的下载。
> 参考文献
JAVASCRIPT的
加载第三方内容异步∞
✎谁从未加载第三方内容来嵌入Youtube视频或/ tweet按钮?
最大的问题是,这些代码并不总是有效地传递,无论是通过用户的连接,还是与托管的服务器的连接。或者该服务可能暂时关闭,甚至被用户或其公司的防火墙阻止。
为避免在加载网站或更糟糕的情况下成为关键问题,锁定整个页面加载,请始终加载这些代码(或使用Friendly iFrames)。
var script = document.createElement('script'),
scripts = document.getElementsByTagName('script')[0];
script.async = true;
script.src = url;
scripts.parentNode.insertBefore(script, scripts);
或者,如果要加载多个第三方小部件,则可以使用此脚本异步加载它们。
缓存阵列长度∞
✎这个循环无疑是与JavaScript性能相关的最重要的部分之一。尝试优化一个循环中的逻辑,以便每次迭代都有效地完成。
一种方法是存储要覆盖的数组的大小,因此每次迭代循环时都不需要重新计算。
var arr = new Array(1000),
len, i;
for (i = 0; i < arr.length; i++) {
// Bad - size needs to be recalculated 1000 times
}
for (i = 0, len = arr.length; i < len; i++) {
// Good - size is calculated only 1 time and then stored
}
>注意: 虽然现代浏览器引擎自动优化此过程,但仍然是适合仍然依赖的旧版浏览器的良好做法。
在HTML中的集合的迭代中,作为例如生成的节点列表(NodeList)document.getElementsByTagName('a')
尤其重要。这些集合被认为是“实时的”,即当它们所属的元素发生变化时,它们被自动更新。
var links = document.getElementsByTagName('a'),
len, i;
for (i = 0; i < links.length; i++) {
// Bad - each iteration the list of links will be recalculated to see if there was a change
}
for (i = 0, len = links.length; i < len; i++) {
// Good - the list size is first obtained and stored, then compared each iteration
}
// Terrible: infinite loop example
for (i = 0; i < links.length; i++) {
document.body.appendChild(document.createElement('a'));
// each iteration the list of links increases, never satisfying the termination condition of the loop
// this would not happen if the size of the list was stored and used as a condition
}
> 参考文献
避免使用document.write∞
✎使用document.write
导致对页面的依赖关系返回到完全加载。
开发人员已经废除了这个(坏的)实践,但仍然需要使用它的情况,就像在一些JavaScript文件的同步回退中一样。
例如,如果Google的CDN没有响应,HTML5 Boilerplate会使用此技术在本地加载jQuery 。
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.9.0.min.js"><\/script>')</script>
>注意: document.write
在window.onload
事件或事件后执行,替换当前页面的整个内容。
<span>foo</span>
<script>
window.onload = function() {
document.write('<span>bar</span>');
};
</script>
最终页面的结果将只是条形图,而不是预期的foobar。当window.onload
事件运行后也会发生这种情况。
<span>foo</span>
<script>
setTimeout(function() {
document.write('<span>bar</span>');
}, 1000);
window.onload = function() {
// ...
};
</script>
如果setTimeout
在window.onload
事件之后执行调度的功能,结果将与前面的示例相同。
> 参考文献
最小化重复和回流∞
✎当某些属性或元素被更改时,当有任何重新渲染DOM的过程时会引起重新绘制和重新排列。
当更改元素的外观而不更改其布局时,将重新启动。尼古拉·沙利文(Nicole Sullivan)把这一点描述为改变一种风格background-color
。
回流是最昂贵的,因为它们是由更改页面布局引起的,例如更改元素的宽度。
毫无疑问,应避免过度的回流和重涂,而不是这样做:
var div = document.getElementById("to-measure"),
lis = document.getElementsByTagName('li'),
i, len;
for (i = 0, len = lis.length; i < len; i++) {
lis[i].style.width = div.offsetWidth + 'px';
}
做这个:
var div = document.getElementById("to-measure"),
lis = document.getElementsByTagName('li'),
widthToSet = div.offsetWidth,
i, len;
for (i = 0, len = lis.length; i < len; i++) {
lis[i].style.width = widthToSet + 'px';
}
设置style.width
时,浏览器需要重新计算布局。通常,更改多个元素的样式只会导致一个回流,因为浏览器在需要更新屏幕之前不需要考虑它。然而,在第一个例子中,我们要求offsetWidth
,这是元素的布局宽度,所以浏览器需要重新计算布局。
如果您需要从页面中读取布局数据,请在设置任何更改布局的任何内容之前将其全部放在一起,如第二个示例所示。
避免不必要的dom操纵∞
✎每当你触摸DOM,而不需要这样做,熊猫就会死亡。
认真地,DOM元素的浏览是昂贵的。尽管JavaScript引擎变得越来越强大和快速,但总是喜欢优化DOM树的查询。
最简单的优化之一是经常访问的DOM元素的缓存。例如,不是每循环查询DOM,而是一次查询一次,并将结果保存在一个变量中,而不是使用循环的每次迭代。
// really bad!
for (var i = 0; i < 100; i++) {
document.getElementById("myList").innerHTML += "<span>" + i + "</span>";
}
// much better :)
var myList = "";
for (var i = 0; i < 100; i++) {
myList += "<span>" + i + "</span>";
}
document.getElementById("myList").innerHTML = myList;
// much *much* better :)
var myListHTML = document.getElementById("myList").innerHTML;
for (var i = 0; i < 100; i++) {
myListHTML += "<span>" + i + "</span>";
}
缩小脚本∞
✎就像CSS一样,要保持可读的代码,写一个注释并使用缩进是个好主意:
BrowserDiet.app = function() {
var foo = true;
return {
bar: function() {
// do something
}
};
};
但是对于浏览器来说,这些都不重要。为此,请务必记住通过自动化工具来缩小您的JavaScript。
BrowserDiet.app=function(){var a=!0;return{bar:function(){}}}
这将从文件大小中擦除字节,从而导致更快的下载,解析和执行。
将多个js文件合并成一个∞
✎组织和维护脚本的另一个最佳做法是将它们分为模块化组件。
<script src="navbar.js"></script>
<script src="component.js"></script>
<script src="page.js"></script>
<script src="framework.js"></script>
<script src="plugin.js"></script>
但是,这些文件中的每一个都需要HTTP请求(我们知道浏览器只能并行下载有限数量的资源)。
<script src="main.js"></script>
所以结合你的JS。拥有较少数量的文件将导致更少的请求数量和更快的加载页面。
想要拥有两个世界的最好的?通过构建工具自动执行此过程。
JQUERY的
总是使用最新版本的jquery∞
✎核心的jQuery团队一直在寻求通过更好的代码可读性,新功能和现有算法的优化来改进库。
因此,如果要将其复制到本地文件,请始终使用最新版本的jQuery,这是始终可用的:
http://code.jquery.com/jquery-latest.js
但是,请勿在<script>
代码中引用该网址,否则将来会出现问题,因为较新版本会在您有机会测试之前自动提供给您的网站。相反,链接到您需要具体的最新版本的jQuery。
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
就像聪明的巴尼·斯廷森(Barney Stinson)所说:“新的总是更好”:P
> 参考文献
选择器∞
✎选择器是使用jQuery最重要的问题之一。有许多不同的方式来选择从DOM元素,但并不意味着它们具有相同的性能,可以使用类,ID或类似的方法选择一个元素find()
,children()
。
在所有这些中,选择一个ID是最快的,因为它基于本机DOM操作:
$("#foo");
用于代替每个∞
✎使用本机JavaScript函数几乎总是导致执行速度比jQuery更快。因此,jQuery.each
使用JavaScript自己的for
循环,而不是使用该方法。
但是要注意,即使for in
是原生的,在许多情况下,它的性能会差一些jQuery.each
。
经过测试的for
循环让我们有机会通过缓存我们正在迭代的集合的长度来加快速度。
for ( var i = 0, len = a.length; i < len; i++ ) {
e = a[i];
}
使用反向while
和反向for
循环是社区中的热门话题,经常被引用为最快的迭代形式。然而,通常避免不那么清晰。
// reverse while
while ( i-- ) {
// ...
}
// reverse for
for ( var i = array.length; i--; ) {
// ...
}
> JSPerf / References的结果
不要总是使用jquery ...∞
✎有时,香草JavaScript可以更容易使用,并且具有比jQuery更好的性能。
考虑以下HTML:
<div id="text">Let's change this content</div>
而不是这样做:
$('#text').html('The content has changed').css({
backgroundColor: 'red',
color: 'yellow'
});
使用纯JavaScript
var text = document.getElementById('text');
text.innerHTML = 'The content has changed';
text.style.backgroundColor = 'red';
text.style.color = 'yellow';
它的简单和多快。
> JSPerf / References的结果
图片
使用css精灵∞
✎这种技术是将各种图像分组成单个文件。
然后用CSS定位它们。
.icon-foo {
background-image: url('mySprite.png');
background-position: -10px -10px;
}
.icon-bar {
background-image: url('mySprite.png');
background-position: -5px -5px;
}
因此,您大大减少了HTTP请求的数量,并避免了页面上其他资源的任何潜在延迟。
使用精灵时,请避免在图像之间留下太多空白。这不会影响文件的大小,但会影响内存消耗。
尽管几乎每个人都知道精灵,但是这种技术并没有得到广泛的应用 - 也许由于开发人员没有使用自动化工具来生成精灵。我们已经强调了一些可以帮助你解决这个问题。
数据uri∞
✎这种技术是使用CSS精灵的替代方法。
一个数据-URI是内联的URI,你通常会指向的内容的方式。在这个例子中,我们使用它来内联CSS背景图像的内容,以减少加载页面所需的HTTP请求数量。
之前:
.icon-foo {
background-image: url('foo.png');
}
后:
.icon-foo {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII%3D');
}
IE8及以上版本的所有浏览器都支持这种base64编码技术。
这种方法和CSS sprite方法都需要构建时间工具才能维护。该方法具有不需要手动精简放置的优点,因为它们在开发过程中将图像保存在单个文件中。
但是如果你有大的图像,那么你的HTML / CSS的大小会越来越大。如果您在HTTP请求期间不使用HTML / CSS,则建议不要使用此方法,因为大小开销可能会使您从最小化HTTP请求数量中获得的速度降低。
不要在标记 ∞中重新缩放图像
✎始终定义图像的属性width
和height
属性。这将有助于在渲染过程中避免不必要的重绘和反射。
<img width="100" height="100" src="logo.jpg" alt="Logo">
知道这一点,拥有700x700像素图像的约翰Q.开发者决定使用这种技术将图像显示为50x50像素。
开发人员没有意识到的是,几千个不必要的千字节将通过电线发送。
始终牢记:只是因为您可以用HTML定义宽度和高度的图像,这并不意味着您应该这样做来缩小大图像。
> 参考文献
优化您的图像∞
✎图像文件包含大量在网络上无用的信息。例如,JPEG照片可以具有来自照相机的Exif元数据(日期,相机型号,位置等)。PNG包含有关颜色,元数据,有时甚至是微型嵌入缩略图的信息。浏览器都不使用这些功能,并有助于文件大小化。
存在可用于图像优化的工具,可以删除所有这些不必要的数据,并且在不降低质量的情况下为您提供更细的文件。我们说他们执行无损压缩。
优化图像的另一种方法是以视觉质量为代价进行压缩。我们称这些有损优化。例如,导出JPEG时,您可以选择质量等级(0到100之间的数字)。考虑性能,总是选择尽可能低的视觉质量仍然可以接受的数字。另一种常见的有损技术是减少PNG中的调色板或将PNG-24文件转换为PNG-8。
为了提高用户感知的性能,您还应该转换所有JPEG文件。逐行JPEG具有很好的浏览器支持,创建非常简单,并且没有显着的性能损失。上图是图像将在页面上显示(见演示)。
奖金
诊断工具:你最好的朋友∞
✎如果您想参与这个网络性能的世界,那么在浏览器中安装YSlow扩展至关重要- 从现在开始,它们将成为您最好的朋友。
或者,如果您喜欢在线工具,请访问WebPageTest,HTTP存档或PageSpeed站点。
一般来说,每个人都将分析您的网站的效果,并创建一个报告,使您的网站成绩加上宝贵的建议,以帮助您解决潜在的问题。
这就是今天!∞
✎我们希望通过阅读本指南后,您可以让您的网站成型。:)
记住,像生活中的一切事物一样,没有一个银子弹。您的应用程序的性能调优是值得的,但不应该是您所有开发决策的唯一基础 - 有时您需要衡量成本和收益。
想要了解更多?查看我们用来写本指南的参考资料。
有建议吗 发送推文到@BrowserDiet或在Github 上的拉动请求。
不要忘记与你的朋友分享,让我们为每个人做一个更快的网络。\ O /