对于使用cloudfront在S3上托管的静态站点,如何使index.html的缓存无效?

时间:2016-02-16 08:36:20

标签: html amazon-web-services amazon-s3 cdn amazon-cloudfront

所以我在s3上使用cloudfront dist托管了我的角度应用程序。我做文件修改(使用grunt filerev)以确保我永远不会得到陈旧的内容。但是,我应该如何对index.html文件进行版本控制。它是必需的,因为所有其他文件都在index.html中引用。

我已将我的存储桶配置为静态网站。因此,当我在url中引用存储桶时,它就会选择index.html。

Cloudfront说你应该将min TTL设置为0,因此它总是会命中原点来提供内容。但是,我不需要这个,因为我正在对我的所有文件进行文件修订(index.html除外)。我可以利用cdn缓存这些文件。

他们还说,为了使单个对象无效,请将max-age标头设置为0.我尝试将以下内容添加到我的index.html

<meta http-equiv="Cache-Control" content="public, must-revalidate, proxy-revalidate, max-age=0"/>

但是一旦你在s3上传,这并不能反映出来。我是否需要使用s3cmd或仪表板在s3上显式设置标头?每当index.html更改并上传它时,我是否需要这样做?

我知道我可以使用cmd使单个文件无效,但它是一个重复的过程,如果它只是通过在s3上部署就可以自行解决它。

6 个答案:

答案 0 :(得分:17)

虽然如果你使用的是s3cmd,但是接受的答案是正确的,我使用的是AWS CLI,所以我所做的就是以下两个命令:

首先,要实际部署代码:

aws s3 sync ./ s3://bucket-name-here/ --delete

然后,在CloudFront上创建失效:

aws cloudfront create-invalidation --distribution-id <distribution-id> --paths /index.html

答案 1 :(得分:6)

回答我自己的问题。我使用s3cmd tool将我的站点部署到S3,并且您可以提供一个选项,以使所有已更改文件(在您的s3cmd sync --acl-public --reduced-redundancy --delete-removed --cf-invalidate [your-distribution-folder]/* s3://[your-s3-bucket] 文件夹和S3存储桶之间的差异)的CloudFront缓存无效。这会使更改的所有文件的缓存无效,包括索引文件。通常需要大约15-20分钟来反映生产中的新变化。

这是命令

brew install s3cmd

注意:在macOS上,您可以通过以下方式安装此工具:stores->configuration ->catalog->inventory ->Productstockoptions ->outofstockthreshold->set this value as 0.

希望这有帮助。

答案 2 :(得分:2)

您可以使用Lambda自动执行流程。它允许您创建一个函数,该函数将执行某些操作(在您的情况下为对象失效)以响应某些事件(S3中的新文件)。

更多信息: https://aws.amazon.com/documentation/lambda/

答案 3 :(得分:1)

将本地目录与s3同步时,可以执行以下操作:

<!DOCTYPE html>
<html>

<head>
  <title>Speech Recognition Recording</title>
</head>

<body>
  <input type="button" value="Stop speech command recognition" id="stop">
  <script>
    navigator.mediaDevices.getUserMedia({
        audio: true
      })
      .then(stream => {
        const recorder = new MediaRecorder(stream);
        const recognition = new webkitSpeechRecognition();
        const synthesis = new SpeechSynthesisUtterance();
        const handleResult = e => {
          recognition.onresult = null;
          console.log(e.results);
          const result = e.results[e.results.length - 1];

          if (result.isFinal) {
            const [{transcript}] = result;
            console.log(transcript);
            synthesis.text = transcript;
            window.speechSynthesis.speak(synthesis);
          }
        }
        synthesis.onstart = () => {
          if (recorder.state === "inactive") {
            recorder.start()
          } else {
            if (recorder.state === "paused") {
              recorder.resume();
            }
          }
        }
        synthesis.onend = () => {
          recorder.pause();
          recorder.requestData();
        }
        recorder.ondataavailable = async(e) => {
          if (stream.active) {
            try {
              const blobURL = URL.createObjectURL(e.data);
              const request = await fetch(blobURL);
              const ab = await request.arrayBuffer();
              console.log(blobURL, ab);
              recognition.onresult = handleResult;
              // URL.revokeObjectURL(blobURL);
            } catch (err) {
              throw err
            }
          }
        }
        recorder.onpause = e => {
          console.log("recorder " + recorder.state);
        }
        recognition.continuous = true;
        recognition.interimResults = false;
        recognition.maxAlternatives = 1;
        recognition.start();
        recognition.onend = e => {
          console.log("recognition ended, stream.active", stream.active);

          if (stream.active) {
            console.log(e);
            // the service disconnects after a period of time
            recognition.start();
          }
        }
        recognition.onresult = handleResult;

        stream.oninactive = () => {
          console.log("stream ended");
        }

        document.getElementById("stop")
          .onclick = () => {
            console.log("stream.active:", stream.active);
            if (stream && stream.active && recognition) {
              recognition.abort();
              recorder.stop();
              for (let track of stream.getTracks()) {
                track.stop();
              }
              console.log("stream.active:", stream.active);
            }
          }

      })
      .catch(err => {
        console.error(err)
      });
  </script>
</body>

</html>

第一个命令只是正常同步,第二个命令启用S3以返回除aws s3 sync ./dist/ s3://your-bucket --delete aws s3 cp \ s3://your-bucket s3://your-bucket \ --exclude 'index.html' --exclude 'robots.txt' \ --cache-control 'max-age=604800' \ --metadata-directive REPLACE --acl public-read \ --recursive index.html以外的所有文件的缓存控制。

然后您的SPA可以完全缓存(robots.txt除外)。

答案 4 :(得分:0)

如果您使用s3cmd sync并使用--cf-invalidate选项,则可能还需要指定--cf-invalidate-default-index,具体取决于您的设置。

从手册页:

  

使用Custom Origin和S3静态网站时,无效的默认索引文件。

这将确保您的索引文档(很可能是index.html)无效,否则无论是否通过同步更新,都将跳过该文档。

答案 5 :(得分:0)

我在 S3 上托管并通过 CloudFront 分发的静态网站遇到了同样的问题。就我而言,使 /index.html 无效。

我与 AWS 支持人员进行了交谈,我需要做的是仅使用 / 使无效。这是因为我使用 https://website.com/ URL 而不是 https://website.com/index.html 访问我的网站(这会带来带有 {{1 }} 失效)。这是在 AWS CloudFront 控制台中完成的,而不是通过 AWS CLI 完成的。