压缩 HTML、CSS 和 HTML 的最佳方法 禁用 mod_deflate 和 mod_gzip 的 JS

发布于 2024-07-04 02:03:29 字数 759 浏览 7 评论 0原文

我在运行 Apache 2 的共享主机上有几个站点。我想压缩传送到浏览器的 HTML、CSS 和 Javascript。 主机已禁用 mod_deflate 和 mod_gzip,因此这些选项无效。 不过,我确实有 PHP 5,所以我可以使用它的 gzip 组件。

我目前将以下内容放入我的 .htaccess 文件中:

php_value 输出处理程序 ob_gzhandler

但是,这仅压缩 HTML,而忽略 CSS 和 JS。

有没有一种可靠的方法可以透明地压缩 CSS 和 JS 的输出,而不必更改每个页面? 我在谷歌上搜索过,并提出了许多解决方案,但我还没有找到一个可以工作的解决方案。 如果有人能提出一个他们知道可行的解决方案,我们将非常感激。

请注意,方法 2 "noreferrer">关于压缩 CSS 的权威文章 看起来是一个很好的解决方案,但我无法让它发挥作用。 有其他人使用此方法成功吗?

I have a few sites on a shared host that is running Apache 2. I would like to compress the HTML, CSS and Javascript that is delivered to the browser. The host has disabled mod_deflate and mod_gzip, so these options are out. I do have PHP 5 at my disposal, though, so I could use the gzip component of that.

I am currently placing the following in my .htaccess file:

php_value output_handler ob_gzhandler

However, this only compresses the HTML and leaves out the CSS and JS.

Is there a reliable way of transparently compressing the output of the CSS and JS without having to change every page? I have searched Google and a number of solutions are presented, but I've yet to get one to work. If anyone could suggest a solution that they know to work, that would be very gratefully received.

Note, Method 2 in The Definitive Post on Gzipping your CSS looks like a good solution, but I couldn't get it working. Has anyone else succeeded using this method?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

情绪操控生活 2024-07-11 02:03:29

我所做的:

  • 我分别将脚本放置在 js 目录中,将样式表放置在 css 目录中。
  • 在 Apache 配置中,我添加如下指令:

    <目录/data/www/path/to/some/site/js/>> 
          AddHandler 应用程序/x-httpd-php .js 
          php_value auto_prepend_file gzip-js.php 
          php_flag zlib.output_compression 打开 
       
      <目录/data/www/path/to/some/site/css/>> 
          AddHandler 应用程序/x-httpd-php .css 
          php_value auto_prepend_file gzip-css.php 
          php_flag zlib.output_compression 打开 
       
      
  • js 目录中的

    gzip-js.php 如下所示:

    <前><代码>

  • ...而 css 目录中的 gzip-cs.php 如下所示像这样:

    <前><代码>

这可能不是最优雅的解决方案,但它肯定是一个简单的解决方案,需要很少的变化并且运作良好。

What I do:

  • I place scripts in a js and stylesheets in a css dir, respectively.
  • In the Apache configuration, I add directives like so:

    <Directory /data/www/path/to/some/site/js/>
        AddHandler application/x-httpd-php .js
        php_value auto_prepend_file gzip-js.php
        php_flag zlib.output_compression On
    </Directory>
    <Directory /data/www/path/to/some/site/css/>
        AddHandler application/x-httpd-php .css
        php_value auto_prepend_file gzip-css.php
        php_flag zlib.output_compression On
    </Directory>
    
  • gzip-js.php in the js directory looks like this:

    <?php
        header("Content-type: text/javascript; charset: UTF-8");
    ?>
    
  • …and gzip-cs.php in the css directory looks like this:

    <?php
        header("Content-type: text/css; charset: UTF-8");
    ?>
    

This may not be the most elegant solution, but it most certainly is a simple one that requires few changes and works well.

七月上 2024-07-11 02:03:29

抱歉耽搁了——这对我来说是忙碌的一周。

假设:

  • .htaccesscompress.php 位于同一个文件中
  • 要压缩的静态文件位于 static 子目录中

我从设置.htaccess 中的以下指令:

RewriteEngine on
RewriteRule ^static/.+\.(js|ico|gif|jpg|jpeg|png|css|swf)$ compress.php [NC]

您的提供商需要允许您覆盖 .htaccess 文件中的 mod_rewrite 选项。
那么 compress.php 文件本身可以如下所示:

<?php

$basedir = realpath( dirname($_SERVER['SCRIPT_FILENAME']) );
$file = realpath( $basedir . $_SERVER["REQUEST_URI"] );

if( !file_exists($file) && strpos($file, $basedir) === 0 ) {
    header("HTTP/1.0 404 Not Found");
    print "File does not exist.";
    exit();
}

$components = split('\.', basename($file));
$extension = strtolower( array_pop($components) );

switch($extension)
{
    case 'css':
        $mime = "text/css";
        break;
    default:
        $mime = "text/plain";
}

header( "Content-Type: " . $mime );
readfile($file);

您当然应该向 switch 语句添加更多 mime 类型。 我不想让解决方案依赖于 pecl fileinfo 扩展或任何其他神奇的 mime 类型检测库 - 这是最简单的方法。

至于保护脚本 - 我将其转换为文件系统中的真实路径,因此不会出现被黑的“../../../etc/passwd”或其他 shellscript 文件路径。

这就是

$basedir = realpath( dirname($_SERVER['SCRIPT_FILENAME']) );
$file = realpath( $basedir . $_SERVER["REQUEST_URI"] );

片段。 尽管我非常确定除 $basedir 以外的其他层次结构中的大多数路径在到达脚本之前都会由 Apache 处理。

我还检查生成的路径是否位于脚本的目录树内。
按照 pilif 的建议添加缓存控制的标头,您应该可以找到解决问题的方法。

Sorry about the delay - it's a busy week for me.

Assumptions:

  • .htaccess is in the same file as compress.php
  • static files to be compressed are in static subdirectory

I started my solution from setting the following directives in .htaccess:

RewriteEngine on
RewriteRule ^static/.+\.(js|ico|gif|jpg|jpeg|png|css|swf)$ compress.php [NC]

It's required that your provider allows you to override mod_rewrite options in .htaccess files.
Then the compress.php file itself can look like this:

<?php

$basedir = realpath( dirname($_SERVER['SCRIPT_FILENAME']) );
$file = realpath( $basedir . $_SERVER["REQUEST_URI"] );

if( !file_exists($file) && strpos($file, $basedir) === 0 ) {
    header("HTTP/1.0 404 Not Found");
    print "File does not exist.";
    exit();
}

$components = split('\.', basename($file));
$extension = strtolower( array_pop($components) );

switch($extension)
{
    case 'css':
        $mime = "text/css";
        break;
    default:
        $mime = "text/plain";
}

header( "Content-Type: " . $mime );
readfile($file);

You should of course add more mime types to the switch statement. I didn't want to make the solution dependant on the pecl fileinfo extension or any other magical mime type detecting libraries - this is the simplest approach.

As for securing the script - I do a translation to a real path in the file system so no hacked '../../../etc/passwd' or other shellscript file paths don't go through.

That's the

$basedir = realpath( dirname($_SERVER['SCRIPT_FILENAME']) );
$file = realpath( $basedir . $_SERVER["REQUEST_URI"] );

snippet. Although I'm pretty sure most of the paths that are in other hierarchy than $basedir will get handled by the Apache before they even reach the script.

Also I check if the resulting path is inside the script's directory tree.
Add the headers for cache control as pilif suggested and you should have a working solution to your problem.

执笔绘流年 2024-07-11 02:03:29

无论你做什么,都要小心客户端的缓存:

浏览器​​会采取各种技巧来尝试最小化带宽,HTTP 协议中有很多方法可以做到这一点,所有这些都由 apache 处理 - 如果你只是提供本地文件。

如果您不这样做,那么这是您的责任

至少看一下当前所有浏览器都支持的 ETag 和 If-Modified-Since 机制,它们似乎是查询服务器更新内容的最可靠的方法。

使用 If-Modified-Since-Header 向浏览器提供 CSS 文件的可能方法如下(空标头用于关闭 PHP 默认发送的任何非缓存标头):

$p = 'path/to/css/file'
$i = stat($p);
if ($_SERVER['HTTP_IF_MODIFIED_SINCE']){
    $imd = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
    if ( ($imd > 0) && ($imd >= $i['mtime'])){
        header('HTTP/1.0 304 Not Modified');
        header('Expires:');
        header('Cache-Control:');
        header('Last-Modified: '.date('r', $i['mtime']));
        exit;
    }
}
header('Last-Modified: '.date('r', $i['mtime']));
header('Content-Type: text/css');
header('Content-Length: '.filesize($p));
header('Cache-Control:');
header('Pragma:');
header('Expires:');
readfile($p);

代码将使用 if-modified-浏览器发送的since-header来检查服务器上的实际文件自浏览器给出的日期以来是否已更改。 如果是,则发送该文件,否则,将返回 304 Not Modified,并且浏览器不必重新下载整个内容(如果它足够智能,它也会将解析后的 CSS 保留在内存中)。

还有另一种机制涉及服务器为每段内容发送唯一的 ETag-Header。 客户端将使用 If-None-Match 标头将其发回,从而使服务器不仅可以决定上次修改的日期,还可以决定内容本身。

