24

So I have hosted my angular app on s3 with a cloudfront dist. I do file revision-ing (using grunt filerev) to make sure that I never get stale content. But, how should I version the index.html file. Its required because all other files are referenced inside index.html.

I have configured my bucket to be used as a static site. So it just picks up the index.html when I reference the bucket in url.

Cloudfront says that you should set min TTL to 0, so it would always hit origin to serve the content. But, I don't need this since I am doing file revisioning of all my files (except index.html). I can take advantage of cdn caching for these files.

They also say that in order to invalidate a single object, set the max-age headers to 0. I tried adding following to my index.html

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

But this does not reflect once you upload on s3. Do I need to explicitly set headers on s3 using s3cmd or dashboard? And do I need to do this every time when index.html changes and I upload it?

I am aware that I could invalidate a single file using cmd but its a repeating process and It would be great if it can take care of itself just by deploying on s3.

Nirav Gandhi
  • 1,945
  • 1
  • 23
  • 32
  • Related: [How to purge CloudFront's cache](https://webapps.stackexchange.com/q/12526/22759). – kenorb Oct 09 '17 at 14:20

6 Answers6

28

Although the accepted answer is correct if you are using s3cmd, I was using the AWS CLI, so what I did was the following 2 commands:

First, to actually deploy the code:

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

Then, to create an invalidation on CloudFront:

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

Jordan
  • 31,971
  • 6
  • 56
  • 67
  • Thanks @Jordan. I am trying this but not getting desired result. `aws cloudfront create-invalidation --distribution-id ${CLOUDFRONT_ID} --paths '/index.html'`. any other idea? – Lal Jul 26 '18 at 14:03
  • I would check your cloudfront distribution logs to see if the invalidation was triggered, and make sure that the path is correctly displayed there. – Jordan Jul 27 '18 at 15:16
  • invalidation details from cloudfront distribution shows this alongside other details `objects path /index.html /service-worker.js`. i am deploying react app with service worker enabled – Lal Aug 04 '18 at 09:18
  • if i invalidate `--paths /*`, log shows this `object paths /lib /tmp /srv /root /media /opt /mnt /etc /usr /dev /var /sbin /proc /bin /run /sys /home /boot /lib64` – Lal Aug 04 '18 at 09:43
  • you should use `--paths "/*"` – WisdomPill Jan 21 '19 at 09:45
  • 1
    There's no need to invalidate the entire bucket just to invalidate index.html. – Jordan Jan 22 '19 at 12:07
7

Answering my own question. I deploy my site to S3 using s3cmd tool and there is an option you could provide to invalidate CloudFront cache of all the files changed (diff between your dist folder and S3 bucket). This invalidates cache of all the files changed including index file. It usually takes around 15-20 mins to reflect the new changes on production.

Here is the command

s3cmd sync --acl-public --reduced-redundancy --delete-removed --cf-invalidate [your-distribution-folder]/* s3://[your-s3-bucket]

Note: On macOS, you can install this tool via: brew install s3cmd.

Hope this helps.

Nirav Gandhi
  • 1,945
  • 1
  • 23
  • 32
  • What do you have to specify in `[your-distribution-folder]/*`? Is that the same as the **CloudFront Distributions ID**?**Domain Name**? Or **ARN**? These are the fields I see (http://i.imgur.com/8IEEYmS.jpg), but I've tried a bunch and it keeps giving me `ERROR: Parameter problem: Invalid source: 'WHATEVER_I_TRIED' is not an existing file or directory` (on Windows if that matters). – chamberlainpi Jun 05 '17 at 19:19
  • Also is the `/*` required? Does it signify that everything in the distribution / bucket gets invalidated? – chamberlainpi Jun 05 '17 at 19:19
  • It should be the name of the bucket/folder you've configured as the root of the website. – Nirav Gandhi Jun 06 '17 at 04:59
  • And no. It doesn't invalidate everything. It checks for the difference in files using sync command and only invalidates files that have changed. – Nirav Gandhi Jun 06 '17 at 05:01
6

I have had the same problem with my static website hosted on S3 and distributed with CloudFront. In my case invalidating /index.html didn't work.

I talked with AWS support and what I needed to do was to invalidate with only /. This is due I am accessing my website with https://website.com/ URL and not with https://website.com/index.html (which would have brought the updated content with the /index.html invalidation). This was done in AWS CloudFront console and not with the AWS CLI.

Dharman
  • 30,962
  • 25
  • 85
  • 135
lucianov88
  • 185
  • 3
  • 10
3

You can automate a process using Lambda. It allows you to create a function that will perform certain actions (Object invalidation in your case) in response to certain events (new file in S3).

More information here: https://aws.amazon.com/documentation/lambda/

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
Vladimir Mukhin
  • 577
  • 2
  • 7
  • After manually invalidation of the /index.html I get the previous version of my application. Are you able to get this working? – erwineberhard May 17 '16 at 19:12
  • Here's a Gist that helped me set this up quickly: https://gist.github.com/supinf/e66fd36f9228a8701706 (I'm not the creator so can't really help if it doesn't work out of the box!) – chamberlainpi Jun 05 '17 at 21:20
1

When you sync local directory with s3, you can do this:

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

The first command is just a normal sync, the second command enable S3 to return cache-control for all the files except index.html and robots.txt.

Then your SPA can be fully cached (except index.html).

Ming
  • 4,110
  • 1
  • 29
  • 33
0

If you use s3cmd sync and utilize the --cf-invalidate option, you may have to also specify --cf-invalidate-default-index depending on your setup.

From the man page:

When using Custom Origin and S3 static website, invalidate the default index file.

This will ensure to also invalidate your index document, most likely index.html, which will otherwise be skipped regardless if updated or not through the sync.