Web前端性能优化实战:从网络到JavaScript的完整指南

作者:白帽猫时间:2026-10-21 21:14:31浏览:580

本文深入解析Web前端性能优化的核心策略,涵盖网络层面的资源合并、CDN部署、HTTP协议差异及DNS优化,以及JavaScript层面的图片预加载、惰性模式与映射关系减少分支、第三方脚本异步加载、Cookie与LocalStorage缓存对比,以及事件委托、节流与去抖动等高级技巧,帮助开发者提升页面加载速度与交互流畅度。

网络优化策略

一、网络优化

YSlow提供了23条优化规则,中文参考资源可查阅相关文档。这些规则的核心目标在于消除或减少不必要的网络延迟,并将需要传输的数据量压缩至最低限度。

1)合并压缩CSS、JavaScript、图片,静态资源CDN缓存

利用Gulp等构建工具,可以在开发阶段同步完成资源的合并与压缩工作。

执行合并压缩的主要原因是:HTTP 1.x协议不允许在一个连接上交错接收多个响应数据(即不支持多路复用),因此必须等待前一个响应完全返回后,下一个响应才能开始传输。

这意味着,即使客户端同时发起两个请求,且CSS资源已准备就绪,服务器仍会优先发送HTML响应,随后才交付CSS内容。

网络优化策略

部署CDN旨在让用户访问距离最近的节点资源,从而缩短数据传输往返时间。

HTTP 2.0对HTTP 1.x的诸多限制进行了改进。

2)CSS放顶部,JavaScript放底部

CSS样式表可以并行下载,而JavaScript脚本在加载执行时会造成页面渲染阻塞。

然而存在例外情况:若将行内脚本置于样式表之后,会显著延迟资源下载(表现为样式表下载完成且行内脚本执行完毕后,后续资源才能开始下载)。

这是因为行内脚本可能包含依赖样式表中定义的代码,例如调用document.getElementsByClassName()获取元素时,需确保样式已应用。


<head>
 <link rel="stylesheet" href="css/all-normal.css" type="text/css" />
</head>
<body>
 <div id="content"></div>
 <script>
  var content = '';
  for(i=1; i<1000000; i++)
    content += '写入页面';
  document.getElementById('content').innerHTML = content;
 </script>
 <img src="images/ui.png" />
</body>

下面通过Chrome开发者工具查看具体表现:

网络优化策略

3)优化DNS解析,减少重定向

在进行“女神评选活动”开发时,需在微信环境中访问以获取用户openid。微信获取用户基本信息需经过多个步骤:

首先获取code,再通过code换取openid,最后跳转至静态页面。

由于公司业务划分为多个小组,这短短三步涉及三个小组协作,导致需要重定向多个域名。

下图展示了优化前的瀑布流图,这并非最坏情况,有时访问静态页面耗时超过10秒,完全不可接受。图中显示跳转了4个域名:

网络优化策略

后续策略是不再跳转index域名,而是直接跳转至微信操作域名,从而减少一个域名的跳转。各小组代码虽经优化,但效果仍不理想,仅提速数秒。

最终发现,在与微信服务器交互过程中,DNS解析耗时过长。因此,在服务器host文件中添加记录,直接通过IP地址指向目标。

下图为最终优化结果,虽未实现秒开,但已处于可接受范围:

网络优化策略

JavaScript性能优化

二、JavaScript优化

1)图片预加载

在“秋名山活动”开发中,采用了图片预加载技术。该活动涉及120多张图片。

业务流程简单:用户答题,最后展示评论结果并支持分享。

网络优化策略 

网络优化策略 

网络优化策略

一次性加载所有图片显然是低效做法。最终决定,在页面载入时先加载通用图片。

在答题过程中,当前页面预先加载后续页面的图片,防止访问新页面时出现图片未展示的情况。同时,对图片进行了适当合并处理。

使用gtmetrix.com测试网站性能,最终瀑布流图显示图片位于其他静态资源之后,从而能尽早向用户展示页面内容:

网络优化策略

优化工作远未结束。在Chrome中分别模拟good 2G、good 3G以及4G网络环境后,结果显示仍有较大优化空间。

good 2G网络环境下:

  网络优化策略

good 3G网络环境下:

  网络优化策略

4G网络环境下:

  网络优化策略

预加载原理可参考《图片预加载与懒加载》一文,仍有很大优化空间。

2)减少分支

编写业务逻辑时,常使用if else、switch等条件判断。频繁执行大量判断会严重影响性能。

因此,可通过多种方式避免过多的条件分支。

1. 惰性模式

此概念源自《JavaScript设计模式》一书。

通过对象重定义来屏蔽原对象中的分支判断,从而减少每次代码执行时的重复性分支判断。

