使用 htaccess 进行自动版本控制:htaccess 正则表达式重写规则未拾取模式
使用答案中的建议 这个问题,以及这篇文章 它提供了几乎相同的解决方案,我一直在尝试设置 htaccess 来处理我的 js 和 css 文件上的自动版本控制规则。
我想这样做的原因是我对它们进行了很多更改,但仍然希望它们被浏览器缓存很长一段时间,而不必在每次更改时手动输入新的版本号。
使用的方法很简单:(1) 函数使用更改日期将版本号附加到文件,格式为 [filename].[version_number].[suffix]
,因此 <例如,code>style.css 将变为 style.1300638388.css
; (2) 使用 php,版本号包含在我网站页面的样式表声明中,并且该版本号提供给客户端浏览器,如果版本化文件名与缓存的文件名不同,客户端浏览器将请求新副本; (3) .htaccess 中的 RewriteRule 使用 mod_rewrite 重写版本号,将其恢复为其原始值并提供更新的文件。
下面列出了我在这三个阶段中每个阶段使用的代码。我正在我的博客的沙盒版本中的样式表上对此进行测试 http://edge.donaldjenkins.net/< /a>
1. 在WordPress 的functions.php 文件中
// Allows autoversioning of css and js files
/**
* Given a file, i.e. /css/base.css, replaces it with a string containing the
* file's mtime, i.e. /css/base.1221534296.css.
*
* @param $file The file to be loaded. Must be an absolute path (i.e.
* starting with slash).
*/
function auto_version($file)
{
if(strpos($file, '/') !== 0 || !file_exists($_SERVER['DOCUMENT_ROOT'] . $file))
return $file;
$mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $file);
}
2. 在我的博客文件的
部分中
<!-- Stylesheets -->
<link rel="stylesheet" href="<?=auto_version('/path/to/style.css')?>" />
3. 在.htaccess 文件中
# Allow versioning for js and css files
RewriteEngine On
RewriteRule ^(.*)\.[\d]+\.(css|js)$ $1.$2 [L] # Strip out the version number
# End Allow versioning for js and css files
通过上述设置,页面显示时不带任何格式,生成页面的源代码显示样式表被引用为版本号——这当然在服务器上不存在。
这表明该函数正确地更改了样式表的名称,但由于某种原因,.htaccess 中的 RewriteRule 中的正则表达式模式无法捕获文件名并重写它。事实上,如果我将其更改为 ^style.1300638388.css$ style.css [L]
,它甚至无法捕获它。
我尝试了几种模式,但都无济于事,但一定缺少一些非常基本的东西。
mod_rewrite
在服务器上打开,并且对于其他几个 RewriteRule 实例运行没有问题。
更新
.htaccess
文件中唯一的其他 RewriteRule 是标准 WordPress 漂亮 URL 重写规则。我怀疑它会干扰这个,尽管显然我无法在没有 WordPress 规则的情况下轻松测试,因为这会完全破坏页面生成:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
更新 2:已解决
CharlesLeaf 在下面的评论中指出,由于 WordPress规则先于版本控制规则,后者将不会被执行。这实际上就是原因,让我可以通过对两条规则进行分组来回答问题,如下所示:
<IfModule mod_rewrite.c>
# Allow versioning for js and css files
RewriteEngine On
RewriteRule ^(.*)\.[\d]+\.(css|js)$ $1.$2 [L] # Strip out the version number
# End Allow versioning for js and css files
# BEGIN WordPress
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php
# END WordPress
</IfModule>
Using a suggestion in the answer to this question, as well as this article which offers an almost identical solution, I've been trying to set up htaccess to handle an autoversioning rule on my js and css files.
The reason I want to do this is that I change them quite a lot, but still want them to be cached by browsers for aggressively long periods, without having to manually enter a new version number each time they are changed.
The method used is simple: (1) a function appends a version number to files using the date on which they were changed, on the pattern [filename].[version_number].[suffix]
, so style.css
, for instance, would become, say, style.1300638388.css
; (2) using php, the versioned number is included in the stylesheet declaration for my site's pages, and this is served to client browsers who will request a fresh copy if the versioned file name differs from that they have cached; (3) a RewriteRule in .htaccess using mod_rewrite rewrites the versioned number, reverts it to its original value and serves the updated file.
The code I'm using at each of these three stages is listed below. I'm testing this on the stylesheet in a sandbox version of my blog on http://edge.donaldjenkins.net/
1. In WordPress's functions.php file
// Allows autoversioning of css and js files
/**
* Given a file, i.e. /css/base.css, replaces it with a string containing the
* file's mtime, i.e. /css/base.1221534296.css.
*
* @param $file The file to be loaded. Must be an absolute path (i.e.
* starting with slash).
*/
function auto_version($file)
{
if(strpos($file, '/') !== 0 || !file_exists($_SERVER['DOCUMENT_ROOT'] . $file))
return $file;
$mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $file);
}
2. In the <head>
portion of my blog files
<!-- Stylesheets -->
<link rel="stylesheet" href="<?=auto_version('/path/to/style.css')?>" />
3. In the .htaccess file
# Allow versioning for js and css files
RewriteEngine On
RewriteRule ^(.*)\.[\d]+\.(css|js)$ $1.$2 [L] # Strip out the version number
# End Allow versioning for js and css files
With the setup described above, pages display without any formatting, and source code of the generated page shows that the stylesheet is referenced as the versioned number—which of course doesn't exist on the server.
This would suggest that the function is correctly changing the name of the stylesheet, but that for some reason the regex pattern in the RewriteRule in .htaccess isn't catching the file name and rewriting it. In fact, it doesn't even catch it if I change it to ^style.1300638388.css$ style.css [L]
.
I've tried several patterns, to no avail, but must be missing something pretty basic.
mod_rewrite
is on on the server and runs without issues for several other RewriteRule instances.
UPDATE
The only other RewriteRule in the .htaccess
file is the standard WordPress pretty url rewrite rule. I doubt it interferes with this one, although obviously I can't easily test without the WordPress rule as this would completely break page generation:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
UPDATE 2: SOLVED
CharlesLeaf in a comment below pointed out that as the WordPress rule was before the versioning one, the latter would not be carried out. This actually was the reason and allowed me answer the question by grouping the two rules, as follows:
<IfModule mod_rewrite.c>
# Allow versioning for js and css files
RewriteEngine On
RewriteRule ^(.*)\.[\d]+\.(css|js)$ $1.$2 [L] # Strip out the version number
# End Allow versioning for js and css files
# BEGIN WordPress
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php
# END WordPress
</IfModule>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
^ 表示“字符串的开头”,在本例中不是“style”,而是 /path/to/style。
您可以尝试使用正则表达式中的完整路径,或者查看 RewriteBase。
更新的解决方案
这种情况下的问题是,在相关的 RewriteRule 之前还有其他 RewriteRule,因此它永远不会到达此 RewriteRule。 RewriteRules 的正确顺序很重要。
^ means the 'start of the string', which isn't 'style' in this case but /path/to/style.
You could try it with the full path in the regex, or look into RewriteBase perhaps.
updated solution
The problem in this scenario was that there were other RewriteRules before the one in question, so it never reached this RewriteRule. The right order of RewriteRules is important.
感谢您提供 .htaccess 解决方案。我遇到了 jQuery 插件文件的问题,这些文件在文件名中包含自己的版本控制方案,如 jquery.NAME-OF-PLUGIN.1.1.1.js 中所示。我建议使用
[0-9]{10}
解析文件修改时间,以便仅“删除”十位数字后缀。如果文件名末尾有十位数字,仍然可能会出现错误,但这只是一种罕见的边缘情况。此外,直到 2286 年 11 月 20 日星期六 17:46:40 GMT 之前才需要考虑 UNIX 纪元时间戳中的 11 位数字。
Thank you for the .htaccess solution. I've had issues with jQuery plugin files that include their own versioning scheme in the file name as in jquery.NAME-OF-PLUGIN.1.1.1.js. I recommend parsing the file modified time with
[0-9]{10}
, so that only a ten digit suffix will be "removed." It's still possible for errors if the filename has ten digits at the end of it, but that would be a rare edge case.Also 11 digits in the UNIX Epoch timestamp won't need to be accounted for until Sat, 20 Nov 2286 17:46:40 GMT.