websharks/html-compressor

合并并压缩 CSS/JS/HTML 代码。

170420.24924 2017-04-20 06:56 UTC

README

合并并压缩 CSS/JS/HTML 代码。

<?php
require_once 'html-compressor.phar';
$html_compressor = new WebSharks\HtmlCompressor\Core();
ob_start(array($html_compressor, 'compress'));

安装说明(两种选项)

  1. 作为 Composer 依赖项
{
    "require": {
        "websharks/html-compressor": "dev-master"
    }
}
  1. 或者,下载 PHAR 二进制文件,请参阅:https://github.com/websharks/html-compressor/releases

我从哪里获取 PHAR 文件?

每个官方版本都提供了一个 PHAR 二进制文件。请参阅:发布版本

我们为什么创建 HTML 压缩器?

HTML 压缩器类是开发出来的,因为我们在这里的 WebSharks™ 都厌倦了看到野外运行的许多不同插件的 WordPress 安装;每个插件可能都添加了一组新的 CSS/JS 文件。即使启用了页面缓存插件,这也可能导致网站加载缓慢。

例如,如果您查看大多数由 WordPress(或审计开发者在网络开发控制台中的)等发布平台提供的网站的 HTML 源代码,您将发现 像这样的混乱...

<link rel="stylesheet" href="theme.css" type="text/css" />
<link rel="stylesheet" href="child-theme.css" type="text/css" />
<link rel="stylesheet" href="theme-variation.css" type="text/css" />
<link rel="stylesheet" href="plugin1.css" type="text/css" />
<link rel="stylesheet" href="plugin2.css" type="text/css" />
<link rel="stylesheet" href="plugin3.css" type="text/css" />
<link rel="stylesheet" href="plugin4.css" type="text/css" />
<link rel="stylesheet" href="plugin5.css" type="text/css" />
... and on, and on, and on ...

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery-migrate.min.js"></script>
<script type="text/javascript" src="tabs.min.js"></script>
<script type="text/javascript" src="custom.js"></script>
<script type="text/javascript" src="plugin1.js"></script>
<script type="text/javascript" src="plugin2.js"></script>
<script type="text/javascript" src="plugin3.js"></script>
<script type="text/javascript" src="plugin4.js"></script>
<script type="text/javascript" src="plugin5.js"></script>
... and on, and on, and on ...

↑ 这里的问题是什么?

而不是单个 CSS 和/或 JS 文件(即一个或两个 HTTP 连接);浏览器需要发出 多个 请求;并且需要单独下载这些资源。这不仅仅影响 WordPress,我们在许多包含插件的发布平台上都看到了这个问题。

理想情况下,您的发布平台(或主题)会通过合并这些外部资源(即 CSS/JS 文件)为仅一个或两个文件,并对其进行压缩来最小化它所依赖的外部资源数量。但是,并非所有主题都这样做。事实上,这并不总是可能的(即使主题/插件开发者知道这个问题)。

例如,如果主题/插件开发者在一系列 PHP 框架标准(例如,“WordPress 方式”做事)内工作,最终结果可能并不总是以理想的方式优化。我们深知这真的让开发者头疼。经验丰富的开发者不是故意弄乱,这只是框架将所有东西组合在一起的方式,有时会产生混乱。此外,当网站所有者后来添加插件时;其中发布平台(或主题)通过 CSS/JS 文件得到补充,而这些文件是针对特定插件的——这时事情可能变得非常混乱;例如,每个插件都有一个新的 CSS 和/或 JS 文件。

解决方案,WebSharks™ HTML 压缩器!

WebSharks™ HTML 压缩器作为一个额外的功能层,可以在您的发布平台组合所有内容之后运行。 WebSharks™ HTML 压缩器实时分析您网站的每一页;即,它在加载时;检查每一行 HTML 代码。

CSS/JS 文件(在可能的情况下)合并和压缩;然后它还可以优化 HTML 代码以及任何内联 JavaScript/CSS。目标是加快访问者的速度,并减少服务器处理的 HTTP 连接数量。

逐步(详细说明)

所有这些压缩选项默认启用,但您可以按需修改此行为。在本文件底部,您将找到所有可能的配置选项列表。

