Caching image optimization tasks in gulp
I am trying to write a gulpfile.js that will follow modern optimization best practices and one of them is using an element picture
. So I optimize, resize and add webp
images, but all these processing tasks take quite a long time, so I want to cache them.
'use strict';
var gulp = require('gulp'),
plumber = require('gulp-plumber'),
gutil = require('gulp-util'),
notify = require('gulp-notify'),
size = require('gulp-size'),
rename = require('gulp-rename'),
sass = require('gulp-sass'),
autoprefixer = require('gulp-autoprefixer'),
cmq = require('gulp-combine-media-queries'),
minifyCSS = require('gulp-minify-css'),
jshint = require('gulp-jshint'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
psi = require('psi'),
ngrok = require('ngrok'),
cp = require('child_process'),
browserSync = require('browser-sync'),
imageMin = require('gulp-imagemin'),
cwebp = require('gulp-cwebp'),
imageResize = require('gulp-image-resize'),
cache = require('gulp-cache'),
cached = require('gulp-cached'),
changed = require('gulp-changed'),
newer = require('gulp-newer'),
parallel = require('concurrent-transform'),
os = require('os-utils'),
minifyHTML = require('gulp-minify-html'),
clean = require('gulp-clean'),
url = 'http://1ec934f4.ngrok.com/',
reload = browserSync.reload;
var onError = function(err) {
gutil.beep();
gutil.log(gutil.colors.green(err + '\n'));
};
var messages = {
jekyllBuild: '<span style="color: grey">Running:</span> $ jekyll build'
};
/*========== Paths ==========*/
var paths = {
styles: {
src: 'assets/sass/main.scss',
dest: 'build/css',
destProd: 'html/build/css',
watch: 'assets/sass/**/*.scss',
style: 'build/css/main.css',
styleProd: 'html/build/css/main.css',
styleMin: 'build/css/main.min.css',
styleMinProd: 'html/build/css/main.min.css'
},
scripts: {
src: 'assets/js/**/*.js',
dest: 'build/js',
destProd: 'html/build/js',
destVen: 'assets/js/vendor',
script: 'build/js/main.js',
scriptProd: 'html/build/js/main.js',
scriptMin: 'build/js/main.min.js',
scriptMinProd: 'html/build/js/main.min.js',
bundleMain: 'build/js/main.bundle.js',
bundleMainMin: 'build/js/main.bundle.min.js',
watch: ['assets/js/**/*.js', '!/assets/js/vendor/**/*.js']
},
jshint: {
src: [
'assets/js/**/*.js',
'!assets/js/vendor/**/*.js'
]
},
bundles: {
main: [
'assets/js/main.js',
'assets/js/vendor/**/*.js',
'!assets/js/vendor/bootstrap-sprockets.js',
'!assets/js/vendor/bootstrap.js',
]
},
images: {
src: 'assets/img/**/*.{jpg, png, svg, gif, webp}',
dest: 'build/img',
destOpt: 'build/img/opt',
destProd: 'html/build/img',
watch: 'assets/img/**/*.{jpg, png, svg, gif, webp}',
watchOpt: 'build/img/opt/*.{jpg, png, svg, gif, webp}',
watchDest: 'build/img/*.{jpg, png, svg, gif, webp}',
watchProd: 'html/build/img/**/*.{jpg, png, svg, gif, webp}'
},
html: {
dest: 'html',
watch: ['index.html', '_layouts/*.html', '_includes/**/*', '_posts/**/*'],
watchProd: 'html/**/*.html'
},
copy: {
styles: 'bower_components/bootstrap-sass-official/assets/stylesheets/**/*.scss',
scripts: 'bower_components/bootstrap-sass-official/assets/javascripts/**/*.js'
},
clean: {
img: 'build/img',
imgProd: 'html/build/img',
styles: 'build/css',
stylesProd: 'html/build/css',
scripts: 'build/js',
scriptsProd: 'html/build/js',
build: 'build',
buildProd: 'html/build',
prod: 'html'
}
};
/*==================================
= Gulp Tasks =
==================================*/
gulp.task('browser-sync', function() {
browserSync({server: {baseDir: paths.html.dest}});
});
gulp.task('sass', function () {
return gulp.src(paths.styles.watch)
.pipe(plumber({errorHandler: onError}))
.pipe(sass({outputStyles: 'nested'}))
.pipe(autoprefixer(['last 15 versions', '> 1%', 'ie 8', 'ie 7'], {cascade: true}))
.pipe(gulp.dest(paths.styles.dest))
.pipe(gulp.dest(paths.styles.destProd))
.pipe(size({showFiles: true}))
.pipe(notify('sass is done.\n'));
});
gulp.task('sass-min', ['sass'], function () {
return gulp.src(paths.styles.style)
.pipe(plumber({errorHandler: onError}))
.pipe(cmq({log: true}))
.pipe(minifyCSS())
// .pipe(zopfli())
// .pipe(zip('main.css.zip'))
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest(paths.styles.dest))
.pipe(gulp.dest(paths.styles.destProd))
.pipe(size({showFiles: true}))
.pipe(notify('Sass-min is done.\n'));
});
gulp.task('sass-reload', ['sass-min'], function () {
return gulp.src(paths.styles.styleMin)
.pipe(reload({stream: true}));
});
gulp.task('jshint-gulp', function () {
return gulp.src('gulpfile.js')
.pipe(cache(jshint('.jshintrc')))
.pipe(jshint.reporter('jshint-stylish'))
.pipe(notify('jshint-gulp is done.\n'));
});
gulp.task('jshint', ['jshint-gulp'], function () {
return gulp.src(paths.scripts.script)
.pipe(cache(jshint('.jshintrc')))
.pipe(jshint.reporter('jshint-stylish'))
.pipe(notify('jshint-gulp is done.\n'));
});
gulp.task('concat', ['jshint'], function () {
return gulp.src(paths.bundles.main)
.pipe(concat('main.bundle.js'))
.pipe(gulp.dest(paths.scripts.dest))
.pipe(gulp.dest(paths.scripts.destProd))
.pipe(size({showFiles: true}));
});
gulp.task('js', ['concat'], function () {
return gulp.src(paths.scripts.bundleMain)
.pipe(uglify())
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest(paths.scripts.dest))
.pipe(gulp.dest(paths.scripts.destProd))
.pipe(notify('js is done.\n'));
});
gulp.task('js-reload', ['js'], function () {
return gulp.src(paths.scripts.bundleMainMin)
.pipe(plumber({errorHandler: onError}))
.pipe(reload({stream:true}));
});
gulp.task('image-min', function () {
return gulp.src(paths.images.src)
.pipe(plumber({errorHandler: onError}))
.pipe(cached(imageMin({optimizationLevel: 3, progressive: true, interlaced: true})))
.pipe(gulp.dest(paths.images.destOpt))
.pipe(size({showFiles: true}))
.pipe(notify('image-min is done.\n'));
});
gulp.task('image-resize-sm', ['image-min'], function () {
return gulp.src(paths.images.watchOpt)
.pipe(plumber({errorHandler: onError}))
.pipe(changed(paths.images.dest))
.pipe(parallel(imageResize({
width : 400,
height : 300,
crop : true,
upscale : false
}), os.cpuUsage(function(v) { console.log( 'CPU Usage (%): ' + v ); })))
.pipe(rename({suffix: '-sm'}))
.pipe(gulp.dest(paths.images.dest))
.pipe(size({showFiles: true}))
.pipe(gulp.dest(paths.images.destProd));
});
gulp.task('image-resize-md', ['image-resize-sm'], function () {
return gulp.src(paths.images.watchOpt)
.pipe(plumber({errorHandler: onError}))
.pipe(changed(paths.images.dest))
.pipe(parallel(imageResize({
width : 800,
height : 600,
crop : true,
upscale : false
}), os.cpuUsage(function(v) { console.log( 'CPU Usage (%): ' + v ); })))
.pipe(rename({suffix: '-md'}))
.pipe(gulp.dest(paths.images.dest))
.pipe(size({showFiles: true}))
.pipe(gulp.dest(paths.images.destProd));
});
gulp.task('image-resize-lg', ['image-resize-md'], function () {
return gulp.src(paths.images.watchOpt)
.pipe(plumber({errorHandler: onError}))
.pipe(changed(paths.images.dest))
.pipe(parallel(imageResize({
width : 1200,
height : 900,
crop : true,
upscale : false
}), os.cpuUsage(function(v) { console.log( 'CPU Usage (%): ' + v ); })))
.pipe(rename({suffix: '-lg'}))
.pipe(size({showFiles: true}))
.pipe(gulp.dest(paths.images.dest))
.pipe(gulp.dest(paths.images.destProd));
});
gulp.task('cwebp', ['image-resize-lg'], function () {
return gulp.src(paths.images.watchProd)
.pipe(plumber({errorHandler: onError}))
// .pipe(changed(paths.images.watchDest))
// .pipe(cwebp())
.pipe(changed(paths.images.watchDest))
.pipe(parallel(cwebp()), os.cpuUsage(function(v) { console.log( 'CPU Usage (%): ' + v ); }))
.pipe(gulp.dest(paths.images.dest))
.pipe(gulp.dest(paths.images.destProd))
.pipe(notify('cwebp is done.\n'));
});
gulp.task('img-reload', ['cwebp'], function () {
return gulp.src(paths.images.destProd)
.pipe(plumber({errorHandler: onError}))
.pipe(reload({stream:true}))
.pipe(notify('img-reload is done.\n'));
});
gulp.task('jekyll-build', function (done) {
browserSync.notify(messages.jekyllBuild);
return cp.spawn('jekyll', ['build'], {stdio: 'inherit'})
.on('close', done);
});
gulp.task('jekyll', ['jekyll-build'], function() {
return gulp.src(paths.html.watchProd)
.pipe(minifyHTML())
.pipe(gulp.dest(paths.html.dest));
});
gulp.task('jekyll-rebuild', ['jekyll'], function () {
reload();
});
gulp.task('copy-css', function() {
return gulp.src(paths.copy.styles)
.pipe(gulp.dest('assets/scss/vendor'));
});
gulp.task('copy-js', function() {
return gulp.src(paths.copy.scripts)
.pipe(gulp.dest(paths.scripts.destVen));
});
gulp.task('clear-cache', function(done) {
return cache(cache.caches = {});
});
gulp.task('clean', ['clear-cache'], function() {
return gulp.src(paths.html.dest, {read: false})
.pipe(clean());
});
gulp.task('ngrok', function () {
ngrok.connect({
authtoken: 'aGJcNEqh838HDfvyheIe', //2BUMGp1fJDzPal7FvxN2
//httpauth: 'login:password',
port: 3000
}, function(err, url) {
if (err !== null) {
console.log( err );
}
});
});
gulp.task('pagespeed', ['ngrok'], function () {
return psi({
nokey: 'true', // or use key: ‘YOUR_API_KEY’
url: url,
strategy: 'mobile'
});
});
gulp.task('watch', ['sass-min', 'js', 'browser-sync'], function () {
gulp.watch(paths.styles.watch, ['sass-reload']);
gulp.watch(paths.scripts.watch, ['js-reload']);
gulp.watch(paths.images.watch, ['img-reload']);
gulp.watch(paths.html.watch, ['jekyll-rebuild']);
});
Questions
- How to properly use os-utils to output cpu and memory in% used for one task?
- Does the onError function work well? I am confused about how to use beep and gutil?
- How to cache (or
change
,remember
,cached
or any other caching plugins) for image problemsgulp-resize
andgulp-cwebp
?
Check out the Github repository
I ran a few tests and the processing times suggest that gulp-cached
both parallel
are working fine but gulp-changed
not working. I also tried using plugins gulp-cache
and gulp-cached
instead gulp-changed
, but that didn't work either.
I did the task gulp-reload
for these tests with all the image analyzes from this repo. The task gulp-reload
includes plugins gulp-imagemin
, gulp-image-resize
and gulp-cwebp
.
If you want to run these tests on your local machine, I suggest using a task gulp clear-cache
to clear the cache for a task gulp image-min
.
Test 1
- image-min [cached]
- resize image []
- cwebp []
TIME +/- 64 sec.
Test 2
- image-min [cached]
- resizing image [resized]
- cwebp []
TIME +/- 63 sec
Test 3
- image-min [cached]
- resizing image [resized]
- cwebp [modified]
TIME +/- 64 sec.
Test 4
- image-min [cached]
- resizing image [resized, parallel]
- cwebp [modified]
Time +/- 22 sec
Test 5
- image-min []
- resizing image [resized, parallel]
- cwebp [modified]
Time +/- 32sec
Any suggestions for the code are also welcome!
source to share
No one has answered this question yet
Check out similar questions: