Skip to content

Instantly share code, notes, and snippets.

@umkasanki
Last active February 5, 2019 15:58
Show Gist options
  • Save umkasanki/4e71973b02dcce753bb2b394b25cd84d to your computer and use it in GitHub Desktop.
Save umkasanki/4e71973b02dcce753bb2b394b25cd84d to your computer and use it in GitHub Desktop.
/* eslint-env node */
// package vars
const pkg = require('./package.json');
const webpack = require('webpack-stream');
const gulp = require('gulp');
// load all plugins in "devDependencies" into the variable $
const $ = require('gulp-load-plugins')({
pattern: ['*'],
scope: ['devDependencies'],
rename: {
'gulp-prettier': 'prettify'
}
});
// error logging
const onError = err => {
$.notify.onError({
title: 'Gulp',
subtitle: ['<%= error.relativePath %>', '<%= error.line %>'].join(':'),
message: '<%= error.messageOriginal %>',
open: 'file://<%= error.file %>',
onLast: true,
sound: 'Beep'
})(err);
};
let currentCSSVersion = 0;
let currentJSVersion = 0;
// static assets version tasks
gulp.task('css-version', () => {
$.fancyLog('-> Change CSS version');
return gulp
.src(pkg.paths.craftConfig + 'general.php')
.pipe(
$.replace(/'currentCSSVersion' => (\d+),/g, function(match, p1) {
p1++;
$.fancyLog('-> Changed currentCSSVersion to ' + p1);
currentCSSVersion = p1;
return "'currentCSSVersion' => " + p1 + ',';
})
)
.pipe(gulp.dest(pkg.paths.craftConfig));
});
gulp.task('js-version', () => {
$.fancyLog('-> Change JS version');
return gulp
.src(pkg.paths.craftConfig + 'general.php')
.pipe(
$.replace(/'currentJSVersion' => (\d+),/g, function(match, p1) {
p1++;
$.fancyLog('-> Changed currentJSVersion to ' + p1);
currentJSVersion = p1;
return "'currentJSVersion' => " + p1;
})
)
.pipe(gulp.dest(pkg.paths.craftConfig));
});
// gulp clean-js
gulp.task('clean-js', () => {
return gulp.src([
pkg.paths.build.js + '**/*.js',
pkg.paths.dist.js + '**/*.js'
], { read: false }).pipe($.clean());
});
// gulp clean-css
gulp.task('clean-css', () => {
return gulp.src([
pkg.paths.build.css + '**/*',
pkg.paths.dist.css + '**/*'
],
{ read: false }).pipe($.clean());
});
// gulp browser-sync
gulp.task('browser-sync', function(cb) {
$.browserSync.init({
proxy: {
target: pkg.urls.local
}
});
cb();
});
// gulp prettify - prettier task
gulp.task('prettify', () => {
return gulp
.src(['*.js', 'src/**/*.js', 'src/scss/**/*.scss', '*yml', '*.json', '*md'])
.pipe($.prettify())
.pipe(gulp.dest(file => file.base));
});
// gulp scss - build the scss to the build folder, including the required paths, and writing out a sourcemap
gulp.task(
'scss',
gulp.series('css-version', 'clean-css', () => {
$.fancyLog('-> Compiling scss');
return (
gulp
.src(pkg.paths.src.scss + pkg.vars.scssName)
.pipe($.sassGlob())
.pipe($.plumber({ errorHandler: onError }))
.pipe($.sourcemaps.init({ loadMaps: true }))
.pipe(
$.sass({
includePaths: [pkg.paths.scss, 'node_modules']
}).on('error', $.sass.logError)
)
.pipe($.cached('sass_compile'))
.pipe($.autoprefixer())
.pipe($.base64({ extensions: ['svg'], debug: true }))
.pipe($.sourcemaps.write('./'))
.pipe($.size({ gzip: true, showFiles: true }))
.pipe(gulp.dest(pkg.paths.build.css))
);
})
);
// gulp css - combine & minimize any distribution CSS into the public css folder, and add our banner to it
gulp.task(
'css',
gulp.series('scss', () => {
$.fancyLog('-> Building css');
return (
gulp
.src(pkg.globs.distCss)
.pipe($.plumber({ errorHandler: onError }))
.pipe($.newer({ dest: pkg.paths.dist.css + pkg.vars.siteCssName }))
.pipe($.print.default())
.pipe($.sourcemaps.init({ loadMaps: true }))
// .pipe($.concat(currentCSSVersion + '.' + pkg.vars.siteCssName))
.pipe($.rename({ suffix: '.min.' + currentCSSVersion }))
.pipe(
// $.if(
// process.env.NODE_ENV === 'production',
$.cssnano({
discardComments: {
removeAll: true
},
discardDuplicates: true,
discardEmpty: true,
minifyFontValues: true,
minifySelectors: true
})
// )
)
.pipe($.sourcemaps.write('./'))
.pipe($.size({ gzip: true, showFiles: true }))
.pipe(gulp.dest(pkg.paths.dist.css))
.pipe($.filter('**/*.css'))
);
})
);
// gulp js-babel - transpile our Javascript into the build directory
gulp.task(
'js-babel',
gulp.series('js-version', 'clean-js', () => {
$.fancyLog('-> Transpiling Javascript ...');
return gulp
.src(pkg.globs.babelJs)
.pipe($.plumber({ errorHandler: onError }))
.pipe($.newer({ dest: pkg.paths.build.js }))
.pipe(
webpack({
...require('./webpack.config.js'),
mode: process.env.NODE_ENV || 'development'
})
)
.pipe(gulp.dest(pkg.paths.build.js));
})
);
// gulp js-inline - minimize the inline Javascript into _inlinejs in the templates path
gulp.task(
'js-inline',
gulp.series('js-babel', () => {
$.fancyLog('-> Copying inline js');
return gulp
.src(pkg.globs.inlineJs)
.pipe($.plumber({ errorHandler: onError }))
.pipe(
$.if(
['*.js', '!*.min.js'],
$.newer({ dest: pkg.paths.templates + '_inlinejs', ext: '.min.js' }),
$.newer({ dest: pkg.paths.templates + '_inlinejs' })
)
)
.pipe($.if(['*.js', '!*.min.js'], $.terser()))
.pipe($.if(['*.js', '!*.min.js'], $.rename({ suffix: '.min.' + currentJSVersion })))
.pipe($.size({ gzip: true, showFiles: false }))
.pipe(gulp.dest(pkg.paths.templates + '_inlinejs'))
.pipe($.filter('**/*.js'));
})
);
// gulp js - minimize any distribution Javascript into the public js folder, and add our banner to it
gulp.task(
'js',
gulp.series('js-inline', () => {
$.fancyLog('-> Building js');
return (
gulp
.src(pkg.globs.distJs)
.pipe($.plumber({ errorHandler: onError }))
.pipe(
$.if(
['*.js', '!*.min.js'],
$.newer({ dest: pkg.paths.dist.js, ext: '.min.js' }),
$.newer({ dest: pkg.paths.dist.js })
)
)
.pipe($.if(['*.js', '!*.min.js'], $.terser()))
.pipe($.if(['*.js', '!*.min.js'], $.rename({ suffix: '.min.' + currentJSVersion })))
.pipe($.stripComments())
.pipe($.size({ gzip: true, showFiles: true }))
.pipe(gulp.dest(pkg.paths.dist.js))
.pipe($.filter('**/*.js'))
);
})
);
// Process data in an array synchronously, moving onto the n+1 item only after the nth item callback
function doSynchronousLoop(data, processData, done) {
if (data.length > 0) {
const loop = (data, i, processData, done) => {
processData(data[i], i, () => {
if (++i < data.length) {
loop(data, i, processData, done);
} else {
done();
}
});
};
loop(data, 0, processData, done);
} else {
done();
}
}
// Process the critical path CSS one at a time
function processCriticalCSS(element, i, callback) {
const criticalSrc = pkg.urls.critical + element.url;
const criticalDest = pkg.paths.templates + '_inlinecss/' + element.template + '_critical.min.css';
let criticalWidth = 1440;
let criticalHeight = 1000;
if (element.template.indexOf('amp_') !== -1) {
criticalWidth = 375;
criticalHeight = 750;
}
$.fancyLog('-> Generating critical CSS: ' + $.chalk.cyan(criticalSrc) + ' -> ' + $.chalk.magenta(criticalDest));
$.critical.generate(
{
src: criticalSrc,
dest: criticalDest,
penthouse: {
timeout: 120000,
blockJSRequests: false,
forceInclude: pkg.globs.criticalWhitelist
},
inline: false,
ignore: [],
css: [pkg.paths.dist.css + pkg.vars.siteCssName],
minify: true,
width: criticalWidth,
height: criticalHeight
},
err => {
if (err) {
$.fancyLog($.chalk.magenta(err));
}
callback();
}
);
}
// gulp criticalcss - criticalcss css task
gulp.task(
'criticalcss',
gulp.series('css', callback => {
doSynchronousLoop(pkg.globs.critical, processCriticalCSS, () => {
// all done
callback();
});
})
);
// gulp favicons-generate - favicons-generate task
gulp.task('favicons-generate', () => {
$.fancyLog('-> Generating favicons');
return gulp
.src(pkg.paths.favicon.src)
.pipe(
$.favicons({
appName: pkg.name,
appDescription: pkg.description,
developerName: pkg.author,
developerURL: pkg.urls.live,
background: '#FFFFFF',
path: pkg.paths.favicon.path,
url: pkg.site_url,
display: 'standalone',
orientation: 'portrait',
version: pkg.version,
logging: false,
online: false,
html: pkg.paths.build.html + 'favicons.html',
replace: true,
icons: {
android: false, // Create Android homescreen icon. `boolean`
appleIcon: true, // Create Apple touch icons. `boolean`
appleStartup: false, // Create Apple startup images. `boolean`
coast: true, // Create Opera Coast icon. `boolean`
favicons: true, // Create regular favicons. `boolean`
firefox: true, // Create Firefox OS icons. `boolean`
opengraph: false, // Create Facebook OpenGraph image. `boolean`
twitter: false, // Create Twitter Summary Card image. `boolean`
windows: true, // Create Windows 8 tile icons. `boolean`
yandex: true // Create Yandex browser icon. `boolean`
}
})
)
.pipe(gulp.dest(pkg.paths.favicon.dest));
});
// gulp favicons - copy favicons task
gulp.task(
'favicons',
gulp.series('favicons-generate', () => {
$.fancyLog('-> Copying favicon.ico');
return gulp
.src(pkg.globs.siteIcon)
.pipe($.size({ gzip: true, showFiles: true }))
.pipe(gulp.dest(pkg.paths.dist.base));
})
);
// gulp imagemin - imagemin task
gulp.task('imagemin', () => {
$.fancyLog('-> Minimizing images in ' + pkg.paths.src.img);
return gulp
.src(pkg.paths.src.img + '**/*.{png,jpg,jpeg,gif,svg}')
.pipe(
$.imagemin([
$.imagemin.gifsicle({ interlaced: true }),
$.imagemin.optipng({
optimizationLevel: 3
}),
$.imagemin.jpegtran({ progressive: true }),
$.imagemin.svgo({
removeViewBox: true
})
])
)
.pipe(gulp.dest(pkg.paths.dist.img));
});
// gulp fonts - copy fonts task
gulp.task('fonts', () => {
return gulp.src(pkg.globs.fonts).pipe(gulp.dest(pkg.paths.dist.fonts));
});
// gulp set-dev-node-env - set the node environment to development
gulp.task('set-dev-node-env', function(cb) {
$.fancyLog('-> Setting NODE_ENV to development');
process.env.NODE_ENV = 'development';
cb();
});
// gulp set-prod-node-env - set the node environment to production
gulp.task('set-prod-node-env', function(cb) {
$.fancyLog('-> Setting NODE_ENV to production');
process.env.NODE_ENV = 'production';
cb();
});
function reload(done) {
$.browserSync.reload();
done();
}
// gulp - default task
gulp.task(
'default',
gulp.series('set-dev-node-env', 'css', 'js', 'browser-sync', cb => {
$.fancyLog('-> Livereload listening for changes');
gulp.watch('**/*.{scss,sass}', { cwd: pkg.paths.src.scss }, gulp.series('css', reload));
gulp.watch('**/*.js', { cwd: pkg.paths.src.js }, gulp.series('js', reload));
// gulp.watch('**/*.{png,jpg,jpeg,gif,svg}', { cwd: pkg.paths.src.img }, gulp.series('imagemin', reload));
gulp
.watch('**/*.{html,twig}', { cwd: pkg.paths.templates }, gulp.series(() => {
return gulp.src(pkg.paths.templates).pipe($.plumber({ errorHandler: onError }));
}, reload));
cb();
})
);
// gulp build - production build
gulp.task(
'build',
gulp.parallel('set-prod-node-env', 'fonts', 'favicons', 'imagemin', 'criticalcss', 'js', 'css')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment