【问题标题】:How to use Cache-Busting with Webpack?如何让 Webpack 使用 Cache-Busting 后缀?
【发布时间】:2017-01-07 08:50:39
【问题描述】:

在使用 Webpack 之前,我总是依赖以下“缓存清除”模式:

<script src="foo.js?cacheBust=12345" />

12345 是服务器在每次构建时为我生成的令牌(它可能是 Git 哈希,但在我的情况下不是)。

使用 Webpack,我现在有两个文件:build.jschunk.1.js。由于我将第一个带入普通脚本标签,因此我可以使用上述模式:

<script src="build.js?cacheBust=12345" />

但是,此时build.js 会去获取chunk.1.js,但它不包含缓存清除后缀。

我希望 Webpack 自动附加 ?cacheBust=12345,但在构建时我不知道 12345 部分,所以我不能将它包含在我的 webpack.config 中。相反,我必须等到 HTML 页面被评估,此时我从服务器获取令牌。

所以,我的问题是,有没有办法让 Webpack 查看用于获取初始文件的参数(例如?cacheBust=12345)并在获取其他文件时附加相同的参数?

【问题讨论】:

  • 当其内容更改时,您希望将查询参数添加到同一文件的技术不会导致缓存失效。见:stevesouders.com/blog/2008/08/23/…
  • 我认为您可能读得太快了:它并没有说该技术不起作用。它确实说的是,如果您像 Steve Souders 那样使用 Squid 代理,该技术将无法工作。服务器如何处理请求完全取决于服务器,但根据我的经验,大多数主要的服务器端框架以及大多数 Web 服务器(例如 Apache)确实对 foo.pngfoo.png?v=1 有不同的处理方式。
  • 本文的重点是强调这样一个事实,即客户端和服务器之间可能存在的任何代理服务器很可能会丢弃查询参数并检查文件的缓存版本。如果在代理上为真,则不会检索您的文件的新版本,用户将看到较旧的缓存版本。
  • 如果您查看第 1 部分 @Everettes 的答案,它确实回答了您的问题。使用[chunkhash] 的chunkFilename 是破坏缓存的最佳方式。如果您将这些文件存储在 git 中,您可以 git rm 文件,进行构建,然后 git add。那些哈希值没有改变的文件将被简单地“恢复”,而那些哈希值改变的文件将消失。考虑解决方案,而不是机制。
  • 这是一个古老的论点,但 Souders 臭名昭著的博客文章却大错特错。使用查询字符串进行缓存清除比他想象的要有效得多。

标签: javascript webpack browser-cache


【解决方案1】:

如果您想以“webpack方式”实现缓存清除:

1。输出文件的哈希名称

将输出文件名更改为哈希生成的名称(在构建阶段)

output: {
    path: '/',
    filename: '[hash].js',
    chunkFilename: '[chunkhash].js',
},

从那时起,您的 foo.jschunk.1.js 将被称为 e883ce503b831d4dde09.jsf900ab84da3ad9bd39cc.js。值得一提的是,这些文件的生成通常与制作生产和时间有关更新cacheBust 值。

2。如何包含未知名称的文件?

从现在起您的foo.js - 主文件以未知方式命名。要提取此文件名,您可以使用AssetsPlugin

const AssetsPlugin = require('assets-webpack-plugin');
const assetsPluginInstance = new AssetsPlugin();

并将这个插件添加到webpack.config.js

plugins: [
    assetsPluginInstance
]

webpack-assets.json 文件中,您应该会看到类似

{
    "main": {
        "js": "/e883ce503b831d4dde09.js"
    }
}

您可以使用此文件指向主.js 文件。更多详情请阅读this answer

3。受益时间

我猜如果你因为修改chunk.2.js文件而制作应用程序,你会改变文件路径

- build.js?cacheBust=12345
- chunk.1.js?cacheBust=12345
- chunk.2.js?cacheBust=12345
- chunk.2.js?cacheBust=12345

给新人

- build.js?cacheBust=12346   // modified referation to chunk.2.js file
- chunk.1.js?cacheBust=12346
- chunk.2.js?cacheBust=12346 // modified
- chunk.2.js?cacheBust=12346

如果您使用上述解决方案,您将获得免费缓存确定。现在填充将被称为

(以前的作品)

- e883ce503b831d4dde09.js
- f900ab84da3ad9bd39cc.js
- 5015cc82c7831915903f.js
- 8b6de52a46dd942a63a7.js

(新产品)

- c56322911935a8c9af13.js // modified referation to chunk.2.js file
- f900ab84da3ad9bd39cc.js
- cd2229826373edd7f3bc.js // modified
- 8b6de52a46dd942a63a7.js

现在 main filechunk.2.js 名称被更改,您将通过使用 webpack 方式免费获得。

您可以在此处阅读有关长期缓存的更多信息 https://medium.com/webpack/predictable-long-term-caching-with-webpack-d3eee1d3fa31

【讨论】:

  • 谢谢。虽然我很欣赏“Webpack 方式”的解释,但您实际上并没有回答我的问题。是不是不能让 Webpack 将?cacheBust=12345 附加到它导入的文件中?
  • 它可以追加而不是 chunk.1.js?cacheBust=12345 语法略有不同:chunk.1.12345.js
  • 不幸的是没有:(我试图让文件具有完全相同的URL,从服务器的角度来看,每次,因为只有一个文件服务器端。“缓存破坏令牌” (cacheBust=12345) 需要在 ? 之后,以便客户端将其视为 URL 的一部分(从而破坏缓存),但服务器会忽略它(并且每次只看到实际的文件路径)。
  • 你必须找到插件来修改jsonp webpack loader。我不知道这样做。
  • @Everettss 如何为assets文件夹下的图片添加哈希值?
【解决方案2】:

你可以这样做

output: {
    filename: '[name].js?t=' + new Date().getTime(),
    chunkFilename: '[name]-chunk.js?t=' + new Date().getTime(),
    publicPath: './',
    path: path.resolve(__dirname, 'deploymentPackage')
}

【讨论】:

  • 如何在 html 的脚本 src= 中使用这个文件名?谢谢!
  • @xims,你可以直接引用html,chunk会被命名为0-chunk.js,你只需要引用它,我想知道你为什么要给chunk引用虽然
  • 对不起,我不清楚。目前,html 代码为 。如果我将 webpack 的 output.filename 更改为 app.js?t=123,如何在 html 的 script 标签中使用该动态文件名?
  • 按照@Everettss 的回答,您也可以使用[name]-chunk.js?t=[hash] 模式——这仍然为您提供了一个可读的文件名,并且应该只更改哈希值,如果文件改变了。
  • @xims 的答案实际上与并非总是能够轻松选择使用模板或类似解决方案将 id 注入 html 的 firebase 用户非常相关。 Webpack 只是缓存破坏的一半解决方案。使用日期和 .getTime() 代替内容散列是一个糟糕的建议。
【解决方案3】:

您可以使用 HtmlWebpackPlugin

来自webpack.js.org/plugins/html-webpack-plugin的描述:

... 插件简化了 HTML 文件的创建来为你的 webpack 包提供服务。这对于 在文件名中包含会更改每次编译的哈希值的 webpack 捆绑包特别有用...

我的 webpack.config.js 的一部分:

// ...
const HtmlWebpackPlugin = require('html-webpack-plugin');
// ...
module.exports = {
   // ...
   plugins: [
      new HtmlWebpackPlugin({
         template: './assets/index.html',
         hash: true,
      }),
      // ...
   ]
};

如果 hash: true 则将唯一的 webpack 编译哈希附加到所有包含的脚本和 CSS 文件。这对于缓存无效化很有用。

更多关于 HtmlWebpackPlugin 选项github.com/jantimon/html-webpack-plugin

多亏了这个选项,我得到了输出 html 文件:

<!DOCTYPE html>
<html>
   <head>
      <!-- ... rest of my head code ... -->
      <link href="./css/styles.css?f42fdf96e2f7f678f9da" rel="stylesheet">
   </head>
   <body>
      <!-- ... rest of my body code ... -->
      <script type="text/javascript" src="./js/index.bundle.js?f42fdf96e2f7f678f9da"></script>
   </body>
</html>

我的项目源码:github.com/cichy380/html-starter-bs4-webpack

【讨论】:

  • 这不适用于 v5.3.1。相反,我通过运行npm view html-webpack-plugin@* version 查找最新的 v2,看到 2.30.1 是该主要版本的最新版本,然后运行 ​​npm i html-webpack-plugin@2.30.1 --save-dev --save-exact 以锁定该兼容包。现在像魅力一样工作,谢谢!
【解决方案4】:

如果你想在 Webpack 中使用 name.js?cacheBust=1234 格式的哈希,你可以这样做:

output: {
  filename: '[name].js',
  chunkFilename: '[name].js?cacheBust=[chunkhash]',
},

我正在使用 Laraval Mix 在 Webpack 中做一些非常相似的事情,我在这个 Github 问题中找到了答案:https://github.com/JeffreyWay/laravel-mix/issues/2131

【讨论】:

    【解决方案5】:

    以下是 Webpack v5

    webpack.config.js

    module.exports = {
        // ...
        output: {
            filename: "[name].bundle.[chunkhash].js",
            path: path.resolve(__dirname, "dist"),
            assetModuleFilename: "images/[hash][ext][query]"
        },
        // ...
        optimization: {
            moduleIds: "deterministic",
        }
        // ...
    }
    

    使用哈希很重要,例如[chunkhash]

    注意,方法不止一种。

    来源:https://webpack.js.org/guides/caching/

    【讨论】:

      【解决方案6】:

      有很多方法可以进行缓存清除,也可以使用 webpack。我自己经常使用后缀技术,并来到这篇文章寻找答案。我使用与 OP 不同的块,因为我只引用通过 webpack 运行的 javascript 中的块:

      const componentPromise = import(/* webpackChunkName: "myDelayedSource" */ "path/to/myComponent/myComponent.js");
      

      我找到的缓存清除(在 js 中)的解决方案是简单地更改块的名称:

      const componentPromise = import(/* webpackChunkName: "myDelayedSource_2020-05-14" */ "path/to/myComponent/myComponent.js");
      

      这不会给出文件后缀,但会更改文件名,并且引用该文件的脚本也将使用新的文件名。

      我希望这可以帮助某人。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-15
        • 2022-01-24
        • 1970-01-01
        • 2016-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-17
        相关资源
        最近更新 更多