1. HTML 压缩器首先检查 HTML 文档的 <head><body> 部分。尝试递归地将所有 CSS 资源(包括内联样式和所有远程资源)合并成一个单独的 CSS 文件。如果启用了 compress_css_code(默认开启),则该文件中的代码也会被压缩(例如,删除额外空格、优化十六进制颜色代码等)。

关于步骤 1 的几点说明。

  • 注意:HTML 压缩器在此过程中会尽可能保持标准兼容性,从而将冲突的可能性降至最低。

  • 注意:尝试获取远程资源(例如,外部托管的资源)或 @import 规则。所有远程资源都会简单地添加到单个 CSS 文件中,以消除需要多个 HTTP 连接来加载合并后的 CSS 的可能性。HTML 压缩器在此过程中还能够解析文件路径和 url() 引用到正确位置。

  • 注意:HTML 压缩器通过智能跳过您定义的任何排除项以及任何无法合并的内容来避免级联冲突。在某些情况下,10 个文件可能合并成 1 个;在其他情况下,10 个文件可能合并成 2 个或 3 个。这可能会因网站而异——甚至可能是页面到页面的差异。如果可能的话,您将获得 1 个文件。否则,您将获得可能的最大压缩效果。

  • 注意:在任何情况下,HTML 压缩器都不会改变底层 CSS 资源的加载顺序。即使在多个集合中合并文件(或跳过某些排除项)时,加载顺序也会始终保留,以防止此过程引入 CSS 冲突。

  • 注意:HTML 压缩器也会保留所有 CSS @ 规则。这包括 @media 规范(无论它们是在 @import<link media=""> 标签中定义的;还是通过嵌入的 @media 规则)。只有一个例外。始终将 @charset 规则强制为 @charset "UTF-8";(推荐使用)。

  • 注意:条件 CSS(例如,<!--if[] 标签)始终排除在合并之外,以防止其行为改变。当遇到排除项时,会保留级联顺序;当然,也包括 <!--if[] 标签。

2. 接下来,我们检查 HTML 文档的 <head> 部分。尝试将 <head> 中的所有 JS 资源合并成一个单独的 JS 文件。如果启用了 compress_js_code(默认开启),则该文件中的代码也会被压缩(例如,删除额外空格、优化变量名等)。

3. 接下来,我们检查源代码的一个特殊区域,可以通过用 <!--footer-scripts--><!--footer-scripts--> 包裹部分内容来标记进行压缩。如果您故意将脚本放置在页脚中,则此标记是必要的。如果 HTML 压缩器找到 <!--footer-scripts--><!--footer-scripts--> 部分;将尝试将所有 JS 资源合并成一个单独的 JS 文件。如果启用了 compress_js_code(默认开启),则该文件中的代码也会被压缩(例如,删除额外空格、优化变量名等)。

关于步骤 23 的几点说明。

  • 注意:HTML 压缩器在此过程中会尽可能保持标准兼容性,从而将冲突的可能性降至最低。

  • 注意:尝试获取远程资源(例如,外部托管的 JavaScript 资源)。所有远程资源都会简单地添加到单个 JS 文件中,以消除需要多个 HTTP 连接来加载合并后的 JS 的可能性。HTML 压缩器在此过程中也能够解析文件路径和引用到正确位置。

  • 注意:HTML 压缩器通过智能地跳过您定义的任何排除项以及无法合并的任何内容,避免加载顺序冲突。在某些情况下,10 个文件可能合并成 1 个;在其他情况下,10 个文件可能合并成 2 或 3 个。这可能会因网站而异;或页面与页面之间。如果可能,您将获得 1 个文件。否则,您将获得可能的任何压缩。

  • 注意:在任何情况下,HTML 压缩器都不会改变底层 JS 资源的加载顺序。即使文件被组合成多个集合(或跳过某些排除项),加载顺序始终得到保留,以避免在此过程中引入 JS 冲突。

  • 注意:在此过程中,所有 JavaScript async 指示符都被保留。异步加载是通过 <script> 标签中的 async 和/或 defer 属性检测到的。

  • 注意:条件 JS(例如,<!--if[] 标签)始终被排除在合并之外,因此它们的行不会改变。当遇到排除项时,会保留加载顺序;当然,这也适用于 <!--if[] 标签。

4. 接下来,我们查看 <body> 中是否有内联 <script> 标签。虽然无法合并内联 JS;如果启用 compress_inline_js_code(默认启用),将尝试压缩这些内联代码片段中的 JavaScript 代码,以减少它们可能增加的开销。

5. 最后,我们压缩 HTML 代码本身(即,移除额外空白)。在原始格式化很重要的特殊标签处,我们会小心保留;但您应该得到一个更小的 HTML 文件;并且它所依赖的外部资源肯定已减少到最低限度。

一些使用示例

1. HTML 压缩器作为输出缓冲区

此代码片段应在任何其他输出之前处理。

<?php
require_once 'html-compressor.phar';
$html_compressor = new WebSharks\HtmlCompressor\Core();
ob_start(array($html_compressor, 'compress'));

提示:php.ini 指令 auto_prepend_file 是集成 HTML 压缩器的一种优雅/干净的方式。您可以根据此示例创建一个文件,并指定为 auto_prepend_file 以启用对您提供的每个 HTML 文件的压缩;请注意,HTML 压缩器将简单地通过其缓冲区传递任何非 HTML 代码而不会对其进行压缩。HTML 压缩器仅尝试压缩包含关闭 </html> 标签的数据。

重要提示:要记住的一件事是,WebSharks™ HTML 压缩器与 ZenCache for WordPress 等页面缓存插件或您可能更喜欢另一个页面缓存插件集成时效果最好。为什么使用页面缓存插件?HTML 压缩器可以用于任何由 PHP 驱动的网站;但理想情况下,您会缓存它输出的优化 HTML,从而无需 HTML 压缩器分析每个请求。当然,您 可以 分析每个请求(HTML 压缩器也有自己的缓存来帮助保持事情正常),但始终最好是存储(缓存)由此类创建的压缩 HTML 输出。这将减少服务器负载并使您的网站更快。

常见问题解答:是否只需要 html-compressor.phar 文件?是的。GitHub 仓库中显示的其他文件已压缩到 PHAR 文件中。您需要的唯一文件是 html-compressor.phar。为每个官方版本提供了一个 PHAR 二进制文件。请参阅:发行版

2. HTML 压缩器作为输出缓冲区(带有选项)

这仅演示如何指定选项数组。

<?php
require_once 'html-compressor.phar';
$html_compressor_options = array(

    'css_exclusions' => array(),
    'js_exclusions' => array('.php?'),
    'uri_exclusions' => array(),

    'cache_expiration_time' => '14 days',
    'cache_dir_public' => '/var/www/public_html/htmlc/cache/public',
    'cache_dir_url_public' => 'http://example.com/htmlc/cache/public',
    'cache_dir_private' => '/var/www/public_html/htmlc/cache/private',

    'compress_combine_head_body_css' => TRUE,
    'compress_combine_head_js' => TRUE,
    'compress_combine_footer_js' => TRUE,
    'compress_inline_js_code' => TRUE,
    'compress_css_code' => TRUE,
    'compress_js_code' => TRUE,
    'compress_html_code' => TRUE,

    'benchmark' => FALSE,
    'product_title' => 'HTML Compressor',
    'vendor_css_prefixes' => array('moz','webkit','khtml','ms','o')
);
$html_compressor = new WebSharks\HtmlCompressor\Core($html_compressor_options);
ob_start(array($html_compressor, 'compress'));

3. 在原始 HTML 代码上使用 HTML 压缩器

这演示了如何对任意 HTML 代码运行压缩器。

