前端页面性能优化方式

时间:2021-08-08 06:12:04

避免内嵌/嵌入代码

您有三种基本方法可以在您的页面上包含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}

这将从文件大小中擦除字节,从而导致更快的下载,解析和执行。

对于那些使用诸如SassLessStylus之类的预处理器可以将编译的CSS输出配置为最小化。

有用的工具 / 参考

组合多个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
}

> JSPerf的结果

>注意: 虽然现代浏览器引擎自动优化此过程,但仍然是适合仍然依赖的旧版浏览器的良好做法。

在HTML中的集合的迭代中,作为例如生成的节点列表(NodeListdocument.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.writewindow.onload事件事件执行,替换当前页面的整个内容。

<span>foo</span>
<script>
window.onload = function() {
document.write('<span>bar</span>');
};
</script>

最终页面的结果将只是条形图,而不是预期的foob​​arwindow.onload事件运行后也会发生这种情况。

<span>foo</span>
<script>
setTimeout(function() {
document.write('<span>bar</span>');
}, 1000);
window.onload = function() {
// ...
};
</script>

如果setTimeoutwindow.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>";
}

JSPerf的结果

缩小脚本

就像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");

> JSPerf的结果

用于代替每个

使用本机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请求数量中获得的速度降低。

有用的工具 / 参考

不要在标记 ∞中重新缩放图像

始终定义图像的属性widthheight属性。这将有助于在渲染过程中避免不必要的重绘和反射。

<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扩展至关重要- 从现在开始,它们将成为您最好的朋友。

或者,如果您喜欢在线工具,请访问WebPageTestHTTP存档PageSpeed站点。

一般来说,每个人都将分析您的网站的效果,并创建一个报告,使您的网站成绩加上宝贵的建议,以帮助您解决潜在的问题。

这就是今天!

前端页面性能优化方式

我们希望通过阅读本指南后,您可以让您的网站成型。:)

记住,像生活中的一切事物一样,没有一个银子弹您的应用程序的性能调优是值得的,但不应该是您所有开发决策的唯一基础 - 有时您需要衡量成本和收益。

想要了解更多?查看我们用来写本指南参考资料

有建议吗 发送推文到@BrowserDiet在Github 上的拉动请求

不要忘记与你的朋友分享,让我们为每个人做一个更快的网络。\ O /