Code Monkey home page Code Monkey logo

gulp-cloudfront's Introduction

gulp-cloudfront Build Status

Updates the Default Root Object of a CloudFront distribution

Purpose

Content distribution networks like CloudFront let you cache static assets in Edge Locations for extended periods of time. A problem occurs however when you go to release a new version of your website, you will have to explictly tell CloudFront to expire each file or you will have to wait for the TTL to expire. In the case of CloudFront, you will need to invalidate items or wait for the cache TTL to expire before vistors of your website will see the vew version.

A solution to this problem is adding a revisioned suffix to the filename for each static asset. The gulp plugin gulp-rev-all can assist in this process. eg. unicorn.css => unicorn-098f6bcd.css You can then use gulp-s3 to upload the revisioned files to a S3 bucket which CloudFront points to.

Finally gulp-cloudfront comes in during the final step, to update a CloudFront distributions' Default Root Object to the latest revisioned index.html.
Updating the Default Root Object only takes 5-10 minutes and all new visitors to your website will no longer see the old cached content. A much better solution than waiting for cached items to expire or invalidating individual files which costs $$.

You can in essence host multiple versions of your website under the same static host and if you need to revert to an older version you need only change the index.html file.

Under the Hood

This plugin will identify the index.html file based on the default or configured pattern. Once identified it will update the CloudFront distribution to the new index file.

Install

Install with npm

npm install --save-dev gulp-cloudfront

Example

var gulp = require('gulp');
var revall = require('gulp-rev-all');
var awspublish = require('gulp-awspublish');
var cloudfront = require("gulp-cloudfront");

var aws = {
    "key": "AKIAI3Z7CUAFHG53DMJA",
    "secret": "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",
    "bucket": "bucket-name",
    "region": "us-standard",
    "distributionId": "E1SYAKGEMSK3OD"
};

var publisher = awspublish.create(aws);
var headers = {'Cache-Control': 'max-age=315360000, no-transform, public'};

gulp.task('default', function () {
    gulp.src('dist/**')
        .pipe(revall())
        .pipe(awspublish.gzip())
        .pipe(publisher.publish(headers))
        .pipe(publisher.cache())
        .pipe(awspublish.reporter())
        .pipe(cloudfront(aws));
});

API

options.patternIndex

Type: Regular Expression Default: /^\/index\.[a-f0-9]{8}\.html(\.gz)*$/gi

Specify the pattern used to match the default root object

var aws = {
    ..,
    "patternIndex": /^\/root\-[a-f0-9]{4}\.html(\.gz)*$/gi
};

License

MIT © Joshua Bellamy-Henn

gulp-cloudfront's People

Contributors

niftylettuce avatar nitaigao avatar remie avatar steadicat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

gulp-cloudfront's Issues

Index.html reference not getting updated

My index file did get it's name updated: index.2e6ac32e.html

But the references inside are incorrect.

I see that the references in my css files did get updated correctly.

I see that the references in my js files got updated correctly

I see that the files that are in the revall ignore rule don't get the links/resources updated, I don't want the name changed but I want the references ok :).

Bug: Cannot call method 'substr' of undefined

Sometimes when an object is deleted I get an error:

[13:26:07] [delete] bundle.3557797d.js

events.js:72
        throw er; // Unhandled 'error' event
              ^
TypeError: Cannot call method 'substr' of undefined
    at Transform._transform (/Users/me/Work/project/web/client/node_modules/gulp-cloudfront/index.js:21:34)

Gulp task:

gulp.task('deploy', function() {
  var publisher = awspublish.create(aws);
  var headers = {
     'Cache-Control': 'max-age=315360000, no-transform, public'
  };
  return gulp.src('./dist/**')
    .pipe(awspublish.gzip())
    .pipe(revall())
    .pipe(publisher.publish(headers))
    .pipe(publisher.sync())
    .pipe(publisher.cache())
    .pipe(awspublish.reporter())
    .pipe(cloudfront(aws));
});

