Web 开发人员的文本压缩
Web 上的大多数文本数据由 HTML、Javascript 和 CSS 组成。 这些格式不适合有损压缩格式。 因此,您只能使用无损编码器,它们无法提供某些有损图像和视频编解码器的显着压缩率。 那么如何在不发疯的情况下缩小网络应用程序的占用空间呢? 本文将引导您完成整个过程,并帮助您保持理智。
文本数据压缩清单
- 首先考虑 移动 用户体验
- 您页面的资产足迹是多少? 你能减少它吗?
- 用户平均需要多长时间才能加载您的页面?
- 缩小所有可以缩小的内容。
- CSS 和 Javascript 压缩器功能强大、易于使用,并且适合现有的构建管道。
- 尽可能多地预处理数据。
- 对所有文本资源使用 GZIP 压缩。
- 如果您需要更多,请使用 BZIP2 和 LZMA 等高级编解码器。
为什么小就是大
已经有一个巨大的移动市场,随着世界范围内连接的增加,技术公司发现自己处于一场新的战斗中,为即将上网的下一个 50 亿人提供内容和数据。 埃里克·施密特 (Eric Schmidt) 的“新数字时代” 很好地阐述了这个主题:
非洲已有超过 6.5 亿手机用户,亚洲有近 30 亿手机用户。 这些人中的大多数人都在使用基本功能的手机——语音通话和短信——因为他们国家的数据服务费用往往贵得令人望而却步,以至于即使是那些可以购买网络电话或智能手机的人也无法使用它们经济实惠。 这将会改变,而当它发生时,智能手机革命将使这些人群受益匪浅。
报告,这不是新信息, 根据Cisco 纯移动用户的数量已经在增加, 到 2015 年将接近 7.88 亿纯移动用户 。 当然,对于像思科这样的大公司来说,这是一个大问题,因为 2012 年每月有 597 PB 的 数据流经他们的硬件。
移动连接速度和设备性能。 在过去的几年里,世界已经看到网络速度有了很大的提高。 然而,重要的是要了解这种改进在数量或地理位置方面的差异。 Google Analytics 有一张 很棒的图表 ,显示了全球连接的趋势。 很容易看出改进的想法不是同质的; 例如,中国 增加了 8% 的桌面页面加载时间中位数 (速度变慢了),而他们的移动性能时间减少了 33% ,(速度变快了)加载时间仍然超过 3.5 秒; 这是一个相当大的数字, 考虑到他们 15.3 亿人口中有 42% 在线 。
实际上,用户对加载时间和响应能力的感知是最重要的指标。 正如我们所见, 延迟是新的网络性能瓶颈 ,很明显,网络改进直接成为大多数国家的硬件问题。 建造新的蜂窝塔和光纤线路是土木工程的噩梦,代表着巨大的投资成本。 问题是如此复杂,以至于一些公司甚至正在开发 价值数百万美元的卫星 ,以不同的方式解决这个问题。 简而言之: 移动网络将继续以 的方式努力提高速度 缓慢、不均衡且代价高昂 。 如果您正在等待移动网络突然变得更快,您可能需要找一张更舒适的椅子等待。
给用户 更多 发送 通过减少 。
作为 Web 开发人员,您可以最大程度地控制如何优化您的网站,从而为您的用户提供最快、最便宜、最高质量的体验; 实现这一目标的最佳方法之一是压缩。 当然你可以只做一个移动网站,内容少,宽度小。 然而,事实表明,用户不想要移动网站:如果在两者之间做出选择,三分之一的网站移动访问者会选择访问完整网站。 能够跨多种设备和连接提供快速、可靠、跨平台用户体验的网站所有者将拥有不远的未来的网络。
压缩算法的类型
文本压缩的联合主要由无损压缩算法组成。 (不包括您可能拥有的基于文本的浮点数据的边缘情况)。 这些是典型的压缩算法,允许直接恢复源流而不会丢失任何精度或信息。 在大多数归档压缩器中,流行的无损编解码器包括 LZ77 、 霍夫曼 和 算术编码 。 无损压缩算法是大多数编解码器的支柱,通常在其他算法之后应用,以压缩几个百分点。
前 | 后 |
aaaaabbbbbcccddddeeeeffffaaaaabb | a5b4c2d4e4f4a5bb |
图 1 - 无损压缩示例。 值的运行被编码为符号后跟运行的长度。 我们可以正常恢复原来的流。 请注意,如果运行的长度 <= 2 个字符,则只保留符号是有意义的。 您会在带有“bb”的流的末尾看到它。
在极少数情况下,您可以通过在应用无损压缩器之前对部分内容应用有损转换来进一步节省成本。 由于数据无法从这些转换中恢复到其源状态,因此这些算法通常保留用于不会丢失信息的基于文本的数据类型; 例如,将浮点数截断为仅两位有效的小数位可能是数据集可接受的转换。
前 | 后 |
0.123, 1.2345, 21.2165, 21.999, 12.123 | 0,0,20,20,10 |
图 2 - 有损压缩示例。 值被量化为它们所占的 10 的最小倍数。 这种转变无法逆转。
文本压缩格式
当今的大部分文本压缩系统都通过将各种数据转换链接在一起来取得成功。 系统中每个阶段的重点是转换数据,以便下一阶段可以使用并有效地压缩数据。 这些阶段的总和产生了一个小的、无损的可恢复文件。 实际上有数百种压缩格式/系统,每种格式/系统在不同类型的数据方面各有利弊。 您从未听说过它们中的大多数,因为它们要么不够健壮(处理多种类型的数据),要么没有产生预期的节省。 出于我们的目的,让我们看一下三种更流行的格式,GZIP、BZip2 和 7zip。
Web 支持的格式:GZIP 和 Deflate
有两种常用的 HTTP 压缩 当今网络上 方案: DEFLATE 和 GZIP 。 DEFLATE 是一种非常流行的压缩算法,它通常使用 LZ77 算法和 霍夫曼 编码来包装数据。 GZIP 是一种在内部使用 DEFLATE 的文件格式,以及一些有趣的阻塞、过滤启发式方法、标头和校验和。
一般而言, GZIP 使用的附加阻塞和启发式算法比单独使用 DEFLATE 具有更好的压缩率。 Web 堆栈已尽最大努力使这些技术的使用成为半自动的,将文件的实际压缩推送到分发服务器(这两种算法在压缩和解压缩速度上都非常快,这使它们成为在服务器端工作的理想选择). PHP 、 Apache ,甚至 Google App Engine 都支持 GZIP ; 它们代表您压缩文件,并允许您在 HTTP 标头中设置标志以描述流量的传输方式。 这样的下一代传输协议 像SPDY 和 HTTP2.0 支持使用GZIP 进行头压缩,因此未来大多数 Web 堆栈都将依赖这种压缩算法。
滚动您自己的较小的 GZIP 文件
大多数开发人员只是简单地上传未压缩的内容,并依靠 Web 服务器即时压缩数据。 这为大多数开发人员带来了很好的结果,并且易于使用。 但是大多数人不知道 的默认GZIP 大多数服务器上 级别设置为级别 6 ,其中最高级别实际上是 9。此设置是有意的:它让服务器以更大的输出文件为代价更快地压缩数据. 来获得更好的压缩效果 您可以通过使用GZIP 离线压缩文件并将压缩文件上传到服务器 。
您可以直接将 GZIP 用于此过程,但更高级的压缩器(如 Zopfli 和 7zip )会定期生成 更小的 gzip 文件,通过更高级的搜索/匹配算法,以及利用更多内存以实现更好模式匹配的数据结构。 要利用这些节省,请脱机压缩您的文件,然后将压缩文件上传到您的服务器。 您需要配置您的服务器以正确传送预压缩的内容(这里是如何在 Apache 、 nginx 和 Amazon Web Services 上执行此操作)。 当客户请求您的页面时,它将像往常一样交付和解压缩,而无需对您的客户端代码进行任何更改。
其他压缩格式
GZIP 远非唯一的选择,如果您碰巧是一个经常发送大量数据块的 Web 应用程序,那么您可能需要投资其他技术来减少内容大小。 这些技术之一可能涉及使用 javascript 构建压缩格式,它 为您提供比GZIP更好的压缩。 以合理的解压缩速度 是两种有竞争力的压缩格式(又名“孩子们正在使用什么”) BZIP2 和 LZMA ,它们通常可以生成比 GZIP 更小的文件,并且在许多情况下解压缩的速度也更快。
遗憾的是,这两种格式在本机级别的浏览器中不受支持,但是这些流行的格式现在具有 其代码的 JavaScript 移植版本 ,这意味着您可以使用这些编解码器离线压缩数据,并在客户端的 javascript 中解压缩它们。 此活动的解压缩时间会较慢,这意味着它可能不适合所有数据,但是交互式和高度详细的 Web 应用程序的开发人员可能会发现沿着这条路走下去会有很大的好处。
就格式而言,这两个在其数据压缩路径中使用完全不同的阶段,因此很难与 GZIP 进行适当的比较。 例如, BZIP2 是围绕 Burrows Wheeler Transform 以及 Move To Front 变换构建的。 这两种转换都不会减少数据的实际大小,而是以一种后续霍夫曼/算术编码器可以进行实际压缩的方式转换数据。
BZIP 经常因其需要更大的内存而受到批评(BWT 可以通过简单的实现快速消耗内存)但就比较而言,它可以轻松压缩小于 gzip。 LZMA 的远亲 可以被认为是GZIP 。 它们都从流行的 LZ 字典压缩开始,然后是统计范围编码系统。 产生 然而, LZMA 比 GZIP 更小文件的原因在于其先进的 LZ 匹配和窗口算法。
预处理文本以获得更好的压缩
通常,网络上的文本压缩是一个两步过程; 首先是最小化步骤,然后是无损压缩步骤。
缩小
第一步, 缩小 是减少数据大小的行为,这样它就可以在不被 底层系统 处理的情况下使用。 基本上我们尽可能多地从文件中删除不必要的数据,而不更改它的语法。 例如,从 Javascript 文件中删除大部分空格是安全的,可以在不更改 JavaScript 语法的情况下减小文件大小。 缩小通常在 构建过程 中作为手动步骤或作为自动构建链的一部分进行处理。
CSS Minifiers 有许多 CSS minifiers 可供选择。 一些可用的选项包括。
尝试一些,然后选择能给您带来良好效果并适合您的工作流程且摩擦最少的那个。 这些工具之间的主要区别在于它们缩小过程的深度。 例如,简单的优化过滤文本以删除多余的空格和空块。 更高级的优化可能包括将“ ” AntiqueWhite ”替换为“ #FAEBD7 ,因为十六进制形式在文件中更短,并强制所有字符为小写以增加 GZIP 压缩。 更积极的 CSS 最小化方法可以节省更多空间, 但也有违反 CSS 规则的风险 。
因此,大多数改进并不总是自动化的,开发人员必须决定文件大小的改进是否值得冒这个风险。 事实上,创建 其他 版本 的 CSS 语言 以帮助更有效地编写 CSS 代码的新趋势已成为一种新趋势,并且作为一个额外的好处,允许编译器生成更小的 CSS 代码。
Javascript Minifiers 与 CSS minifiers 一样,没有万能的 JavaScript minifier。 同样,它们都做着几乎相同的工作,因此请选择适合您的构建链并具有您想要的功能的那个。 一些比较受欢迎的是:
大多数这些系统的工作方式是将您的 Javascript 编译成某种 抽象语法树 表示,并从 ASK 重新生成更紧凑的 JavaScript。 示例优化包括最小化空格、缩短变量名称以及以更短的形式重写表达式。 例如,foo.bar 而不是 foo[“bar”]) 自动缩小器可以很好地完成工作,但有一些 机器人不知道如何进行 的高级优化。 新一代的 JS 黑客正在将过去的自动缩小方法推向 手动生成的缩小 ,这通常会产生比任何自动化工具都能产生的文件更小的文件。 当然,需要有点疯狂才能实现。
内容特定处理
虽然通用无损压缩算法可以节省大量成本,但普遍的趋势是对数据进行预处理以获得更好的压缩效果。 大多数压缩系统中最大的胜利现在来自关于信息格式和组织的高度明智的决策,以及通过分组和自定义压缩(这也称为 建模 )来利用它。 大多数时候,这需要清晰、认真地查看您的内容,以确定您可以在较高级别利用哪些类型的冗余。 这里有一些想法可以让你思考:
对于文本数据,可以从压缩流中删除一些符号,稍后在客户端恢复(例如空格),这可以减小整体文件大小,并且不会对客户端性能造成太大影响。
图 3 - 删除已知冗余文本的示例。 我们知道在这个例子中所有的值都是个位数字节,我们可以删除逗号并稍后恢复它们。
如果您要传递大量浮点数, 那么量化 您的值是一个好主意,因为它可能会减少唯一符号的数量,并且还会截断一些不必要地添加到文件中的精度。
图 4 - 有损压缩示例。 值被量化为它们所占的 10 的最小倍数。 这种转变无法逆转。
通常,开发人员会发送索引数组,这些索引数组往往与顺序无关。 如果您的索引信息恰好是一个闭区间(即 X、Y 的所有值,没有任何跳过),那么您可以对您的信息进行排序,并对它进行增量编码以获得更大的收益。
增量编码 = [0,1,1,1,1,1,1,1,1,1] |
图 5 - 排序和增量编码的示例。 我们首先对数据进行排序,然后对其进行编码,这样每个元素都表示为前一个元素之间的差异。 请注意增量编码形式如何包含许多重复符号。
最近,压缩大师 Matt Mahoney 参加了一场压缩 人类 DNA 序列 的比赛。 他的 成果令人印象深刻 ,并且通常以手头内容的提取、建模和分析为中心。 从交错流中提取相似数据类型到同类块中的能力允许压缩算法利用本地信息来帮助压缩,通常允许基于几个独立数据点预测未来符号的能力。
为任意的混合内容数据文件编写这种类型的特定于内容的压缩非常棘手且麻烦。 对你来说幸运的是,有些人已经开始沿着这条路走下去:
- XMILL 是一种 XML 特定的压缩系统,它提取出异构类型的数据,将它们组合在一起,并对它们运行各种压缩算法。
- 另一个很棒的应用程序是 JSZap ,它将你的 JavaScript 分解成一个抽象语法树,然后将相似的数据类型分离成单独的流,使用每个流的最佳压缩器单独压缩每个流。
- 将这个想法应用到 JSON 数据中,你可以很容易地找到多个参考资料; 再一次,您可以 在将JSON 文件 传递给 GZIP 之前对其进行预处理,以产生更大的节省。
结论
尽管图像占用了大多数网站带宽的 60%,但您不能忽略来自文本内容的其他数据块。 JavaScript 文件越来越大,JSON 数据每天都在发送,越来越多的用户在网络连接不畅的情况下上网。 因此,请确保每次推送网站构建时,您都遵循 文本压缩清单 :
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 避免不必要的绘画:GIF 动画版
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论