Grunt filerev、usemin 和文件缓存
Grunt filerev, usemin and file caching
我正在使用 g运行t filerev
任务在文件内容更改时将缓存无效化程序添加到文件中。 usemin
任务将相关文件路径替换为其引用的修订版本。一切都已设置好,并且他们正在按预期/在他们的文档中写的那样工作。
我现在将尝试解释这个问题:
这是一个Angular JS项目,简化后的结构有点像这样:
a.html -> b.js -> c.html (partial)
这里 a.html 指的是 b.js 并且 b.js 加载 c.html 作为部分。服务器设置为缓存所有这些资产,因此缓存无效化字符串变得很重要。
当我运行grunt build
执行filerev
然后usemin
时,它会将c.html
重命名为c.[md5_hash_of_c].html
,b.js
到 b.[md5_hash_of_b].js
和 a.html
到 a.[md5_hash_of_a].html
。在此之后,它将 c.html
的 b.js
中的参考线更新为 c.[md5_hash_of_c].html
。同样,它也会更新 a.html
。这意味着当计算哈希值时,这些文件仍然引用了其他文件的未修订版本。因此,当 c.html
的内容更改时,它会更新其在 b.js
中的引用,但不会更新 b.js
的名称以反映此更改。
这违背了在文件名中获取缓存清除器的目的。因为现在浏览器缓存了 b.[md5_hash_of_b].js
和 a.[md5_hahs_of_a].html
,所以更新 c.[md5_hash_of_c].html
的调用失败。
我在想,在 angular 世界和其他地方,这应该是一个非常标准的做法,但在任何地方都看不到它的详细讨论。我正在寻找可以解决此问题的工作流程。
发现这个问题在 three different places 上讨论过。第三个link最接近解。
我最终使用 vermin
作为 filerev
和 usemin
的替代任务,它在内部重复执行这两个任务,直到文件名停止更改。它在此处作为要点共享:https://gist.github.com/markrian/aa185c5ec66232a38a68
来自要点评论:
/**
* Vermin completely manages the running of the filerev and usemin tasks, so
* that assets that reference other assets are correctly hashed after their
* referenced assets are spliced in by usemin.
*
* Vermin also makes various assumptions about how filerev and usemin are set
* up. For instance, it assumes that usemin runs immediately after filerev,
* that filerev renames files in-place, and that usemin relies on
* `grunt.filerev.summary`, as prepared by filerev (which vermin manipulates).
* There may be other implicit assumptions that haven't been identified yet.
*
* Because grunt tasks can only be inserted into the task stack, to be run
* sequentially, vermin recursively adds filerev, usemin and itself to the
* stack to do its work. It maintains its state on the grunt object, and reads
* that on each run to determine where in the process it is.
*/
我正在使用 g运行t filerev
任务在文件内容更改时将缓存无效化程序添加到文件中。 usemin
任务将相关文件路径替换为其引用的修订版本。一切都已设置好,并且他们正在按预期/在他们的文档中写的那样工作。
我现在将尝试解释这个问题:
这是一个Angular JS项目,简化后的结构有点像这样:
a.html -> b.js -> c.html (partial)
这里 a.html 指的是 b.js 并且 b.js 加载 c.html 作为部分。服务器设置为缓存所有这些资产,因此缓存无效化字符串变得很重要。
当我运行grunt build
执行filerev
然后usemin
时,它会将c.html
重命名为c.[md5_hash_of_c].html
,b.js
到 b.[md5_hash_of_b].js
和 a.html
到 a.[md5_hash_of_a].html
。在此之后,它将 c.html
的 b.js
中的参考线更新为 c.[md5_hash_of_c].html
。同样,它也会更新 a.html
。这意味着当计算哈希值时,这些文件仍然引用了其他文件的未修订版本。因此,当 c.html
的内容更改时,它会更新其在 b.js
中的引用,但不会更新 b.js
的名称以反映此更改。
这违背了在文件名中获取缓存清除器的目的。因为现在浏览器缓存了 b.[md5_hash_of_b].js
和 a.[md5_hahs_of_a].html
,所以更新 c.[md5_hash_of_c].html
的调用失败。
我在想,在 angular 世界和其他地方,这应该是一个非常标准的做法,但在任何地方都看不到它的详细讨论。我正在寻找可以解决此问题的工作流程。
发现这个问题在 three different places 上讨论过。第三个link最接近解。
我最终使用 vermin
作为 filerev
和 usemin
的替代任务,它在内部重复执行这两个任务,直到文件名停止更改。它在此处作为要点共享:https://gist.github.com/markrian/aa185c5ec66232a38a68
来自要点评论:
/**
* Vermin completely manages the running of the filerev and usemin tasks, so
* that assets that reference other assets are correctly hashed after their
* referenced assets are spliced in by usemin.
*
* Vermin also makes various assumptions about how filerev and usemin are set
* up. For instance, it assumes that usemin runs immediately after filerev,
* that filerev renames files in-place, and that usemin relies on
* `grunt.filerev.summary`, as prepared by filerev (which vermin manipulates).
* There may be other implicit assumptions that haven't been identified yet.
*
* Because grunt tasks can only be inserted into the task stack, to be run
* sequentially, vermin recursively adds filerev, usemin and itself to the
* stack to do its work. It maintains its state on the grunt object, and reads
* that on each run to determine where in the process it is.
*/