Does this work with multiple index files?

Thanks for gulp-cloudfront, definitely solves a problem I had in a unique way. Does it support multiple index file in multiple directories? I have an index in root and an index in /app but I am getting this output.

....
[10:01:21] gulp-cloudfront: DefaultRootObject updated to [index.d474d950.html].
[10:01:21] gulp-cloudfront: Identified index [ /app/index.6a5485a0.html ]
[10:01:23] gulp-cloudfront: DefaultRootObject updated to [app/index.6a5485a0.html].
[10:01:23] Finished 'deploy' after 6.93 s

Which obviously doesn't work for root since the default root object is different signature for both. I believe the problem is that the 2nd index is not identified until after first DefaultRootObject is updated.

Thanks in advance.

Error: `Message: Cannot read property 'Bucket' of undefined`

Message:
    Cannot read property 'Bucket' of undefined

I'm getting this error message on execute.

const
  gulp = require( "gulp" ),
  awsPublish = require( "gulp-awspublish" ),                                   
  cloudfront = require( "gulp-cloudfront" ),
  aws = {
    key:"",
    secret: "",
    distributionId: "",
    bucket: "",
    region:""
  },
  envFlag = "dev";

gulp.task( "toS3:dev", () => {
  const publisher = awsPublish.create( aws );
  return gulp.src( "./src/dist/**" )             
    .pipe( awsPublish.gzip() )
    .pipe( publisher.publish( {
      "x-amz-acl": "public-read",
      "Cache-Control": ( envFlag === "prod" ? "max-age=3600" : "max-age=120" )
    }))              
    .pipe( publisher.cache() )
    .pipe( awsPublish.reporter() )
    .pipe( cloudfront( aws ) );
});

Change default pattern to use "-" hyphen

I figured I'd file an issue to see if it was OK with you before I submitted a PR.

-options.patternIndex = options.patternIndex || /^\/index\.[a-f0-9]{8}\.html(\.gz)*$/gi;
+options.patternIndex = options.patternIndex || /^\/index\-[a-f0-9]{8}\.html(\.gz)*$/gi;

I suggest this considering that gulp-rev and gulp-rev-all by default out of the box use this approach.

Recommendation for deleting old files on s3?

I've got gulp-cloudfront working correctly, however, I'm wondering what the best way to remove the old files on s3 is, since every time I push code, I know have multiple copies of all the same files.

I'm using gulp-s3-ls, not gulp-awspublish (because gulp-awspublish wasn't working for buckets with periods in the name...)

Any suggestions?

IMPORTANT! Outdated AWS SDK exposes issue with sSLSupportMethod being set to 'VIP'

Starting mid-October 2018 there is a confirmed issue with the AWS API when used in combination with older SDK versions (before at least 2015-09-17). This issue causes the CloudFront distribution that is updated using the UpdateDistribution to switch the supported SSL method from 'SNI only' to 'Virtual IP', regardless of the request parameters.

As shown in this CloudTrail Event:

{
    "eventVersion": "1.03",
    ...
    "eventSource": "cloudfront.amazonaws.com",
    "eventName": "UpdateDistribution",
    ...
    "userAgent": "aws-sdk-nodejs/2.0.31 linux/v6.8.1",
    "requestParameters": {
        "distributionConfig": {
            ...
            "viewerCertificate": {
                "sSLSupportMethod": "sni-only",
                "minimumProtocolVersion": "TLSv1"
            },
            ...
        }
    },
    "responseElements": {
        ...
        "distribution": {
            "distributionConfig": {
                ...
                "viewerCertificate": {
                    "sSLSupportMethod": "vip",
                    "minimumProtocolVersion": "TLSv1"
                },
                ...
            }
        }
    },
    ...
    "eventType": "AwsApiCall",
    "apiVersion": "2014_10_21",
    ...
}

the distribution request does have the correct value of the sSLSupportMethod, but the response from the API says it was changed to VIP. This will incur additional costs up to $600,-- USD per distribution per month.

The only way to avoid this issue is to update to the latest version of the SDK. Amazon Web Services is aware of the issue and has created an internal request to stop support for older SDK, which will eventually break this package.

Does not correctly match paths on windows systems.

On windows systems the options.dirRoot is not correctly resolved. file.base seems to use backslashes while file.path uses forward slash.

It seems the line:

options.dirRoot = options.dirRoot || file.base.replace(/\/$/, "");

Should be using:

options.dirRoot = options.dirRoot || file.base.replace(/[\/|\\]$/, "");

for it to run on windows.

Missing required key \'OriginAccessIdentity\'

Whenever I try to run gulp-cloudfront I receive the following error

  plugin: 'gulp-cloudfront',
  showStack: false,
  name: 'MissingRequiredParameter',
  message: 'Missing required key \'OriginAccessIdentity\' in params.DistributionConfig.Origins.Items[0].S3OriginConfig',
  stack: 'Error: Missing required key \'OriginAccessIdentity\' in params.DistributionConfig.Origins.Items[0].S3OriginConfig\n    at fail (/Users/andrewnarkewicz/Development/docs-attribution/node_modules/gulp-cloudfront/node_modules/aws-sdk/lib/param_validator.js:99:26)\n    at validateStructure (/Users/andrewnarkewicz/Development/docs-attribution/node_modules/gulp-cloudfront/node_modules/aws-sdk/lib/param_validator.js:18:14)\n    at validateMember (/Users/andrewnarkewicz/Development/docs-attribution/node_modules/gulp-cloudfront/node_modules/aws-sdk/lib/param_validator.js:45:21)\n    at validateStructure (/Users/andrewnarkewicz/Development/docs-attribution/node_modules/gulp-cloudfront/node_modules/aws-sdk/lib/param_validator.js:32:14)\n    at validateMember (/Users/andrewnarkewicz/Development/docs-attribution/node_modules/gulp-cloudfront/node_modules/aws-sdk/lib/param_validator.js:45:21)\n    at validateList (/Users/andrewnarkewicz/Development/docs-attribution/node_modules/gulp-cloudfront/node_modules/aws-sdk/lib/param_validator.js:60:12)\n    at validateMember (/Users/andrewnarkewicz/Development/docs-attribution/node_modules/gulp-cloudfront/node_modules/aws-sdk/lib/param_validator.js:47:21)\n    at validateStructure (/Users/andrewnarkewicz/Development/docs-attribution/node_modules/gulp-cloudfront/node_modules/aws-sdk/lib/param_validator.js:32:14)\n    at validateMember (/Users/andrewnarkewicz/Development/docs-attribution/node_modules/gulp-cloudfront/node_modules/aws-sdk/lib/param_validator.js:45:21)\n    at validateStructure (/Users/andrewnarkewicz/Development/docs-attribution/node_modules/gulp-cloudfront/node_modules/aws-sdk/lib/param_validator.js:32:14)' }

Removed files, now what?

Hey guys,

So I removed my files to try to upload it again to s3 using gulp-cloudfront, and now I'm busted.

I tried it a couple of times and it always says that my files are "cached" or "found". How do I clear all of it out and upload everything again in my bucket? I tried creating a new bucket, new cloudfront and it seems that the caching or mapping is somewhere in my PC.

Best Regards,

Failures are not reported correctly

I am using this on a build server and this task always returns a successful status code, even when it has failed.

I believe the issue is that the task does not pass the error to the callback on failure

tool.updateDefaultRootObject(filename)
                .then(function() {
                    return callback(null, file);
                }, function(err) {
                    gutil.log(new gutil.PluginError('gulp-cloudfront', err));
                    callback(null, file); // Pass the error to the callback

                });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.