Skip to content

Instantly share code, notes, and snippets.

@icamys
Last active December 29, 2018 01:42
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 icamys/464668020c5341861c3f8ff846b383fc to your computer and use it in GitHub Desktop.
Save icamys/464668020c5341861c3f8ff846b383fc to your computer and use it in GitHub Desktop.
Gulp 4 gulpfile.js (assets builder + JSCS + JSHint)
/*jslint node: true */
'use strict';
// ## Globals
var argv = require('minimist')(process.argv.slice(2));
var autoprefixer = require('gulp-autoprefixer');
var changed = require('gulp-changed');
var concat = require('gulp-concat');
var gulp = require('gulp');
var gulpif = require('gulp-if');
var imagemin = require('gulp-imagemin');
var jshint = require('gulp-jshint');
var jscs = require('gulp-jscs');
var less = require('gulp-less');
var merge = require('merge-stream');
var cssNano = require('gulp-cssnano');
var rev = require('gulp-rev');
var sass = require('gulp-sass');
var sourcemaps = require('gulp-sourcemaps');
var uglify = require('gulp-uglify');
var notify = require('gulp-notify');
var combiner = require('stream-combiner2').obj;
var del = require('del');
// CLI options
var enabled = {
// Enable static asset revisioning when `--production`
rev: argv.production,
// Disable source maps when `--production`
maps: !argv.production,
// Fail due to JSHint warnings only when `--production`
failJSHint: argv.production,
// Strip debug statments from javascript when `--production`
stripJSDebug: argv.production,
compression: argv.production
};
var manifestFilePath = 'web/assets/manifest.json';
// See https://github.com/austinpray/asset-builder
var manifest = require('asset-builder')(manifestFilePath);
// `path` - Paths to base asset directories. With trailing slashes.
// - `path.source` - Path to the source files. Default: `assets/`
// - `path.dist` - Path to the build directory. Default: `dist/`
var path = manifest.paths;
//// `config` - Store arbitrary configuration values here.
//var config = manifest.config || {};
// `globs` - These ultimately end up in their respective `gulp.src`.
// - `globs.js` - Array of asset-builder JS dependency objects. Example:
// ```
// {type: 'js', name: 'main.js', globs: []}
// ```
// - `globs.css` - Array of asset-builder CSS dependency objects. Example:
// ```
// {type: 'css', name: 'main.css', globs: []}
// ```
// - `globs.fonts` - Array of font path globs.
// - `globs.images` - Array of image path globs.
// - `globs.bower` - Array of all the main Bower files.
var globs = manifest.globs;
// `project` - paths to first-party assets.
// - `project.js` - Array of first-party JS assets.
// - `project.css` - Array of first-party CSS assets.
var project = manifest.getProjectGlobs();
// Path to the compiled assets manifest in the dist directory
var revManifest = path.dist + 'assets.json';
// ### CSS processing pipeline
// Example
// ```
// gulp.src(cssFiles)
// .pipe(combinedCssTasks('main.css'))
// .pipe(gulp.dest(path.dist + 'styles'))
// ```
var combinedCssTasks = function (filename) {
return combiner(
gulpif(enabled.maps, sourcemaps.init()),
gulpif('*.less', less({
plugins: [require('less-plugin-glob')]
})),
gulpif('*.scss', sass({
outputStyle: 'nested', // libsass doesn't support expanded yet
precision: 10,
includePaths: ['.'],
errLogToConsole: true
})),
concat(filename),
autoprefixer({
browsers: [
'last 2 versions',
'ie 8',
'ie 9',
'android 2.3',
'android 4',
'opera 12'
]
}),
gulpif(enabled.compression === true, cssNano({
safe: true
})),
gulpif(enabled.rev, rev()),
gulpif(enabled.maps, sourcemaps.write('.', {
sourceRoot: path.source + 'styles/'
}))
).on('error', notify.onError());
};
// ### JS processing pipeline
// Example
// ```
// gulp.src(jsFiles)
// .pipe(combinedJsTasks('main.js')
// .pipe(gulp.dest(path.dist + 'scripts'))
// ```
var combinedJsTasks = function (filename) {
return combiner(
gulpif(enabled.maps, sourcemaps.init()),
concat(filename),
gulpif(enabled.compression === true, uglify({
output: {
'ascii_only': true
},
compress: {
'drop_debugger': enabled.stripJSDebug
}
})),
gulpif(enabled.rev, rev()),
gulpif(enabled.maps, sourcemaps.write('.', {
sourceRoot: path.source + 'scripts/'
}))
).on('error', notify.onError());
};
// ### Write to rev manifest
// If there are any revved files then write them to the rev manifest.
// See https://github.com/sindresorhus/gulp-rev
var writeToManifest = function (directory) {
return combiner(
gulp.dest(path.dist + directory),
rev.manifest(revManifest, {
base: path.dist,
merge: true
}),
gulp.dest(path.dist)
).on('error', notify.onError());
};
// ## Gulp tasks
// Run `gulp -T` for a task summary
// ### Wiredep
// `gulp wiredep` - Automatically inject Less and Sass Bower dependencies. See
// https://github.com/taptapship/wiredep
gulp.task('wiredep', function () {
var wiredep = require('wiredep').stream;
return gulp.src(project.css)
.pipe(wiredep())
.pipe(changed(path.source + 'styles', {
hasChanged: changed.compareSha1Digest
}))
.pipe(gulp.dest(path.source + 'styles'));
});
gulp.task('styles:compilation', function (cb) {
var merged = merge();
manifest.forEachDependency('css', function (dep) {
merged
.add(gulp.src(dep.globs, {base: 'styles'})
.pipe(combinedCssTasks(dep.name)));
});
cb();
return merged
.pipe(writeToManifest('styles'));
});
// ### Styles
// `gulp styles` - Compiles, combines, and optimizes Bower CSS and project CSS.
// By default this task will only log a warning if a precompiler error is
// raised. If the `--production` flag is set: this task will fail outright.
gulp.task('styles', gulp.series(
'wiredep',
'styles:compilation'
));
// ### JSCS
// `gulp scripts:jscs` - Checks Javascript code style with JSCS
gulp.task('scripts:jscs', function () {
return gulp.src(['gulpfile.js'].concat(project.js))
.pipe(jscs())
.on('error', notify.onError())
.pipe(jscs.reporter())
.pipe(gulpif(enabled.failJSHint, jscs.reporter('fail')));
});
// ### JSHint
// `gulp scripts:jshint` - Lints configuration JSON and project JS.
gulp.task('scripts:jshint', function () {
return gulp.src([
'bower.json', 'gulpfile.js'
].concat(project.js))
.pipe(jshint())
.on('error', notify.onError())
.pipe(jshint.reporter('jshint-stylish'))
.pipe(gulpif(enabled.failJSHint, jshint.reporter('fail')));
});
gulp.task('scripts:compilation', function (cb) {
var merged = merge();
manifest.forEachDependency('js', function (dep) {
merged.add(
gulp.src(dep.globs, {base: 'scripts'})
.pipe(combinedJsTasks(dep.name))
);
});
cb();
return merged
.pipe(writeToManifest('scripts'));
});
// ### Scripts
// `gulp scripts` - Runs JSCS, JSHint then compiles, combines, and optimizes Bower JS
// and project JS.
gulp.task('scripts', gulp.series('scripts:jscs', 'scripts:jshint', 'scripts:compilation'));
// ### Fonts
// `gulp fonts` - Grabs all the fonts and outputs them in a directory
gulp.task('fonts', function () {
return gulp.src(globs.fonts)
.pipe(gulp.dest(path.dist + 'fonts'));
});
// ### Images
// `gulp images` - Run lossless compression on all the images.
gulp.task('images', function () {
return gulp.src(globs.images)
.pipe(gulpif(enabled.compression === true, imagemin({
progressive: true,
interlaced: true,
svgoPlugins: [{removeUnknownsAndDefaults: false}, {cleanupIDs: false}]
})))
.pipe(gulp.dest(path.dist + 'images'));
});
// ### Clean
// `gulp clean` - Deletes the build folder entirely.
gulp.task('clean', function () {
return del(path.dist);
});
// ### Build
// `gulp build` - Run all the build tasks but don't clean up beforehand.
// Generally you should be running `gulp` instead of `gulp build`.
gulp.task('build', gulp.series(
'clean',
gulp.parallel(
'styles',
'scripts',
'fonts',
'images'
)
));
// ### Gulp
// `gulp` - Run a complete build. To compile for production run `gulp --production`.
gulp.task('default', gulp.series('build'));
// ### Watch
// `gulp watch` - Use BrowserSync to proxy your dev server and synchronize code
// changes across devices. Specify the hostname of your dev server at
// `manifest.config.devUrl`. When a modification is made to an asset, run the
// build step for that asset and inject the changes into the page.
// See: http://www.browsersync.io
gulp.task('watch:styles', function () {
gulp.watch([path.source + 'styles/**/*'], gulp.series('styles'));
});
gulp.task('watch:scripts', function () {
gulp.watch([path.source + 'scripts/**/*'], gulp.series('scripts'));
});
gulp.task('watch:fonts', function () {
gulp.watch([path.source + 'fonts/**/*'], gulp.series('fonts'));
});
gulp.task('watch:images', function () {
gulp.watch([path.source + 'images/**/*'], gulp.series('images'));
});
gulp.task('watch:build', function () {
gulp.watch(['bower.json', manifestFilePath], gulp.series('build'));
});
gulp.task('watch',
gulp.series(
'default', gulp.parallel('watch:styles', 'watch:scripts', 'watch:fonts', 'watch:images', 'watch:build')
)
);
{
"name": "",
"version": "",
"author": "",
"engines": {
"node": ">= 4.4.5",
"npm": ">=2.15.5"
},
"devDependencies": {
"asset-builder": "^1.0.2",
"bower": "^1.7.9",
"del": "^2.2.0",
"gulp": "gulpjs/gulp#4.0",
"gulp-autoprefixer": "^3.1.0",
"gulp-changed": "^1.2.1",
"gulp-concat": "^2.5.2",
"gulp-cssnano": "^2.1.2",
"gulp-if": "^2.0.0",
"gulp-imagemin": "^3.0.1",
"gulp-jscs": "^3.0.2",
"gulp-jshint": "^2.0.0",
"gulp-less": "^3.0.3",
"gulp-notify": "^2.2.0",
"gulp-plumber": "^1.0.0",
"gulp-rename": "^1.2.0",
"gulp-rev": "^7.0.0",
"gulp-sass": "^2.0.0",
"gulp-sourcemaps": "^1.5.1",
"gulp-uglify": "^1.1.0",
"gulp-util": "^3.0.4",
"imagemin-pngcrush": "^4.0.0",
"jshint": "^2.9.2",
"jshint-stylish": "^2.1.0",
"less-plugin-glob": "^1.1.1",
"merge-stream": "^1.0.0",
"minimist": "^1.1.1",
"run-sequence": "^1.0.2",
"stream-combiner2": "^1.1.1",
"traverse": "^0.6.6",
"wiredep": "^4.0.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment