Last active
January 19, 2024 13:43
-
-
Save jeromecoupe/dbda0e037f2fee9e0026dfb38fbc5e73 to your computer and use it in GitHub Desktop.
responsive image pipeline in Gulp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
// --------------------------------------- | |
// packages | |
// --------------------------------------- | |
const del = require("del"); | |
const deleteEmpty = require("delete-empty"); | |
const globby = require("globby"); | |
const gulp = require("gulp"); | |
const gulpImagemin = require("gulp-imagemin"); | |
const gulpImageresize = require("gulp-image-resize"); | |
const gulpNewer = require("gulp-newer"); | |
const merge2 = require("merge2"); | |
// --------------------------------------- | |
// transfroms config | |
// --------------------------------------- | |
const transforms = [ | |
{ | |
src: "./assets/img/blogposts/*", | |
dist: "./public/assets/img/blogposts/", | |
params: { | |
width: 800, | |
height: 600, | |
crop: true | |
} | |
}, | |
{ | |
src: "./assets/img/banners/*", | |
dist: "./public/assets/img/banners/", | |
params: { | |
width: 1500, | |
height: 844, | |
crop: true | |
} | |
} | |
]; | |
// --------------------------------------- | |
// images tasks | |
// --------------------------------------- | |
/** | |
* Copy original images | |
* - check if images are newer than existing ones | |
* - if they are, optimise and copy them | |
* - ignore (empty) directories | |
*/ | |
gulp.task("img:copy", ["img:clean"], () => { | |
return gulp.src("./assets/img/**/*", { nodir: true }) | |
.pipe(gulpNewer("./public/assets/img/")) | |
.pipe(gulpImagemin({ | |
progressive: true, | |
svgoPlugins: [{ removeViewBox: false }, { removeUselessStrokeAndFill: false }] | |
})) | |
.pipe(gulp.dest("./public/assets/img/")); | |
}); | |
/** | |
* Make thumbnails | |
* 1. walk transforms array to build an array of streams | |
* - get src images | |
* - check if images in src are newer than images in dist | |
* - if they are, make thumbnails and minify | |
* 2. merge streams to create all thumbnails in parallel | |
*/ | |
gulp.task("img:thumbnails", ["img:clean"], () => { | |
// create empty streams array for merge2 | |
const streams = []; | |
// loop through transforms and add to streams array | |
transforms.map((transform) => { | |
// create a stream for each transform | |
streams.push( | |
gulp.src(transform.src) | |
.pipe(gulpNewer(transform.dist + "thumbs_" + transform.params.width + "x" + transform.params.height)) | |
.pipe(gulpImageresize({ | |
imageMagick: true, | |
width: transform.params.width, | |
height: transform.params.height, | |
crop: transform.params.crop | |
})) | |
.pipe(gulpImagemin({ | |
progressive: true, | |
svgoPlugins: [{ removeViewBox: false }, { removeUselessStrokeAndFill: false }] | |
})) | |
.pipe(gulp.dest(transform.dist + "thumbs_" + transform.params.width + "x" + transform.params.height)) | |
); | |
}); | |
// merge streams | |
return merge2(streams); | |
}); | |
/** | |
* Clean images | |
* 1. get arrays of filepaths in images src (base images) and dist (base images and thumbnails) | |
* 2. Diffing process | |
* - build list of filepaths in src | |
* - loop through filepaths in dist, remove dist and thumbnails specific parts | |
* to get both base images and corresponding thumbnails, compare with filepaths in src | |
* - if no match, add full dist image filepath to delete array | |
* 3. Delete files (base images and thumbnails) | |
*/ | |
gulp.task("img:clean", ["img:clean:directories"], () => { | |
// get arrays of src and dist filepaths (returns array of arrays) | |
return Promise.all([ | |
globby("./assets/img/**/*", { nodir: true }), | |
globby("./public/assets/img/**/*", { nodir: true }) | |
]) | |
.then((paths) => { | |
// create arrays of filepaths from array of arrays returned by promise | |
const srcFilepaths = paths[0]; | |
const distFilepaths = paths[1]; | |
// empty array of files to delete | |
const distFilesToDelete = []; | |
// diffing | |
distFilepaths.map((distFilepath) => { | |
// sdistFilepathFiltered: remove dist root folder and thumbs folders names for comparison | |
const distFilepathFiltered = distFilepath.replace(/\/public/, "").replace(/thumbs_[0-9]+x[0-9]+\//, ""); | |
// check if simplified dist filepath is in array of src simplified filepaths | |
// if not, add the full path to the distFilesToDelete array | |
if ( srcFilepaths.indexOf(distFilepathFiltered) === -1 ) { | |
distFilesToDelete.push(distFilepath); | |
} | |
}); | |
// return array of files to delete | |
return distFilesToDelete; | |
}) | |
.then((distFilesToDelete) => { | |
// delete files | |
del.sync(distFilesToDelete); | |
}) | |
.catch((error) => { | |
console.log(error); | |
}); | |
}); | |
/** | |
* Clean unused directories | |
* 1. Diffing process between src and dist for images and thumbnails | |
* - Build array of all thumbs_xxx directories that should exist using the transforms map | |
* - Build array of all thumbs_xxx directories in img dist | |
* - Diffing: array of all unused thumbnails directories in dist | |
* 2. Delete files | |
* 3. Delete all empty folders in dist images | |
*/ | |
gulp.task("img:clean:directories", () => { | |
globby("./public/assets/img/**/thumbs_+([0-9])x+([0-9])/") | |
.then((paths) => { | |
// existing thumbs directories in dist | |
const distThumbsDirs = paths; | |
// create array of dirs that should exist by walking transforms map | |
const srcThumbsDirs = transforms.map((transform) => transform.dist + "thumbs_" + transform.params.width + "x" + transform.params.height + "/"); | |
// array of dirs to delete | |
const todeleteThumbsDirs = distThumbsDirs.filter((el) => srcThumbsDirs.indexOf(el) === -1); | |
// pass array to next step | |
return todeleteThumbsDirs; | |
}) | |
.then((todeleteThumbsDirs) => { | |
// deleted diff thumbnails directories | |
del.sync(todeleteThumbsDirs); | |
}) | |
.then(() => { | |
// delete empty directories in dist images | |
deleteEmpty.sync("./public/assets/img/"); | |
}) | |
.catch((error) => { | |
console.log(error); | |
}); | |
}); | |
// --------------------------------------- | |
// tasks | |
// --------------------------------------- | |
/** | |
* We just need img:copy and img:thumbnails. | |
* All other tasks are dependencies | |
*/ | |
gulp.task("img", ["img:copy", "img:thumbnails"]); | |
/** | |
* watch task | |
*/ | |
gulp.task("watch", () => { | |
gulp.watch(["assets/img/**/*"], ["img"]); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You're repeated width config for thumbnail height:
width: transform.params.width, height: transform.params.width,