Skip to content

Instantly share code, notes, and snippets.

@jamiter
Last active August 29, 2015 14:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamiter/fff2081c3cdcf62ce316 to your computer and use it in GitHub Desktop.
Save jamiter/fff2081c3cdcf62ce316 to your computer and use it in GitHub Desktop.
gulp file to replace Hem

Gulp

Gulp is used to quickly generate all js and css files. In our project you do not need to call gulp directly. Simply use npm install and npm start and the right gulp actions will be called.

Dependencies

gulp    = require 'gulp'

coffee  = require 'gulp-coffee'
common  = require 'gulp-commonjs'
concat  = require 'gulp-concat'
connect = require 'gulp-connect'
gulpif  = require 'gulp-if'
gutil   = require 'gulp-util'
insert  = require 'gulp-insert'
jade    = require 'gulp-jade'
rename  = require 'gulp-rename'
stylus  = require 'gulp-stylus'
uglify  = require 'gulp-uglify'

Configuration

Destination

Destination directory

dest = "build"

Paths

paths =
  stylus: ["css/index.styl"]
  coffee: [
    "app/**/*.coffee"
    "app/**/*.litcoffee"
  ]
  js: ["app/**/*.js"]
  jade: ["app/**/*.jade"]

Libs will be directly added without a commonjs wrapper:

  libs: [
    "node_modules/jade/runtime.js"
    "node_modules/commonjs-require-definition/require.js"
  ]

Node modules which will be included with a commonjs wrapper:

  modules: [
    "es5-shimify"
    "json2ify"
    "jquery"
    "jquery-ui"
    "jquery.browser/dist/jquery.browser.js"
    "moment"
    "pluralize"
    "q"
    "spine/lib/spine"
    "spine/lib/local"
    "spine/lib/relation"
    "spine/lib/ajax"
    "spine/lib/route"
    "spine/lib/manager"
    "spine/lib/list"
  ]

Targets

Names for the generated files

targets =
  css     : "application.css"
  js      : "application.js"
  jsMin   : "application.min.js"
  jade    : "templates.js"
  lib     : "libs.js"
  scripts : "scripts.js"
  coffee  : "coffee.js"
  modules : "modules.js"

Error handler

When a file generates an error, we report it and then continue the stream

reportError = (err) ->
  gutil.log err
  @emit 'end'

CSS

Convert stylus files into one .css file.

generateCss = ->
  gulp.src paths.stylus
    .pipe stylus()
    .pipe concat targets.css
    .pipe gulp.dest dest
    .pipe connect.reload()

gulp.task "stylus", generateCss

JS

Modules are node_modules which are added to the client code. These are all wrapped in a commonjs wrapper.

gulp.task "modules", ->
  files = (require.resolve(module) for module in paths.modules)
  gulp.src(files, base: __dirname)
    .pipe rename (path) ->
      path.extname = ""
      path.dirname = path.dirname
      .split('node_modules/')[1]
      .split('/dist')[0]
      path.basename = '' if path.basename is 'index'
      path.dirname = '' if path.basename in ['spine', path.dirname]
      path
    .pipe common()
    .pipe concat targets.modules
    .pipe gulp.dest dest

Transform all the .jade files to templates.js with commonjs wrappers around them.

gulp.task "jade", ->
  gulp.src paths.jade
    .pipe jade(client: true).on('error', reportError)
    .pipe insert.prepend "module.exports = "
    .pipe rename extname: ""
    .pipe common()
    .pipe concat targets.jade
    .pipe gulp.dest dest

All .coffee and .js files are combined into one .js file with a commonjs wrapper around each one.

gulp.task "scripts", ->
  gulp.src paths.js
    .pipe rename extname: ""
    .pipe common()
    .pipe concat targets.scripts
    .pipe gulp.dest dest

gulp.task "coffee", ->
  gulp.src paths.coffee
    .pipe coffee(bare: true).on('error', reportError)
    .pipe rename extname: ""
    .pipe common()
    .pipe concat targets.coffee
    .pipe gulp.dest dest

Libs are directly added without a commonjs wrapper. Note: this shouldn't be the default, but special case only.

gulp.task "libs", ->
  gulp.src paths.libs
    .pipe concat targets.lib
    .pipe gulp.dest dest

Do all the js things

gulp.task "js", ["libs", "modules", "scripts", "coffee", "jade"], (next) ->
  next()

Combine the above results into one .js file.

combineJs = ->
  # We need to rethrow jade errors to see them
  rethrow = (err, filename, lineno) -> throw err

  files = [
    targets.lib
    targets.modules
    targets.scripts
    targets.coffee
    targets.jade
  ]
  sources = files.map (file) -> "#{dest}/#{file}"

  gulp.src sources
    .pipe concat targets.js
    .pipe insert.append "jade.rethrow = #{rethrow.toLocaleString()};"
    .pipe gulp.dest dest
    .pipe connect.reload()

gulp.task "combine", combineJs

Build

Build js, stylus and combine js

gulp.task "build", ["js"], ->
  generateCss()
  combineJs()

Minify end results

gulp.task "minify", ->
  gulp.src "#{dest}/#{targets.js}"
    .pipe uglify()
    .pipe concat targets.jsMin
    .pipe gulp.dest dest

Server

The connect server has livereload support, which means that css and js are automatically refreshed in the browser.

gulp.task "server", ["build"], connect.server
  root: [dest]
  port: 9294
  livereload: true
  middleware: ->
    [
      (req, res, next) ->
        res.setHeader 'Access-Control-Allow-Origin', '*'
        res.setHeader 'Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE'
        res.setHeader 'Access-Control-Allow-Headers', 'Content-Type'
        next()
    ]

Watch

gulp.task "watch", ["server"], ->

  gulp.watch 'css/*.styl', {interval: 1000}, ['stylus']
  gulp.watch paths.jade, {interval: 2000}, ['jade']
  gulp.watch paths.coffee, {interval: 2000}, ['coffee']
  gulp.watch paths.js, {interval: 2000}, ['scripts']

  files = [targets.scripts, targets.jade, targets.coffee]
  sources = ("#{dest}/#{file}" for file in files)

  gulp.watch sources, {interval: 1000}, ['combine']

Default

gulp.task "default", ["watch"]
doctype html
html
head
link(rel="stylesheet", type="text/css", href="build/application.css")
script(type="text/javascript", src="build/application.js")
script(type="text/javascript").
var jQuery = require("jquery");
var $ = jQuery;
var exports = this;
jQuery(function(){
console.log('ready to go!');
});
@jamiter
Copy link
Author

jamiter commented May 7, 2014

The fact that I great multiple files is for testing purposes.

@sebastiannm
Copy link

Hi, thanks for your work.

Based in your work I created a new gulp configuration. I share it with you:

https://github.com/Nex9/imago.theme

Some changes would be using BrowserSync, it's pretty amazing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment