How to Aggregate, Minimize, Version, and Publish JS & CSS files to S3 with Gulp

Gulp is build system automating tasks, today we will use it to aggregate (concat), minimize, version and finally publish our files to S3 (where you could also use the CloudFront CDN service).

We will keep these tasks independent from each other, and chain them together by specifying dependencies. This works well within the NodeJS module architecture pattern, and leaves the user free to pick and choose the tasks they'd like to make use of.

Setup: Install/include the gulp packages we will need.

npm i gulp-version-filename --save-dev && npm i gulp-concat --save-dev && npm i gulp-minify-css --save-dev && npm i gulp-s3-ls --save-dev && npm i gulp-uglify --save-dev

gulpfile.js

const gulp = require('gulp')
const concat = require('gulp-concat')
const minCss = require('gulp-minify-css')
const uglify = require('gulp-uglify')
const filever = require('gulp-version-filename')
const s3 = require('gulp-s3-ls')

1. Aggregating Files (concat-ing) Task

Aggregate the javascript or stylesheet files with gulp-concat, you can see all the available plug-in options on the gulp-concat github repo.

/**
 * 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([
      'src/css/open-sans.css',
      'src/css/bootstrap.css',
      'src/css/my-custom-theme.css'
      ])
    .pipe(concat('common.css'))
    .pipe(gulp.dest('dist/css/'));;
});

2. Minimizing Task

Note: Adding the "concat" task here as a dependency is what will allow us to issue a single pipeline command to run all the tasks.

gulp-minify-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('/dist/common.css')
    .pipe(minCss({
        compatibility: 'ie8',
        keepSpecialComments: 1,
      }))
    .pipe(gulp.dest('dist/css/'))
})

gulp-uglify

/**
 * Minify the JS files.
 *
 * We need to preserve comments to allow for versioning later
 */
gulp.task('minJS', ['concat'], function() {
  return gulp.src('src/js/*.js')
    .pipe(uglify({
        preserveComments: 'some',
      }))
    .pipe(gulp.dest('dist/js'))
})

3. Versioning Task

This will take the version name specified within our files in @version ABC.123 and add it to our filenames common-ABC.123.css.

gulp-version-filename

/**
 * 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(['dist/css/*.css', 'dist/js/*.js'])
    .pipe(filever({
      silent: true,
    }))
    .pipe(gulp.dest('dist'))
})

4. Publish Task

Takes our productionized files and publishes them to S3 for inclusion in our web pages.

AWS Credentials: You will need to setup your AWS security crednetials to be able to publish files to your S3 account, you can see the various ways Amazon allows to include your credentials.

gulp.task('publish', ['version'], function() {
  const aws = require("./.aws.json"); // Credentials
  let options = {
    headers: {
      'x-amz-acl': 'public-read',
      'Cache-Control': 'max-age=315360000, no-transform, public'
    },
    uploadPath: '/web-apps/assets/css/',
  };

  return gulp.src(['dist/css/*.js', 'dist/js/*.js'])
    .pipe(s3(aws, options));
})

All done! To execute our entire pipeline, execute the final task (in our case gulp publish), or run everything except the S3 publishing with gulp version

Here is the entire file together

gulpfile.js

const gulp = require('gulp')
const concat = require('gulp-concat')
const minCss = require('gulp-minify-css')
const uglify = require('gulp-uglify')
const filever = require('gulp-version-filename')
const 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([
      'src/css/open-sans.css',
      'src/css/bootstrap.css',
      'src/css/my-custom-theme.css',
      ])
    .pipe(concat('common.css'))
    .pipe(gulp.dest('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('/dist/common.css')
    .pipe(minCss({
        compatibility: 'ie8',
        keepSpecialComments: 1,
      }))
    .pipe(gulp.dest('dist/css/'))
})

/**
 * Minify the JS files.
 *
 * We need to preserve comments to allow for versioning later
 */
gulp.task('minJS', ['concat'], function() {
  return gulp.src('src/js/*.js')
    .pipe(uglify({
        preserveComments: 'some',
      }))
    .pipe(gulp.dest('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(['dist/css/*.css', 'dist/js/*.js'])
    .pipe(filever({
      silent: true,
    }))
    .pipe(gulp.dest('dist'))
})

gulp.task('publish', ['version'], function() {
  const aws = require("./.aws.json"); // Credentials
  let options = {
    headers: {
      'x-amz-acl': 'public-read',
      'Cache-Control': 'max-age=315360000, no-transform, public',
    },
    uploadPath: '/web-apps/assets/css/',
  };

  return gulp.src(['dist/css/*.js', 'dist/js/*.js'])
    .pipe(s3(aws, options))
})

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

Small dog web development studio

View All Our Posts

Web application developers in western Washington, creating user centric web solutions for businesses of all shapes and sizes.

Our projects include ecommerce, event organization, user driven web applications and more.


Small Dog Studios, LLC. Small Dog Studios News