但这只会使代码变得更加复杂,所以我将其省略了。 FF、IE 和 Opera(可能还有 Safari)在收到附加了 Last-Modified 标头的内容时都会发送 If-Modified-Since 标头,因此效果很好。

另请记住,某些版本的 IE(或其使用的 JScript-Runtime)仍然在处理 GZIP 传输的内容时存在问题。

哦。 我知道这不是问题的一部分,但 Acrobat 在某些版本中也是如此。 我在使用 gzip 传输编码提供 PDF 时遇到过白屏的情况。

what ever you do, be careful about caching on the client side:

Browsers do all sort of tricks to try and minimize the bandwith and there are many ways in the HTTP protocol to do that, all of which are dealt with by apache - if you are just serving a local file.

If you are not, then it's your responsibility.

Have a look at least at the ETag and the If-Modified-Since mechanics which are supported by all current browsers and seem to be the most robust way to query the server for updated content.

A possible way to serve a CSS file to browsers using the If-Modified-Since-Header is something like this (the empty headers to turn off any non-caching headers PHP sends per default):

$p = 'path/to/css/file'
$i = stat($p);
if ($_SERVER['HTTP_IF_MODIFIED_SINCE']){
    $imd = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
    if ( ($imd > 0) && ($imd >= $i['mtime'])){
        header('HTTP/1.0 304 Not Modified');
        header('Expires:');
        header('Cache-Control:');
        header('Last-Modified: '.date('r', $i['mtime']));
        exit;
    }
}
header('Last-Modified: '.date('r', $i['mtime']));
header('Content-Type: text/css');
header('Content-Length: '.filesize($p));
header('Cache-Control:');
header('Pragma:');
header('Expires:');
readfile($p);

The code will use the if-modified-since-header the browser sends to check if the actual file on the server has changed since the date the browser has given. If so, the file is sent, otherwise, a 304 Not Modified is returned and the browser does not have to re-download the whole content (and if it's intelligent enough, it keeps the parsed CSS around in memory too).

There is another mechanic involving the server sending a unique ETag-Header for each piece of content. The Client will send that back using an If-None-Match header allowing the server to decide not only on the date of last modification but also on the content itself.

This just makes the code more complicated though, so I have left it out. FF, IE and Opera (probably Safari too) all send the If-Modified-Since header when they receive content with a Last-Modified header attached, so this works fine.

Also keep in mind that certain versions of IE (or the JScript-Runtime it uses) still have problems with GZIP-transferred content.

Oh. And I know that's not part of the question, but so does Acrobat in some versions. I've had cases and cases of white screens while serving PDFs with gzip transfer encoding.

浮华 2024-07-11 02:03:29

您可以使用 mod_rewrite 试试运气。

创建一个脚本,通过例如 $_SERVER['QUERY_STRING'] 将本地静态文件名作为输入,并以压缩形式输出。 许多提供商不允许使用 .htaccess 文件配置 mod_rewrite 或将其完全禁用。

如果您之前没有使用过 rewrite,我推荐一本很好的初学者指南,例如 这个
这样你就可以让 apache 将所有对静态文件的请求重定向到 php 脚本。 例如,style.css 将被重定向到 compress.php?style.css

与往常一样,对您接受的输入要极其谨慎,否则您就会遇到 XSS 漏洞!

You can try your luck with mod_rewrite.

Create a script that takes a local static file name as input, through e.g. $_SERVER['QUERY_STRING'] and outputs it in compressed form. Many providers don't allow configuring mod_rewrite with .htaccess files or have it completely disabled though.

If you haven't used rewrite before, I recommend a good beginner's guide, like probably this one.
This way you can make the apache redirect all requests for a static file to a php script. style.css will be redirected to compress.php?style.css for instance.

As always be extremely cautious on the input you accept or you have an XSS exploit on your hands!

放肆 2024-07-11 02:03:29

您可以提前对 CSS 和 JavaScript 文件进行 gzip,而不是在用户请求 CSS 和 JavaScript 文件时动态进行 gzip。 只要 Apache 为他们提供正确的标头,您就是黄金。

例如,在 Mac OS X 上,在命令行上对文件进行 gzip 压缩就像这样简单:

gzip -c styles.css > styles-gzip.css

但可能不是适合您的工作流程。

Instead of gzipping on the fly when users request the CSS and JavaScript files, you could gzip them ahead of time. As long as Apache serves them with the right headers, you’re golden.

For example, on Mac OS X, gzipping a file on the command line is as easy as:

gzip -c styles.css > styles-gzip.css

Might not be the sort of workflow that works for you though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文