<?php
require_once 'html-compressor.phar';
$html_compressor_options = array(

    'css_exclusions' => array(),
    'js_exclusions' => array('.php?'),
    'uri_exclusions' => array(),

    'cache_expiration_time' => '14 days',
    'cache_dir_public' => '/var/www/public_html/htmlc/cache/public',
    'cache_dir_url_public' => 'http://example.com/htmlc/cache/public',
    'cache_dir_private' => '/var/www/public_html/htmlc/cache/private',

    'current_url_scheme' => 'http',
    'current_url_host' => 'www.example.com',
    'current_url_uri' => '/raw/file/test.html?one=1&two=2',

    'compress_combine_head_body_css' => TRUE,
    'compress_combine_head_js' => TRUE,
    'compress_combine_footer_js' => TRUE,
    'compress_inline_js_code' => TRUE,
    'compress_css_code' => TRUE,
    'compress_js_code' => TRUE,
    'compress_html_code' => TRUE,

    'benchmark' => FALSE,
    'product_title' => 'HTML Compressor',
    'vendor_css_prefixes' => array('moz','webkit','khtml','ms','o')
);
$html = '<html> ... </html>';
$html_compressor = new WebSharks\HtmlCompressor\Core($html_compressor_options);
$html = $html_compressor->compress($html);

类构造函数选项

例如,new WebSharks\HtmlCompressor\Core($options);

其中 $options 是一个关联数组,其中包含以下列出的一个或多个键。

所有可能的选项当前列表

以下选项允许您排除某些CSS/JS文件和/或内联片段。

注意:这些选项仅在启用CSS/JS文件压缩时适用。

  • (数组)css_exclusions 默认为 array()。如果您有一些CSS文件(或内联样式)不应该被压缩过程包含,请指定一个要排除的搜索标记数组。搜索标记与外部CSS文件的 href 值(即URL或路径)进行比较。搜索标记也与其他任何内联 <style></style> 标签的内容进行比较。

  • (数组)js_exclusions 默认为 array()。如果您有一些JS文件(或内联脚本)不应该被压缩过程包含,请指定一个要排除的搜索标记数组。搜索标记与外部JS文件的 src 值(即URL或路径)进行比较。在可能压缩的情况下,搜索标记也与其他任何内联 <script></script> 标签的内容进行比较。

  • (数组)uri_exclusions 默认为 array()。如果您有一些URL不应该被压缩过程包含,请指定一个要排除的搜索标记数组。搜索标记与当前URI(即域名之后的所有内容)进行比较。

    注意:搜索标记应该是字符串字面量。HTML Compressor当前不支持搜索标记中的通配符或正则表达式。如果您需要使用正则表达式模式而不是搜索标记,请在定义选项键时使用 regex_ 前缀;例如,'regex_js_exclusions' => '/\special\-script\.js/i'。这也适用于 regex_css_exclusionsregex_uri_exclusions

  • (布尔值)disable_built_in_css_exclusions 默认为 FALSE。HTML Compressor的每个新版本都会更新(改进)一些内置的排除模式。建议您始终启用这些模式。但是,如果您更喜欢关闭它们(即仅排除您指定的模式),可以将此设置为 TRUE 以禁用所有内置的。内置排除模式处理几乎所有网站都应该排除的事情。如果您想查看内置模式的列表,可以阅读 $built_in_regex_css_exclusion_patterns 类属性。它是一个正则表达式数组,这些正则表达式与外部CSS文件的 href 值(即URL或路径)进行比较;它们也与其他任何内联 <style></style> 标签的内容进行比较。

  • (布尔值)disable_built_in_js_exclusions 默认为 FALSE。HTML Compressor的每个新版本都会更新(改进)一些内置的排除模式。建议您始终启用这些模式。但是,如果您更喜欢关闭它们(即仅排除您指定的模式),可以将此设置为 TRUE 以禁用所有内置的。内置排除模式处理几乎所有网站都应该排除的事情。如果您想查看内置模式的列表,可以阅读 $built_in_regex_js_exclusion_patterns 类属性。它是一个正则表达式数组,这些正则表达式与外部JS文件的 src 值(即URL或路径)进行比较;它们也与其他任何内联 <script></script> 标签的内容进行比较。

  • (布尔值)disable_built_in_uri_exclusions 默认为 FALSE。HTML Compressor的每个新版本都会更新(改进)一些内置的排除模式。建议您始终启用这些模式。但是,如果您更喜欢关闭它们(即仅排除您指定的模式),可以将此设置为 TRUE 以禁用所有内置的。内置排除模式处理几乎所有网站都应该排除的事情。如果您想查看内置模式的列表,可以阅读 $built_in_regex_uri_exclusion_patterns 类属性。它是一个正则表达式数组,这些正则表达式与URI(即域名之后的所有内容)进行比较。

