记得面试现在这份工作的时候,一位领导语重心长地谈道——当今的世界是互联网的世界,IT企业之间的竞争是很激烈的,如果一个网页的加载和显示速度,相比别人的站点页面有那么0.1秒的提升,那也是很大的一个成就。

然后我不知道怎么写下去了,就在群里问了那群狗头军师,结果是这样的。。。

好的,是时候“语锋一转”切回主题了 —— 如何提升我们站点页面的访问速度、减少等待时间,从而最大化地提升用户访问体验呢?

针对这个问题,我们今天会从前端的角度来提出系列解决方案,它们都能有效地提升你页面的访问速度。

一. 减少对服务器的文件请求

常规的HTTP请求属于“请求”-“应答”-“断开”形式的短连接,每一个独立的资源我们都会向服务器发去一份get请求,再等服务端将我们需要的文件传回来。每一次资源的请求都实实在在地耗费了一次“连接-等待-接收”的时间(当然将http请求设为keep-alive长连接状态可以减少“连接”的次数和时间),如果我们能有效减少对服务器文件的请求次数,便意味着我们可以从这块省下一些页面等待时间,也可以顺便减少服务器的负担。

对于这个解决方案,我们可以这么做:

1. 使用css sprite技术合并多个图片为单个图片文件,实际使用时通过background-position来定位背景位置(相信大家第一个想到的也是这个吧);

2. 合并多个css样式文件为单个样式文件,合并多个脚本为单个脚本,再在页面中引用合并后的样式/脚本文件。对于这个你可以使用r.js来帮忙(看我这篇文章),但我个人倒是不怎么推荐这个方法,因为合并了文件之后,多个页面之间公共部分的样式/脚本文件就无法缓存到客户端了;

3. 使用base64编码来展示图片。就如图github 404页面那样:

你可以使用这个工具来帮你把图片转换为base64编码的文件流,但常规只推荐你把这种方式使用在用户重复访问量较少的页面,因为它们虽然无须从服务端get一遍,但也无法缓存在客户端,导致用户每次访问页面都要重新渲染一次。而且冗长的文件流代码会占用你页面很大的代码空间,维护起页面来估计也会挺心塞;

4. 将小块的css、js代码段直接写在页面上,而非在页面引入独立的样式/脚本文件。相信有的朋友看惯了“保持结构 (标记)、表现 (样式)、行为 (脚本)三者分离”的规范,对此观点可能有些意见。只能说规范不是教条,适合自己的才是硬道理。直接把小段的、复用率低的样式/脚本直接写于页面上带来的利还是大于弊的(弊可能也就是增大了页面代码量、不那么好维护了点)。反观所有主流门户网站的页面源文件,基本没有一个是把样式/脚本都全部作为外部文件引入的(无论他们是否从减少服务器请求这点出发,事实都是这样),配合gzip压缩会是很好的选择;

5. 利用http-equiv="expires"元标签,设定一个未来的某时间点作为页面文件过期时间,用户在过期时间之前所获取到的页面文件都仅从缓存中去取。最好的形式是给资源名称加md5之类的唯一标识符后缀,然后设置一段较长的过期时间,同时请后端配置好ETag。这块的内容可以参考这篇文章。

二. 减少文件大小

文件太大(特别是图片)导致加载时间较长,往往都是影响页面加载体验的头号大敌,那么尽可能减少请求文件的大小便是相当重要的事情了,我们可以做的事情有:

1. 压缩样式/脚本文件,就此你可以使用gulp或者grunt来实现这点,它们均能很好地减少css/js文件的大小(对于js还能起到混淆变量、函数名的作用);

2. 针对性选择图片格式,在无透明背景需求下,对于颜色较单一、无色彩渐变的图片仅使用gif格式,对于jpg图片也可按照其清晰度要求,在导出jpg的时候选择对应的“品质”进行优化:

另外,你可以使用TinyPNG或者腾讯智图这样的工具来压缩图片(极力推荐)

如果你喜欢尝鲜,可以学淘宝那样使用webp图片格式,它能很好地优化同画质下的文件大小:

如果你对webp感兴趣,可以查阅这里;