惰性模式分为两种:第一种在文件加载后立即执行对象方法来重定义;第二种在第一次使用方法对象时进行重定义。

公司有一个页面需提供给第三方APP,最终发现第三方APP不支持localStorage缓存,因此必须采用兼容方案。

为避免每次调用方法时都进行判断,采用加载后立即重定义的方式:


var getFn = function() {
 if (sore.enabled)
  return sore.get;
 return cookie.get;
}();
var setFn = function() {
 if (sore.enabled)
  return sore.set;
 return cookie.set;
}();

2. 建立映射关系

页面中常需弹出提示框,为此自行开发了一个组件,但弹出框有多种款式。

若使用简单工厂模式创建,难免涉及switch分支判断。后续改为通过赋予不同key值来管理,并可缓存起来,仅初始化一次。

网络优化策略网络优化策略


/**
 * 弹出框单例模式
 */
var factories = {};
var DialogFactory = function(type, options) {
 if (factories[type])
  return factories[type];
 return factories[type] = new iDialog(options);
};
/**
 * 提示框
 */
var Alert = function(content, options) {
 var d = DialogFactory('alert', options);
 //其他逻辑省略
 return d;
};
/**
 * 确认框
 */
var Confirm = function(content, options) {
 var d = DialogFactory('confirm', options);
 //其他逻辑省略
 return d;
};

3)第三方代码异步加载

对于百度统计、微信SDK等第三方代码,完全可以在业务资源加载完毕后再添加。


/**
 * 百度统计设置
 */
util.baidu = function(key) {
 global._hmt = global._hmt || [];
 (function() {
  var hm = document.createElement("script");
  hm.src = "//hm.baidu.com/hm.js?" + key;
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(hm, s);
 })();
};

4)cookie与localStorage缓存

利用缓存可减少与服务器的通信,实现本地操作。

公司有一个查违章业务,在本地添加好车辆后,再次进入页面时需能直接选择事先添加好的车辆。

最理想的方式是添加好后,在本地缓存起来,下次进入直接调用缓存数据。

  网络优化策略

优先使用localStorage,下表为两者对比:

cookie

localStorage

数据生命周期

可设置失效时间,除非被清除,否则永久保存

数据大小

大约4KB,大约5M

与服务器通信

每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 不参与和服务器的通信

本地存储,之前的历史大概如下图所示:

网络优化策略

localStorage在浏览器兼容方面,IE8居然也支持了。

网络优化策略

5)事件委托

使用事件委托技术能让你避免对特定的每个节点添加事件监听器。

事件监听器被添加到它们的父元素上,通过事件冒泡触发执行。

在开发过程中,经常会出现动态添加元素的情况。

如果每次都重新绑定一次事件,会产生很多多余操作。而绑定在此元素的父级,就只需绑定一次即可。


document.getElementById('ul').onclick = function(e) {
 var e = e || window.event,
  tar = e.target || e.srcElement;
 if (tar.nodeName.toLowerCase() == 'li') {
  tar.style.background = 'black';
 }
}
6)节流与去抖动

节流(throttle):预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。

例如mousemove事件、window对象的resize和scroll事件。

去抖动(debounce):当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。

例如文本输入keydown事件,keyup事件,做autocomplete等。

节流与去抖动最大的不同在于计算最后执行时间的方式。著名的开源工具库underscore中有内置了两个方法。

在做公司内部的一个系统的时候,需要方希望在左右滚动表格的时候,能将第一列固定在最左边,方便查看。

为了让操作能更流畅,我再这里用了节流,有些浏览器会出现卡顿,就得需要增加周期时间。

网络优化策略

前端开发实用技巧

三、小技巧

1)在手机中打印变量

在移动页面开发时经常需要调试字段,又不能用console.log,每次alert的话,碰到对象就看不到内容了。

只能自己写个小方法来打印出来,JSON.stringify,通过这个方法能够方便的实现功能。


var print = function(obj, space) {
 space = space || 4;
 var html = JSON.stringify(obj, null, space);
 html = html.replace(/\n/g, '<br>').replace(/\s/g, '&nbsp');
 var pre = document.createElement('pre');
 var div = document.createElement('code');
 pre.style.cssText = 'border:1px solid #000;padding:10px;background:#FFF;margin-bottom:20px;';
 div.innerHTML = html;
 pre.appendChild(div);
 var body = document.querySelector('body');
 body.insertBefore(pre, body.children[0]);
};

print({a:1, b:'demo', c:{text:'content'}});

网络优化策略

2)chrome插件JSON-handle

服务器返回的很多都是JSON格式的数据,通常写好后给你个接口,顺便给你几个demo参数。

在浏览器中打开后,就是一串字符串,但要给人看的话,就得格式化一下了,这个插件就是用来让人看的。

网络优化策略

作者最新文章
相关文章
更多