网站通过 mod_rewrite 快 5 倍,但 CSS 图像损坏

Posted

技术标签:

【中文标题】网站通过 mod_rewrite 快 5 倍,但 CSS 图像损坏【英文标题】:site 5x faster via mod_rewrite, but CSS images are broken 【发布时间】:2010-10-12 15:44:22 【问题描述】:

我正在使用 .htaccess 通过以下重定向加速网站:

request for http://example.com/images/name.jpg  routed to  http://i.example.com/name.jpg
request for http://example.com/css/name.css     routed to  http://c.example.com/name.css

通过收听 Stack Overflow 播客,我了解到这可以使网站更快,因为浏览器可以同时下载更多文件(显然每个域有两个流,尽管这尚未得到证实)。

确实,差异是巨大的;页面加载速度大约是 五倍

我没有动过原始文件夹和图片 -- 我只是使用 mod_rewrite 将地址从 example.com/images/ 更改为 i.example.com/

rewritecond %HTTP_HOST !^i\.example\.com [NC] rewriterule ^images/([^/]+)$ http://i.example.com/$1 [L] rewritecond %HTTP_HOST !^c\.example\.com [NC] 重写 ^css/([^/]+)$ http://c.example.com/$1 [L]

我遇到的问题是,这种技术非常适用于 html 中包含的图像标签,但不适用于通过样式表包含的图像:

img src=/images/logo.jpg完美运行

background:url(/images/logo.jpg);不起作用

服务器错误日志包含以下条目:

文件不存在:/var/www/html/css/images,引用者:http://example.com/page.html

这似乎意味着重写规则的应用不正确。

如果我使用样式表可以工作:

背景:url(http://i.example.com/logo.jpg);

但是,为了避免重写所有样式表,我想知道:为什么 url 重写不像 html img 标签那样适用于样式表

[update1] Safari 4 Beta、Firefox 3.0.3 和 Chrome 中存在此问题,但 页面在 IE6 中完美运行

[update2] 添加 [L,R=301] 和 [L,R=302] 没有帮助。

[update3]我根据 Gumbo 的以下建议尝试了以下操作:

如果路径与主机名不匹配,则外部重定向:

rewritecond %HTTP_HOST     !^i\.domain\.com$
rewriterule ^images/([^/]+)$ http://i.domain.com/$1 [L,R=301]
rewritecond %HTTP_HOST     !^c\.domain\.com$
rewriterule ^css/([^/]+)$    http://c.domain.com/$1 [L,R=301]

内部重定向;如果有不必要的文件夹名称,请将其删除(请参阅上面的服务器错误):

rewritecond %HTTP_HOST     ^i\.domain\.com$
rewriterule ^images/([^/]+)$ $1 [L]
rewritecond %HTTP_HOST     ^c\.domain\.com$
rewriterule ^css/([^/]+)$    $1 [L]

还是不行。奇怪的是,服务器错误是:

文件不存在:/var/www/html/css/var,引用者:http://domain.com/page.html

【问题讨论】:

您真的在样式表中使用绝对路径吗? 好吧,我对此行为的唯一解释是样式表“/css/bar”中的相对路径“images/foo”被(正确)解析为“/css/images/foo” .使用绝对路径可以解决这个问题。 我回去验证了,确实是绝对路径。由于不同浏览器的行为会发生变化,这可能与浏览器出于缓存原因尝试解释 CSS 图像的方式有关。我也试过../images和../../images,还是坏了。 除了这个问题:您的方法将导致 302 外部重定向,从而使请求数量增加一倍。你确定要这个吗?为什么不首先使用不同的域? 也许样式表认为它位于 c.example.com 并在 c.example.com/images/logo.jpg 中查找 url ? 【参考方案1】:

我能够通过不尝试将目录合并到子域中来解决此问题

请求 domain.com/images/ 路由到 i.domain.com/images/ 对 domain.com/css/ 的请求路由到 c.domain.com/css/

它运行良好并且仍然非常快

现代浏览器中似乎存在一个错误,其中重定向的 css 请求将仅应用新域,将原始目录作为请求的一部分:

如果 url(domain.com/images/name.jpg) 处的 css 图片被重定向到 i.domain.com/name.jpg,浏览器将错误地请求 i.domain.com/images/name.jpg

【讨论】:

【参考方案2】:

如果所有主机名都使用相同的虚拟主机,我找到了解决此问题的方法:

# redirect externally if path doesn’t match host name
RewriteCond %HTTP_HOST !^i\.example\.com$
RewriteRule ^images/([^/]+)$ http://i.example.com/$1 [L,R=301]
RewriteCond %HTTP_HOST !^c\.example\.com$
RewriteRule ^css/([^/]+)$ http://c.example.com/$1 [L,R=301]

# redirect internally to the file
RewriteCond %HTTP_HOST ^i\.example\.com$
RewriteRule !^images/ images%REQUEST_URI [L]
RewriteCond %HTTP_HOST ^c\.example\.com$
RewriteRule !^css/ css%REQUEST_URI [L]

这将执行以下操作:

http://example.com/css/foo       externally to    http://c.example.com/foo
http://c.example.com/foo         internally to    /css/foo

http://example.com/images/bar    externally to    http://i.example.com/bar
http://i.example.com/bar         internally to    /images/bar

以及纠正不匹配的路径和主机名:

http://i.example.com/css/foo     externally to    http://c.example.com/foo
http://c.example.com/images/bar  externally to    http://i.example.com/bar

当请求的样式表 http://example.com/css/foo 被重定向到 http://c.example.com/foo 并且样式表内的图像 URI 引用(如 /images/bar)从这个新的基本 URI 解析并因此导致 http://c.example.com/images/bar 而不是初始 @ 987654331@.

【讨论】:

此解决方案在内部将i.example.com/bar 重新映射到 /images/bar,而不是我需要的。我认为解决最初问题的方法是将i.example.com/images/bar 重新映射到i.example.com/bar。它不起作用(请参阅修改后的问题)。

以上是关于网站通过 mod_rewrite 快 5 倍,但 CSS 图像损坏的主要内容,如果未能解决你的问题,请参考以下文章

Protobuf有没有比JSON快5倍?用代码来击破pb性能神话

赶快使用 Firefox 57吧! 速度比以前快2倍

只允许某些IP地址使用mod_rewrite访问网站?

据说比Spring快44倍的web开发框架,不妨试试

面试总结之mysql

在 url mod_rewrite 中隐藏扩展名 .php