以下选项可用于设置自定义缓存目录/URL。

注意:在大多数情况下,内置的默认值已经足够。

  • (字符串)cache_expiration_time 默认值为 14天。您可以使用与PHP的 strtotime() 函数兼容的任何值。注意:此过期时间在很大程度上是不相关的,因为HTML压缩器使用内部校验和,它也会在使用现有缓存文件之前检查 filemtime()。HTML压缩器类还负责自动清理您的缓存目录,以防止其随着时间的推移变得过大。因此,除非您的磁盘空间非常有限,否则没有必要将此值设置得更低(即使您的网站经常动态更改)。实际上,您可能希望增加此值,这有助于进一步减少服务器负载。

    缓存再生发生有两种情况。

    1. 当缓存文件过期(基于您的过期时间)时。
    2. 缓存文件必须再生,因为存在校验和不匹配(例如,内容动态更改)。

    简而言之,cache_expiration_time 控制第一种情况;即,缓存文件可以存活或使用的绝对最大时间;这当然也会影响自动清理程序。

  • (字符串)cache_dir_public 绝对服务器路径指向一个本地缓存目录,该目录可通过HTTP访问(即,公开访问)。如果您省略此选项,有两个默认处理程序。如果定义了 WP_CONTENT_DIR(即,您正在WordPress中运行此操作),则您的公共缓存目录将位于:wp-content/htmlc/cache/public。否则,此值将默认为 $_SERVER['DOCUMENT_ROOT']/htmlc/cache/public

  • (字符串)cache_dir_url_public 一个公开可用的URL,可链接到 cache_dir_public。如果您省略此选项,则使用自动检测(即,基于 cache_dir_public 的最佳猜测)。

  • (字符串)cache_dir_private 绝对服务器路径指向一个本地缓存目录,该目录不可通过HTTP访问(即,私有/隐藏)。如果您省略此选项,有两个默认处理程序。如果定义了 WP_CONTENT_DIR(即,您正在WordPress中运行此操作),则您的私有缓存目录将位于:wp-content/htmlc/cache/private。否则,此值将默认为 $_SERVER['DOCUMENT_ROOT']/htmlc/cache/private

  • (字符串)cache_dir_url_private 不适用。此选项存在于内部,但不会生成指向私有缓存目录的URL。因此,在正常情况下,您可以完全忽略此选项值。

  • (布尔值)cleanup_cache_dirs 默认为TRUE。默认情况下,缓存目录会随着时间的推移自动清理;即在半随机间隔和基于您的 cache_expiration_time。如果您希望自己清理缓存,可以将此值设置为FALSE。

以下选项可用于指定当前URL。

注意:通常不需要提供这些值。

  • (字符串)current_url_scheme 当此类作为网络应用程序运行时,我们可以自动检测此值。话虽如此,如果您打算在非网络服务器环境中运行此类,则需要告诉压缩器如果压缩的文件作为网页提供,当前的URL方案将是什么。这应设置为 httpshttp 之一。

  • (字符串)current_url_host 当此类作为网络应用程序运行时,我们可以自动检测此值。话虽如此,如果您打算在非网络服务器环境中运行此类,则需要告诉压缩器如果压缩的文件作为网页提供,当前的URL主机将是什么。这应类似于 www.example.com

  • (字符串)current_url_uri 当这个类作为Web应用程序运行时,我们可以自动检测这个值。换句话说,如果您打算在Web服务器环境之外运行这个类,您需要告诉压缩器如果压缩的文件作为网页提供服务,当前URI(即路径和查询字符串)将会是什么。这应该设置为类似 /path/to/page/?one=1&two=2 的样子。

以下选项控制压缩行为。

