Asset management with Gulp best practice/workflow?

Hi Guys,

I’m wondering about asset management best practice or workflow with Gulp. I have read some (or quite many) articles but since Gulp is pretty much unopinionated tool IMO, every developer seems to have their own workflow! :sweat_smile:

What I’m looking for is a complete workflow for managing all assets which can come from bower, then maybe our own packages as a group of css, js, images, and individual css, js and also sometimes I need to use another asset’s LESS file to be used in mine eg. a bootstrap theme need to inherit the bootstrap global config, and the bootstrap itself was installed using bower, and last but not least, how we manage environment between development and production, where in the latter we need to minify, combine and versioning assets, also some are using CDN. See, that’s quite a lot to do!

So, how do you handle it or have you seen an article or tutorial or anything that explains the best practice/workflow to do all those things properly?

Thanks!

Hey explor,

Yes, it’s complicated.
One tool that sounds like it could be a good fit for you is Webpack, it’s a powerful module bundler that can handle all assets types like css, js images, you can make multiple bundles.

The way these are typically set up is that you compile separate files whenever your assets change in development, and for production you compile them into minified bundles as part of the deploy.

I don’t have a specific tutorial in mind for you to follow but can suggest the Webpack docs as a great starting point.

Hi Mark,

Thanks for your reply, I appreciate it.

Yeah, I’ve heard about Webpack, but I heard it’s more complex than Gulp too, yeah maybe for more features. But actually, my site is not really complicated I think, it’s not even a fully SPA. Here is the directory structure for the assets, just if it can help figuring out:

-- public
-- -- css
-- -- js

-- resources
-- -- assets
-- -- -- css
-- -- -- js
-- -- packages
-- -- -- theme
-- -- -- -- less
-- -- -- -- images
-- -- -- -- js
-- -- bower_components
-- -- -- bootstrap
-- -- -- -- dist
-- -- -- -- less

Just curious, is it too complex to be handled with Gulp? and is it really easier with Webpack?

EDIT:
One of my issues is, let’s say I have several CSS files (my own CSS), then in development should I keep it separated (to make it easy if I need to see the CSS) or I can just merge those files as one? Can source-map help in this case? Is it the same case for JS files?

Sorry for a lot of questions, I’m really lost here :dizzy_face:

Good questions :slight_smile:

It’s not too complex for Gulp but yes I think there will be less custom code required with Webpack.

With Gulp you’ll need separate tasks for each asset type, and separate tasks for compiling locally as well as production, here’s an example of a gulpfile.js that I’ve used. You’re not using the same tools but the idea is the same.

var gulp = require('gulp');
var gutil = require('gulp-util');
var sass = require('gulp-sass');
var coffee = require('gulp-coffee');
var uglifyJS = require('gulp-uglify');
var minifyCSS = require('gulp-minify-css');
var autoprefix = require('gulp-autoprefixer');
var template = require('gulp-template-compile');
var include = require('gulp-include');
var rename = require('gulp-rename');

var paths = {
  coffee: {
    src:  'assets/scripts/**/*.coffee',
    dest: 'static/v3/javascripts'
  },
  js: {
    src:  'assets/scripts/**/*.js',
    dest: 'static/v3/javascripts'
  },
  styles: {
    src:  'assets/scss/**/*.scss',
    dest: 'static/v3/stylesheets'
  },
  templates: {
    src:  'assets/templates/**/*.html',
    dest: 'static/v3/templates'
  }
};

gulp.task('coffee', function() {
  return gulp.src(paths.coffee.src)
    .pipe(include())
    .pipe(coffee())
    .on('error', gutil.log)
    .on('error', gutil.beep)
    .pipe(gulp.dest(paths.coffee.dest));
});

gulp.task('js', function() {
  return gulp.src(paths.js.src)
    .pipe(include())
    .pipe(gulp.dest(paths.js.dest));
});

gulp.task('coffee_compile', function() {
  return gulp.src(paths.coffee.src)
    .pipe(include())
    .pipe(coffee())
    .pipe(uglifyJS())
    .pipe(gulp.dest(paths.coffee.dest));
});

gulp.task('js_compile', function() {
  return gulp.src(paths.js.src)
    .pipe(include())
    .pipe(uglifyJS())
    .pipe(gulp.dest(paths.js.dest));
});

gulp.task('templates', function() {
  return gulp.src(paths.templates.src)
    .pipe(template({
      name: function(file) {
        return file.relative.replace('.html', '');
      },
      templateSettings: {
        variable: 'data'
      }
    }))
    .pipe(gulp.dest(paths.templates.dest));
});
gulp.task('templates_compile', function() {
  return gulp.src(paths.templates.src)
    .pipe(template({
      name: function(file) {
        return file.relative.replace('.html', '');
      },
      templateSettings: {
        variable: 'data'
      }
    }))
    .pipe(uglifyJS())
    .pipe(gulp.dest(paths.templates.dest));
});

gulp.task('styles', function() {
  return gulp.src(paths.styles.src)
    .pipe(sass({errLogToConsole: true}))
    .pipe(autoprefix(['last 2 versions', "ie 8"]))
    .pipe(gulp.dest(paths.styles.dest));
});

gulp.task('styles_compile', function() {
  return gulp.src(paths.styles.src)
    .pipe(sass({errLogToConsole: true}))
    .pipe(autoprefix(['last 2 versions', "ie 8"]))
    .pipe(minifyCSS())
    .pipe(gulp.dest(paths.styles.dest));
});

gulp.task('watch', function() {
  gulp.watch(paths.coffee.src, ['coffee']);
  gulp.watch(paths.js.src, ['js']);
  gulp.watch(paths.styles.src, ['styles']);
  gulp.watch(paths.templates.src, ['templates']);
});

gulp.task('scripts', ['coffee', 'js'])
gulp.task('scripts_compile', ['js_compile', 'coffee_compile'])
gulp.task('default', ['styles', 'scripts', 'templates', 'watch']);
gulp.task('compile', ['styles_compile', 'scripts_compile', 'templates_compile']);

Less has it’s own @import for requiring other files.
For JS to do that you’ll need a module bundler like Browserify or Webpack.

It may be easiest to keep bootstrap as separate includes in your html, and then you can bundle up all of your js and css into single files.

Here’s what I would be aiming to compile it down to.

  • build/js/app.js
  • build/css/app.css
  • vendor/bootstrap/…
2 Likes

Thank you sooo much!

Your answer gives me much clearer view how to manage my assets with Gulp.

I still have a question though, it seems what you posted is for production, what about development? Do you merge all CSS as one file app.css or app.js for JS? and how do you remove the minify or uglify step from Gulp task efficiently? (I mean you won’t write the same steps twice for dev and production, right?)

Thanks again!

I do actually write separate tasks for development and production.

Compare the js and js_compile tasks, the _compile ones include the extra steps for production.
For development I run the default task which watches for changes.

Yes, In the example above I’m using Sass @import’s to merge all the css into one, and in js I’m using the gulp-include package to do simple concatenation but I wouldn’t recommend that. Module bundlers are much better suited to these tasks.

oh okay… my bad, didn’t realize that…

Module bundlers you mean Webpack?

Yes, that’s probably where you will end up after looking into the various options.

If you’ve never created a bundle before I’d suggest you start with Browserify, it’s very simple to switch to Webpack later on if you want but Browserify let’s you require other javascript files similar to what Less / Sass @import statements do.

Here’s an good explanation of what browserify does: https://egghead.io/lessons/nodejs-introduction-to-browserify-part-1
You can run browserify from within a gulp task.

1 Like

Okay, thanks a lot for your help and guidance! I really appreciate it :smile:

No problemo, let us know if you get stuck.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.