Uploading static assets to S3 with Heroku


#1

Has anyone found a good solution for automatically uploading the static assets (i.e. what’s in the build directory) to Amazon S3 in an automated way after they are compiled, and then retrieving them from the app? I’m using Heroku too, for what that’s worth. Thanks!


#2

I figured out how to do this by following this blog post, with a few modifications. https://blog.smalldo.gs/2015/08/how-to-aggregate-minimize-version-and-publish-js-css-files-to-s3-with-gulp/

I also updated the link to those assets within my index.html file.

In package.json

"scripts": {
    "postinstall": "gulp build && gulp publish && gulp publishFonts",
    "start": "node server.js"
  },

In gulpfile

/**
 * Code for minifying js and css files, and uploading to S3
 */
var gulp = require('gulp');
var concat = require('gulp-concat');
var minCss = require('gulp-minify-css');
var uglify = require('gulp-uglify');
var filever = require('gulp-version-filename');
var s3 = require("gulp-s3-ls");
 
/**
 * Aggregate the files.
 *
 * Note that these files are explicitly defined instead of fetching all files
 * from the dir because the concat order of CSS files matter, by definition.
 */
gulp.task('concat', function() {
  return gulp.src([
      'www/build/css/open-sans.css',
      'www/build/css/bootstrap.css',
      'www/build/css/my-custom-theme.css'
      ])
    .pipe(concat('common.css'))
    .pipe(gulp.dest('www/dist/css/'));;
});
 
/**
 * Minify the CSS files.
 *
 * Remove spacing, comments, and unneeded formatting for the smallest possible filesize to serve. Keeps the
 * first special comment (as denoted by "/*!" opening comment delimiter), so we can use it for versioning.
 */
gulp.task('minCSS', ['concat'], function() {    
  return gulp.src('www/build/css/*.css')
    .pipe(minCss({
        compatibility: 'ie8',
        keepSpecialComments: 1
      }))
    .pipe(gulp.dest('www/dist/css/'));;
});
 
/**
 * Minify the JS files.
 *
 * We need to preserve comments to allow for versioning later
 */
gulp.task('minJS', ['concat'], function() {
  return gulp.src('www/build/js/*.js')
    .pipe(uglify({
        preserveComments: 'some'
      }))
    .pipe(gulp.dest('www/dist/js'));
});
 
/**
 * Version the files.
 *
 * Takes the version number specified in the files and adds it to the filename. The `silent` option suppresses
 * errors from files if no version is found within the file.
 */
gulp.task('version', ['minCSS', 'minJS'],function() {
  return gulp.src(['www/dist/css/*.css', 'www/dist/js/*.js'])
    .pipe(filever({
      silent: true
    }))
    .pipe(gulp.dest('www/dist/versioned'));
});
 
gulp.task('publish', ['version'], function() {
  var aws = require("./.aws.json"); // Credentials
  var options = {
    headers: {
      'x-amz-acl': 'public-read',
      'Cache-Control': 'max-age=315360000, no-transform, public'
    },
    uploadPath: 'assets/'
  };
 
  return gulp.src(['www/dist/versioned/*.css', 'www/dist/versioned/*.js'])
    .pipe(s3(aws, options));
});
 
gulp.task('publishFonts', [], function() {
  var aws = require("./.aws.json"); // Credentials
  var options = {
    headers: {
      'x-amz-acl': 'public-read',
      'Cache-Control': 'max-age=315360000, no-transform, public'
    },
    uploadPath: 'fonts/'
  };
 
  return gulp.src(['www/build/fonts/*.ttf', 'www/build/fonts/*.woff', 'www/build/fonts/*.woff2'])
    .pipe(s3(aws, options));
});

// Execute by running `gulp publish`, or run everything except the S3 publishing with `gulp version`