3. 使用Font Awesome来替代页面上的图标,其原理是使用@font-face让用户下载一个非常小的UI字体包,把页面上用到的图标以字符的形式来显示,从而减少了图片需求和图标文件大小。

三. 适度使用CDN

使用CDN有几个好处:如果用户在其它站点下载过这个CDN资源,那么来我们站点仅仅从缓存获取即可;减少了对自己站点服务器的文件请求(外部CDN的情况下),减少服务器负担;多个域会使浏览器允许异步下载资源的最大数量增多,比如一个站点只从一个域来请求资源,那么FireFox只允许同时刻最多异步下载2个文件,但如果使用了外部CDN来引入资源,那么FF允许在同时异步下载本域中的两个资源外,还额外允许同时异步下载另一个域(CDN)下的2个资源。

但是使用CDN有一个很大的问题——增加了dns解析的开销,如果一个页面同时引入了多个CDN的资源,可能会因为dns解析而陷入较多的等待时间,导致得不偿失。

对于这个问题,常规是建议一个站点下只使用同一个可靠、快速的CDN来引入各种所需资源即可,也就是说,建议一个页面从2个不同的域(比如站点域和CDN域)下来请求资源是最佳的选择(据说这个结论是雅虎前端工程师提出的,这里有一篇很不错的文章)。

四. 延迟请求、异步加载脚本

在各主流浏览器下,常规情况,我们的脚本文件跟随其它资源文件一样都是异步下载的,但这里存在一个问题——比如FireFox下载好脚本后的一小段时间内会有“执行阻塞”的情况发生,也就是说浏览器下载好脚本后执行它的这段时间里,浏览器的其它行为被阻塞,导致页面上的其它资源都是无法被请求和下载的:

如果你页面里存在js代码执行时间过长的情况,那么用户就会明显感觉到页面的延迟。解决这个问题有一个简单的方法——将脚本请求标签放置到</body>结束标签前,使得页面上的脚本成为最后被请求的资源,自然也不会阻塞其它页面资源的请求事件了。

另外,虽然上面提到“我们的脚本文件跟随其它资源文件一样都是异步下载的”,但异步下载不代表异步执行,为了严格保证脚本逻辑顺序和依赖关系的正确性,浏览器会按照脚本被请求的先后顺序来执行脚本。那么问题就来了——如果页面上的脚本依赖关系并不大,甚至没有任何相互间的依赖,那么浏览器的这套规则就仅仅增加了页面请求阻塞时间而已(就像你花大钱买了一笔保险,但被保险期间你平安无事啥都没发生。。。嗯,这个比喻有点反人类。。。)。

解决这个问题的办法无非就是让脚本无阻塞地异步执行,比如给script标签加上defer和async属性或者动态注入脚本(可以参考这里),但这些都不是良好的解决方案,要么存在兼容性问题,要么太麻烦还无法处理依赖。

个人是推荐使用 requireJS(AMD规范) 或 seaJS(CMD规范) 来异步加载脚本并处理模块依赖的,前者将“依赖前置”(预加载所有被依赖脚本模块,执行速度最快),后者走的“依赖就近”(懒加载被依赖脚本模块,请求脚本更科学),你可以根据项目具体需求来选择最合适的。

五. 延迟请求首屏外的文件

先解释下,“首屏”指的是页面初始化时候的页面内容显示区域,也就是页面一加载,用户就首先看到的区域。

比如像京东啊淘宝啊,对于需要滚动页面才能看到的图片内容,都做了类似lazyload的处理,这些无非都是走了代理模式的理念,但的确给用户一个错觉——这个页面更快地加载完了,因为我很快就看到了屏幕上的内容(即使我还没下拉滚动条,而页面后方的文件其实还没真正加载呢)。

我们可以这样实现此方案,不依赖任何lazyload库,拿图片来做示范,我们可以这样编写首屏外的图片(假设某张图片地址是a.jpg)的img标签:

<img src="https://img-blog.csdnimg.cn/2022010702091364327.png" data-src="a.jpg">

如上所示,页面初步加载这张图片的时候是直接以base64的方式(当然你也可以统一使用一张占位图loading.gif来替代)来快速显示一张极小的图片的,而图片本身的真实路径是存在data-src属性内的,我们可以在页面加载结束后再向服务器请求它真实的文件并替换:

function init() {var imgDefer = document.getElementsByTagName('img');for (var i=0; i<imgDefer.length; i++) {if(imgDefer[i].getAttribute('data-src')) {imgDefer[i].setAttribute('src',imgDefer[i].getAttribute('data-src'));} }
}
window.onload = init;

如上是对图片的延迟加载处理,对于视频、音频文件,可以采取完全一样的原理来延迟加载,从而有效减少页面初始化等待时间。

六. 优化页面模块排放顺序

这里有一个很好的例子,比如有一个页面是这样的——左边是侧边栏,用于存放用户的头像啊、资料啊,以及网站投放的广告啊,而右侧是文章内容区域:

那么我们的代码很可能是这样的:

<body><sidebar><!-- 侧边栏内容 --></sidebar><content><!-- 文章内容 --></content>
</body>

于是乎,浏览器按照它的UI单线程准则从上到下先加载了侧边栏,再加载我们的文章。。。

很明显,这样不是一个人性化的加载顺序,我们得弄清楚,页面上各个区域模块,对于用户而言,哪个才是最重要、最应当首先展示的

对于上面的例子,文章内容才应该是用户首先要看到、需要浏览器优先请求和显示的区域。所以我们得修改我们的代码为:

<body><content><!-- 文章内容 --></content><sidebar><!-- 侧边栏内容 --></sidebar>
</body>

当然这里仅仅是用一个小示例来挑起各位的脑洞,懂得举一反三和实际运用才是硬道理。

七. 其它建议

1. 不要在css中使用@import,它会让一个样式文件去等待另一个样式文件的请求,无形中增加了页面等待时间(当然如果走的scss,@import就是另一回事了,呃跑题了~);

2. 避免页面或者页面文件重定向查找,这相当于你走进了一间卫生间,然后看到上面的牌子说“此处不同,请去前面左拐的卫生间”,又得重走一遍;

3. 减少无效请求——比如通过css/js来请求一个不存在的资源,可能会导致较长的等待和阻塞(直到它返回错误信息);

4. 无论你是否决定将脚本放到页尾,但一定要保障脚本放置于样式文件后方;

5. 文件在小于50K的时候,直接读取文件流会比从文件系统中去读取文件来的快些,大于50K则相反。比如有一张图片,如果它小于50K,我们可以将它转为二进制数据存储在数据库中,页面若要读取该图片则从数据库上来读取,若文件大小大于50K,那建议存放在可访问的文件夹中以文件的形式来读取即可;

6. 使用 cookie-free domains 来存放资源,减少无用cookie传输的网络开销(可以参考这篇文章);

7. 不重要的样式文件可以走无阻塞渲染的加载形式,可参考这篇文章;

8. 配置.htaccess文件、走Gzip页面压缩形式、开启keep-alive连接模式等后端解决方案,这边就不细说了。

相信页面提速的方案绝对不仅仅局限于上面提到的这些,而且每个项目都有着各种需求和情况,只能按需选择适合自己的方案。

但最重要的还是——尽量把用户的体验放在第一位,无论是页面的加载或者交互,都应当多从用户角度切入去思考和设计最优选的方案,这样相信你一定能做出出色、受欢迎的作品。

今天聊的就是这些,共勉~

转载于:https://www.cnblogs.com/yelongsan/p/6292960.html