注意:压缩例程的顺序与以下列出的选项顺序相同。

  • (布尔值)compress_combine_head_body_css 默认为TRUE。如果您希望不要将CSS文件合并到单个HTTP连接中,请将其设置为FALSE值。如果您的站点(出于任何原因)与CSS压缩合并例程不兼容,这可能会很有帮助。注意:如果您因为不兼容而禁用此功能,请通过GitHub报告问题,以便为所有人解决问题。

  • (布尔值)compress_combine_head_js 默认为TRUE。如果您希望不要将JS文件合并到单个HTTP连接中,请将其设置为FALSE值。如果您的站点(出于任何原因)与JS压缩合并例程不兼容,这可能会很有帮助。注意:如果您因为不兼容而禁用此功能,请通过GitHub报告问题,以便为所有人解决问题。

  • (布尔值)compress_combine_footer_js 默认为TRUE。如果您希望不要将页脚中的JS文件合并到单个HTTP连接中,请将其设置为FALSE值。如果您的站点(出于任何原因)与JS压缩合并例程不兼容,这可能会很有帮助。注意:如果您因为不兼容而禁用此功能,请通过GitHub报告问题,以便为所有人解决问题。

  • (布尔值)compress_combine_remote_css_js 默认为TRUE。如果您希望不要将来自远程资源位置的CSS/JS文件合并,请将其设置为FALSE值。默认情况下,选项 compress_combine_head_body_csscompress_combine_head_jscompress_combine_footer_js 会递归地合并所有资源(包括来自远程位置的资源)。如果您将其设置为FALSE值,所有远程的(外部托管资源;例如,来自CDN或其他远程URL的资源)将自动排除,以防止发生远程站外连接。

  • (布尔值)compress_inline_js_code 默认为TRUE。如果您希望不要压缩内联JS代码(即最小化内联 <script> 标签的内容),请将其设置为FALSE值。如果您的站点(出于任何原因)与内联JS压缩例程不兼容,这可能会很有帮助。注意:如果您因为不兼容而禁用此功能,请通过GitHub报告问题,以便为所有人解决问题。

  • (布尔值)compress_css_code 默认为TRUE。如果您希望不要压缩CSS文件(即最小化底层CSS代码),请将其设置为FALSE值。如果您的站点(出于任何原因)与CSS压缩例程不兼容,这可能会很有帮助。注意:如果您因为不兼容而禁用此功能,请通过GitHub报告问题,以便为所有人解决问题。

  • (布尔值)compress_js_code 默认为TRUE。如果您希望不要压缩JS文件(即最小化底层JS代码),请将其设置为FALSE值。如果您的站点(出于任何原因)与JS压缩例程不兼容,这可能会很有帮助。注意:如果您因为不兼容而禁用此功能,请通过GitHub报告问题,以便为所有人解决问题。

  • (布尔值)compress_html_code 默认为 TRUE。如果您希望不压缩 HTML 标记(即,移除多余的空格等),请将此设置为 FALSE 值。如果您的网站(由于任何原因)与 HTML 压缩程序不兼容,这可能很有帮助。注意:如果您因不兼容而禁用此选项,请通过 GitHub 报告问题,以便为所有人解决问题。

  • (布尔值)amp_exclusions_enable 默认为 TRUE。这提高了与 加速移动页面 的兼容性。当此选项启用且正在压缩的 URI 以 /amp/ 结尾,或者文档包含顶级 <html ⚡> 标签(也接受 <html amp>)时,与 加速移动页面 不兼容的功能将被相应禁用,无论您的其他设置如何。

其他一些选项。这些还没有真正归入任何特定的类别。
  • (布尔值) 或 (字符串)benchmark 默认关闭。如果启用,将在最终输出中添加一些有用的信息的 HTML 注释。如果您将其设置为 TRUE 值,它只是启用整体时间计算。如果您正在调试,并且需要查看许多其他详细信息;可以将此设置为字符串:details(在生产环境中不建议使用)。

  • (字符串)product_title 如果您想更改特定 HTML 压缩实例的标题(例如,将默认名称“HTML Compressor”更改为您喜欢的其他名称),请定义此选项。如果未定义,则默认为 HTML Compressor。注意:这将影响在 HTML 注释中显示的产品标题;假设在最终输出中已启用 benchmark 且包含注释。

  • (数组)vendor_css_prefixes 已知的供应商特定 CSS 前缀数组。默认为 array('moz','webkit','khtml','ms','o')