如何缓存 Rails webpack 包

Posted

技术标签:

【中文标题】如何缓存 Rails webpack 包【英文标题】:How to cache Rails webpack packs 【发布时间】:2020-10-11 01:09:15 【问题描述】:

我有一个 Rails 6 应用程序,其中包含大量供应商 CSS 和 JS。 CSS 和 JS 很少会改变。我希望 Rails 缓存它。

我创建了 2 个包。 1 包含来自供应商的所有导入,另一个包含我的应用程序 JS 的导入。我在两者的头部都使用javascript_packs_with_chunks_tag

每当我修改应用程序的 JS 文件时,该包的缓存也会与供应商的包一起失效!

这种行为似乎很正常,因为我能够使用新的 Rails 应用程序重现它。

编辑:我可以通过关闭编译 (webpacker.yml compile: false) 并在单独的终端选项卡 (./bin/webpack --watch --colors --progress) 中运行 webpack 来解决新 Rails 应用程序中的问题,但在我的应用程序中我仍然遇到问题. Webpack 似乎发现了一些全局变量或关键字来连接这两个包。不幸的是,Webpack 日志和依赖关系图没有显​​示“连接”。 100% 不是import

【问题讨论】:

问题是即使内容没有改变,供应商资产的输出文件哈希也在改变。显然 webpack 添加了时间戳和其他东西,所以哈希正在改变。如果输出文件名(包括哈希)没有改变,缓存将起作用。 Webpack 解决了这个问题(webpack.js.org/guides/caching/),因此可以通过 webpacker 适当地配置 webpack。 很棒的提示,@LesNightingill !您是说“webpacker* 添加时间戳和其他内容”吗?因为根据 webpack 的说法,“[contenthash] 替换将根据资产的内容添加唯一的哈希。当资产的内容发生变化时,[contenthash] 也会发生变化。”。但是,当您查看 webpacker 的配置 gist.github.com/hrdwdmrbl/… 时,看起来他们没有明确添加时间戳或任何额外内容。 如果您从引用的引文往下看几段,它还会说“如果我们在不进行任何更改的情况下运行另一个构建,我们希望该文件名保持不变。但是,如果我们再次运行它,我们可能会发现情况并非如此”,然后继续解释原因。我认为时间戳等已添加到内容中,因此 contenthash 会发生变化(这就是您所看到的,对吗?哈希会发生变化,但您没有对供应商内容进行任何更改)。看起来 webpacker 会合并您提供的任何选项。所以看看你是否可以整合 webpack 记录的想法。 如果您成功获得仅基于代码而不是 webpack 开销的 contenthash,请告诉我们。 我刚刚尝试了一个实验...在我的开发机器上运行 webpack 编译几次,没有代码更改...我没有看到文件名更改,正如 webpack 文档所建议的那样他们可能。所以我可能完全错了!问题是......在您的生产服务器上,当没有代码更改时,供应商包文件名是否会更改?我(还没有)进行代码拆分,所以这可以解释我的结果。 【参考方案1】:

我发现一个简单的解决方案是将供应商 CSS 和 JS 移动到 sprockets 而不是 webpack。我不喜欢这个解决方案,但它确实有效。

为此,请使用 sprocket 类型的包含语句

<%= javascript_include_tag 'vendor' %>
<%= stylesheet_link_tag 'vendor' %>

并将您的供应商 js 和 CSS 放在各自的 app/assets 文件夹中

【讨论】:

你是怎么做到的?【参考方案2】:

另一种解决方案是禁用编译 webpacker.yml compile: false 并单独运行 webpack $./bin/webpack --watch --colors --progress.

这里记录了 https://github.com/rails/webpacker#development,它说“如果 [...] 你有足够的 JavaScript 以至于按需编译太慢...”。

我也不喜欢这个解决方案,因为它没有解释为什么这是必要的。问题不在于编译太慢,而是没有发生缓存。这种解决方案通常会同时解决缓存问题...

【讨论】:

【参考方案3】:

此处提升为答案的评论...

虽然人们希望在供应商代码不变的情况下跳过编译,但情况似乎并非如此。但是,如果内容没有改变,编译代码的文件名不应该*改变。

假设您已经获得了一个不会更改的文件名,那么即使供应商代码被不必要地编译,正常的 http 缓存控制机制也应该提供所需的缓存。如何控制 http 缓存控制标头的一个参考是here

*webpack 文档中对此有一些含糊之处,其中表明某些版本可能会更改编译后的文件名(哈希值),即使代码未更改,由于时间戳和 webpack 添加的其他内容。 (webpack docs) 确实描述了如果您发现文件名哈希发生变化时可用的缓解措施。

【讨论】:

最好不要在没有引用或引用或突出显示重要部分的情况下链接外部资源(阅读***.com/help/how-to-answer)。您能否简要描述一下您建议的修复/缓解措施是什么?

以上是关于如何缓存 Rails webpack 包的主要内容,如果未能解决你的问题,请参考以下文章

Rails webpacker jquery undefined `$` undefined

如何在 Rails 中检查 webpacker 版本?

如何使用webpack打包你的项目

如何使用 @rails/webpacker 加载本地字体?

如何在 webpacker rails 中使用 ProvidePlugin?

webpack 图片处理和优化