Search code examples
node.jsexpressamazon-s3gruntjsamazon-cloudfront

Grunt module(s) to upload all static assets to S3 / CloudFront, replace paths, and invalidate old assets


Using Grunt, NodeJs and Express, what module(s) should I use to:

  1. Discover all static assets (frontend JS, CSS, images) in the app, either by looking at an asset directory or parsing through the codebase

  2. Upload assets to Amazon S3 / CloudFront, renaming each file with a unique "fingerprinted" name

  3. Replace each asset's path in the codebase with the CloudFront URL

  4. Invalidate old CDN assets

This is my first time using CloudFront. I am not sure if all of the above can be accomplished with Grunt, or whether it is best accomplished as a Node/Express module.

With Rails, I've read it's as easy as:

# Setup amazon CDN
config.action_controller.asset_host = "xxxxxxxxxxxxx.cloudfront.net"

and I'm looking for a similar solution for a Node stack.


Solution

  • Invalidating CDN assets is a Bad Idea ®. In CloudFront, it may take up to 15 minutes to complete - that would be adding 15 minutes to your deploy. Also, some browsers may hold old files because the URL is the same.

    Instead, you should probably version you static assets and publish new versions under different version names.

    For example:

    my-app/1.2.3/main.js
    my-app/1.2.4/main.js
    

    So on, and so forth.

    This gives you two advantages:

    • You can cache forever, confidently. The same URL will always serve the same file.
    • You can rollback quickly in case of a disaster deploy. Old files are where they were.

    For deploying to S3, there are specific plugins for that. I, however, prefer to simply use grunt-shell in tandem with the official Amazon AWS CLI

    Configuring it would look something like this:

    shell: {
      cp: {
        command: "aws s3 cp --recursive dist/ s3://my-bucket/my-app/"
      }
    }
    

    You can use grunt to read a version variable from somewhere and automatically put all files inside the dist/{version}/ folder, while replacing any paths in your html to the correct version path.