java web 页面提速相关推荐

  1. 【项目经验】Java web 页面跳转中文乱码

    小编最近在敲demo的时候遇到了Java web 页面跳转后中文乱码的问题,小编也是使劲浑身解数才把页面给弄好了,现在来总结一下. 问题再现: 小编在MyEclipse中试了多种方法,小编在这里一一总 ...

  2. 在Java web页面使用ECharts制作图表

    前言 因为最近在做一项课设,需要可视化,因此选择echarts.但因为太久没用了,所以忘记了怎么在web页面引用echarts,在这里做个记录,开发工具是VSCODE. 一.下载echarts.min ...

  3. java web页面调用海康摄像头

    之前做过web页面调用海康显示4个摄像头.网上web调用的确实比较少,我做的时候参考了http://blog.csdn.net/lucius93/article/details/75308165,但也 ...

  4. java 开发web页面跳转,javaweb页面跳转

    java动态web页面,JavaWEB入门,javaweb页面跳转,javaweb页面登录 他们之间的联系是什么 8 serverlet 的生命周期及各阶段的作用 9 java web两种跳转方式分别 ...

  5. java web 2.0 下载地址_《征服Ajax Web2.0快速入门与项目实践(Java)》[PDF]

    征服Ajax Web2.0快速入门与项目实践(Java) 作者:张桂元 贾燕枫 姜波 基本信息 ·出版社:人民邮电出版社 ·页码:300 页 ·出版日期:2006年 ·ISBN:7115148031 ...

  6. java实现页面高效刷新_selenium高效应对Web页面元素刷新的实例讲解

    当我们在页面上进行selenium.type()或者selenium.click()操作的时候,往往需要需要等待一个元素的出现,对于一般的网页,当我们进入一个新页面的时候,往往会使用selenium. ...

  7. Java 技术篇 - 从指定的web网页页面中读取html内容实例演示,从http协议下的url地址中读取web页面内容方法

    实例为从我文章中读取标题. 通过 class 属性锁定标题元素,把匹配的内容打印出来. 下面是源码: package com.test.test;import java.io.*; import ja ...

  8. java 图形校验_java图形验证码生成工具类 web页面校验验证码

    java图形验证码生成工具类 web页面校验验证码 发布于 2020-7-14| 复制链接 摘记: 最近做验证码,参考网上案例,发现有不少问题,特意进行了修改和完善.验证码生成器: ```java i ...

  9. Java Web项目,Android和微信小程序的初始页面配置

    Java Web项目 我们在Eclipse里开了Java Web项目之后,Run As Tomcat或者Apache服务器,本地运行,如果直接用http://localhost:8080访问项目,会发 ...

最新文章

  1. MFC应用程序中添加控制台窗口
  2. 与用户登录shell相关的文件/etc/profile,~/bashrc等浅析
  3. linux yum安装redis5.0,CentOS 7安装Redis 5.0.5并加入Systemd服务
  4. Python中的for in if 用法
  5. 8. JavaScript HTML DOM 事件
  6. 14.6.4 Configuring the Memory Allocator for InnoDB 配置InnoDB 内存分配器
  7. 重写Java中equals和hashcode方法的一般规则
  8. Linux 下设置java环境和tomcat安装
  9. windows64位搭建汇编(包含汇编dosbox , masm文件,link文件和debug调试)以及debug调试命令(dosbox调试汇编程序的简单使用教程)
  10. 基于java的超市管理系统设计(含源文件)
  11. java 调用 axis2_java调用WebService服务 axis2实现方式
  12. 博饼游戏c语言,2015中秋博饼游戏规则
  13. 怎样让数学学渣看懂什么叫做傅里叶变换?
  14. 男生学计算机会计,男生学习会计专业好吗
  15. office xls Hyperlink
  16. Mock工具之Moco使用教程
  17. Corel VideoStudio会声会影2022旗舰版本视频剪辑软件
  18. HDU 1042 N!(大数阶乘)
  19. Learning with Noisy Correspondencefor Cross-modal Matching(NCR)--文献翻译
  20. mysql的ole db 访问接口msdasql的数据源对象_无法从链接服务器 (null) 的 OLE DB 访问接口 MSDASQL 获取列信息...

热门文章

  1. conda deactivate python3_python3的配置解决
  2. 代码 控制unity 暂停 编辑器_Unity3D 报错解决方案及常用功能收集
  3. 【ruoyi若依】flot 图表跑版
  4. bat/cmd 抛出错误码和捕获错误
  5. jQuery的AJAX
  6. 计算机网络优化是啥,浅析计算机网络优化的方案.doc
  7. mysql二进制日志内容说明_MySQL二进制日志相关问题详细说明
  8. android 仿微信选取相册_Android 仿微信 相册多图选择器
  9. streak10刷Linux,streak 10
  10. xml文件转换成图片_如何把pdf文件转换成图片?