如果你的网站3秒钟没有响应,人们就会失去兴趣了。为了满足响应快这个愿望,需要一个不同的方法在手机上进行分析,设计和测试。
这篇文章将会对Johan Johansson在2013年4月提出" 怎样让你的网站在手机上也很快"的这种理念进行扩展。我们将提出论证方法来确认人们在手机上与网站的交互方式和以前是不一样的,特别是设计也是基于此理念的。我们的目标不仅仅是提高网站性能,而且也要增加客户收入的。
我们将关注手机两个特性,这两个特性短期内也不会有变化:电池容量小,屏幕小。
电量小
手机的通讯要用无线电,但手机的电池很小,所以要非常谨慎的用电以防止把电用光。这样,如果无线电不用的时候就会迅速关掉,这样就增加了网页出现的时间。 2G和3G无线技术需要2秒钟来建立HTTP链接。如果我接受“用户会在3秒后失去兴趣”的观点的话,那我们的网站只有1秒来响应了。想想这“黄金般的一 秒”吧。
最大化利用这“黄金一秒”
小屏幕
在物理世界中,广告牌和杂志的内容都是根据媒介的大小和观看距离来定制的。在数字世界中,一个典型的中档智能手机拥有几乎6平方英寸大小的屏幕。15英寸的MacBook Pro电脑屏幕拥有超过100平方英寸的大小。这样,我们不仅可以通过减少发送到手机端的内容优化网站性能,而且可以优化业务流程来提高网站所有者的投资回报。
本文的代码示例是由.NET提供。我已经在companion article文章中展示了用PHP, Java, C 和Python达到同样的效果。我在这篇文章的结尾会解释为什么选用.NET。
最大化利用 “黄金一秒”
网站设计者和开发者们常常想当然的认为用户应该用高带宽Wi-Fi和固网来连接。响应式网站设计(RWD)强制在不同设备上(不论其性能好坏)显示相同的内容、导航和业务流程,限制了创新。
确保我们能够容易的进行性能测量,进行用户行为监控的基于不同设备特性的解决方案以及低带宽设备网页访问优化都需要最大限度的利用这“黄金一秒”。
模拟现实网络
现实移动带宽模拟测试是一个必不可少的移动Web性能测试。很多100美元以下的廉价无线路由都提供了限制带宽功能,测试仅仅只涉及到了局域网内的客户端的上行和下行带宽限制功能。如果路由不支持这个功能话,那么试试用 DD-WRT(DD-WRT是一个开源升级固件,可以替代目前主流路由的默认操作系统)来限制带宽。
我用DD-WRT升级了Linksys E3000路由。路由升级的过程非常简单,DD-WRT官网上提供了完整的说明。
安装好DD-WRT后去到QoS菜单,启用带宽限制。设置上行和下行带宽的值,我习惯将下行带宽设置为256kbps,上行带宽设置为28kbps来模拟移动网络的平均带宽。
现在无论是以Wi-Fi或网线连接到路由器的设备的带宽都被人为的限制了。我们可以监视带宽实际的使用情况。
虽然这种测试方法并没有包括随机的掉线、可变带宽条件和由信号强弱引起的延迟等情况,但是比起你在快速、低延迟带宽下做的其他测试效果要好。在网站开发初 期,这是一个在开发过程中对Web性能进行非正式测试的简单的方法,能够确保你在正式测试过程中不出现任何讨厌的问题。
你不能管理所不能测量的事
管理顾问 Peter Drucker 曾经说过一句名言:“如果你无法测量某件事,你就无法管理它。”
持续根据设备特性(比如无线支持或屏幕大小)对用户查看的内容进行监控,或多或少将会有助于你识别手机上流行的内容和服务。也许你将看不到任何区别,但是除非你测量过,否则无法确定。
好的日志
Google Analytics 提供了一些关于设备模型的信息,但它缺乏我们需要基于屏幕尺寸和输入方法作出明智决定的细节。幸运的是,一个全面的设备检测库(DDR)可以将此信息添加到现有日志文件中。下面的代码片段可以添加到 .NET网站中,参考51degrees.mobi(可通过 NuGet ) 获取屏幕的物理尺寸和输出到一个简单的CSV文件中。
- // Write a log file containing the current time, and the screen
- // size of the requesting device in inches.
- File.AppendAllText(
- Path.Combine(
- AppDomain.CurrentDomain.BaseDirectory, String.Format(
- "App_Data\\Simple_Log_{0:yyyyMMdd}.csv",
- DateTime.UtcNow)),
- String.Format("{0:s},{1},{2},{3}\r\n",
- DateTime.UtcNow,
- Request.Path,
- Request.Browser["ScreenInchesWidth"],
- Request.Browser["ScreenInchesHeight"]));
第一行是处理请求的日期和时间。第二行是请求的页面。最后两行是设备屏幕的宽度和高度。抓取足够多的数据和平均屏幕的尺寸大小绘制出了下面的图表:
比较设备屏幕的平均大小超过20个月
分析可以缩小到具体的页面。有关设备的特性,操作系统和浏览器也可以被添加到列中。
类似的代码可以使用PHP、Java、Python和其他环境语言。
已有的日志文件
有时,已有的Web页面不能按照上面的方式修改。在这样的情况下,DDR可以用来执行含有用户代理的日志日文的离线分析了。下面的.NET代码是一个实用 的命令行程序,它解析空格分隔的日志文件,然后计算出日志所表示的请求以平方英尺为单位的平均屏幕尺寸。第一个参数是日志文件的位置,第二个参数是日志文 件里用户代理所在列的索引。
- using System;
- using FiftyOne.Foundation.Mobile.Detection.Binary;
- using System.IO;
- namespace ConsoleApplication
- {
- class Program
- {
- static void Main(string[] args)
- {
- // The number of devices read from the log file.
- int count = 0;
- // The column in the input file the user agent is held in.
- int column = int.Parse(args[1]);
- // Screen dimension variables.
- double total = 0, width, height, squareInches;
- // Create a provider to determine the device capabilities.
- var provider = Reader.Create("51Degrees.mobi.dat");
- // Read each line of the log file provided in argument 0.
- // Assume the value at column 8 is the UserAgent string.
- using (var reader = File.OpenText(args[0]))
- {
- while(reader.EndOfStream == false)
- {
- var values = reader.ReadLine().Split(new[] { ' ' });
- if (values.Length >= column)
- {
- // Get the device information based on the UserAgent.
- var device = provider.GetDeviceInfo(
- values[column - 1].Replace("+", " "));
- if (device != null)
- {
- // Determine the screen dimensions in inches.
- double.TryParse(
- device.GetFirstPropertyValue("ScreenInchesWidth"),
- out width);
- double.TryParse(
- device.GetFirstPropertyValue("ScreenInchesHeight"),
- out height);
- squareInches = width * height;
- // If valid values are available (not a desktop/laptop)
- // then add the values to the results.
- if (squareInches > 0)
- {
- total += squareInches;
- count++;
- }
- }
- }
- }
- }
- Console.WriteLine(
- "Average screen size '{0:#.00}' square inches from '{1}' devices",
- total / count,
- count);
- Console.ReadKey();
- }
- }
- }
分析日志文件很不准确,因为除了用户代理外的其他HTTP头都影响着检测结果。对Opera Mini和Opera 移动浏览器来说尤其是这样的。在这两个浏览器里,第二个HTTP头,也就是名字为Device-Stock-UA的头常常用来提供标准用户代理里没有的有 关物理硬件的信息。
为什么监控?
监控使得我们能够将不受欢迎的内容从主页中删除,以此提升更重要的内容或相关的内容的性能。删除的内容应该仍可以通过二级页面访问到——只是不放在首页,不然的话它们会消耗宝贵的带宽并降低性能体验。
那么,我们怎样来创建一个独立的性能优化的移动网站呢?
分而治之
我能理解为什么RWD(响应web设计)从用户界面设计的角度来说很有意义。对于6平方英寸屏幕和10平方英寸屏幕,以及仅仅是需要进行改动的布局来说,在内容,导航以及业务流程需求方面可以完全一致,这实在是太棒了。
平均设备屏幕尺寸。
但是,在上述条件不为真或者对性能要求严格的时候有一个独立的移动网站 具有特别的意义。
独立的移动网站常常表现出一种不良的用户体验。通过给网站惩罚赋以较低的搜索引擎等级,Google现在投射出一缕曙光 到这些普通的问题上。问题包括了将每个桌面页发送到单独的移动主页,重定向到应用下载页,阻止用户访问大屏的网站,对所有带特定操作系统的设备以相同的方式处理。
这些糟糕的实现让人对这些概念有一个坏的印象。这里是一些简单又正确的做法。
下面的 .NETweb.config片段将把来自智能手机的第一个请求,重定向到网站上“Smartphone”部分指定的等价页面。 重要的是,查询字符串与页面名字在重定向的过程中一直保持着。
- <redirect firstRequestOnly="true"
- mobileHomePageUrl="~/Mobile/Default.aspx"
- timeout="20"
- devicesFile="~/App_Data/Devices.dat"
- mobilePagesRegex="/(Mobile|Smartphone)/" >
- <locations>
- <!--Send smartphones to an equivalent version of the original page, preserving the page name and query string.-->
- <location name="smartphone" url="~/Smartphone/{0}" matchExpression="(?<=^\w+://.+/).+">
- <add property="IsSmartphone" matchExpression="true"/>
- </location>
- </locations>
- </redirect>
在大多数情形,当重定向到替代页面时,如果愿意的话用户应当可以返回原始的页面; 或许他们对网站的大屏幕版本更熟悉呢。firstRequestOnly属性保证了只有来自设备的第一次请求才被重定向。devicesFile属性是用 来对不支持cookies的设备进行跟踪。timeout属性控制了在多长时间内该设备被记忆(为了重定向的目的)。
重定向系统还必须知道哪个页面是针对哪种设备设计的。mobilePagesRegex属性被应用到请求URLs。如果存在匹配,页面将不适用重定向。这阻止了无穷重定向的情况。
locations元素允许配置定义不同的地址,以及相关的规则。这个例子将Smartphone目录插入到原始的URL。查询字符串和其他的URL信息在重定向过程中一直保持。所有影响到请求上下文的信息必须被传送,以便用户获得他们期望的内容。
这个简单的方法使得一个搜索引擎友好的,兼容Google的,移动手机优化的网站,在传送的过程中有良好的用户体验和优异的性能。这个过程的基础是DDR,它快速的,一致的,精确的提供了设备的信息。对于改变了移动手机浏览器设置到桌面模式的用户,重定向将不会发生。
警惕云
云服务是给网站迅速增加特性的流行方法。但是它们跨越Internet的请求对性能带来损耗。如果忽略处理时间,我们观察到由Amazon Web Service提供的云服务的数据传输有平均200毫秒的延时。
200毫秒是一个黄金秒的20%。因此,仔细考虑一下你使用的云服务在哪里,确保它们是异步调用的,以便在等待响应的过程中其他处理能继续下去。它们应该避免关键路径上的活动,例如判别请求设备的信息。