使用htaccess进行自动版本控制:htaccess正则表达式重写规则未识别模式。

8
这个问题的答案中,以及这篇文章提供了几乎相同的解决方案。我一直在尝试设置htaccess来处理我的js和css文件的自动版本控制规则。
我之所以要这样做是因为我经常更改它们,但仍然希望它们能被浏览器缓存很长时间,而不必每次更改时手动输入新版本号。
使用的方法很简单:(1)一个函数使用文件修改日期将版本号附加到文件上,模式为[filename].[version_number].[suffix],因此,例如,style.css将变成style.1300638388.css;(2)使用php,在我的网站页面的样式表声明中包含了版本号,并向客户端浏览器提供该信息,在版本化文件名与他们缓存的文件名不同时,请求更新的副本;(3)使用mod_rewrite在.htaccess中添加RewriteRule重写版本号,将其恢复为原始值并提供更新后的文件。
我在以下三个阶段使用的代码如下。我在http://edge.donaldjenkins.net/的博客沙盒版本上测试了这个样式表。

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. 在我的博客文件的<head>部分


<!-- 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重写规则。我怀疑它不会干扰这一个,尽管显然我不能轻易地进行测试,因为这将完全破坏页面生成。
# 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>
2个回答

3

^表示字符串的开头,这里不是指'style',而是指/path/to/style。

你可以尝试在正则表达式中使用完整的路径,或者考虑使用RewriteBase。

更新的解决方案 在这种情况下的问题是,在这个RewriteRule之前有其他的RewriteRules,所以它从来没有到达过这个RewriteRule。正确的RewriteRules顺序很重要。


如果您以 ^path 开始呢?(因为第一个斜杠可能不包括在内) - CharlesLeaf
@Charles:不幸的是,^path\/to\/(.*)\.[\d]+\.(css|js)$ $1.$2 [L]产生了相同的结果。:( - Donald Jenkins
你应该将/path/to添加到重写URL中,但我不确定这是否足够。然而,由于我实际上没有看到其他错误 - 我唯一能想象的是其他重写规则正在干扰,阻止这个规则被处理...也许? - CharlesLeaf
@Charles:我也尝试过,但是没有任何改变。.htaccess文件只包含另一个RewriteRule,这是WordPress的一个完全标准的规则:我已经编辑了我的初始问题并包含了它。 - Donald Jenkins
如果这个来自WordPress的RewriteRule放在你的自动版本控制之前,它会干扰到所有的重写,并且由于[L]标志(最后一个规则标志),它将停止寻找其他的RewriteRules。所以最后一个问题是,你的(带路径的)RewriteRule是在WordPress RewriteRule之前还是之后? - CharlesLeaf
显示剩余2条评论

2
感谢提供.htaccess的解决方案。我曾经遇到过包含自己版本号方案的jQuery插件文件,例如jquery.NAME-OF-PLUGIN.1.1.1.js。我建议使用[0-9]{10}解析文件修改时间,这样只有十位数字后缀才会被“移除”。如果文件名末尾有十位数字,仍可能出现错误,但这是一种罕见的情况。
# Allow versioning for js and css files

RewriteRule ^(.*)\.[0-9]{10}\.(css|js)$ $1.$2 [L] # Strip out the version number

# End Allow versioning for js and css files

同时,在UNIX Epoch时间戳中的11位数字不需要考虑,直到2286年11月20日周六17:46:40 GMT。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接