gulphugonetlifygulp-imageminnetlify-cms

How to optimize images uploaded through Netlify CMS?


I have a Hugo site and I'm using Netlify CMS to manage the content. Everytime the site builds, it runs a Gulp task that optimizes images from the src folder to the static folder. But, the problem is, when I upload an image through the CMS, it stores it in the static folder.

So, in the admin config.yml, should I set the media_folder to src/images instead?

My thinking is that the task will run and store the new minified image into the static folder but is that right? Or is there another way to do this?

Gulp task:

gulp.task('images', () => {
    return gulp.src('src/images/**/*.{png,jpg,jpeg,gif,svg,webp,ico}')
        .pipe($.newer('static/images'))
        .pipe($.print())
        .pipe($.imagemin([
            $.imagemin.jpegtran({progressive: true}),
            $.imagemin.optipng({optimizationLevel: 5}),
        ]))
        .pipe(gulp.dest('static/images'));
});

Admin config.yml

media_folder: "static/images"
public_folder: "images"

Solution

  • In your content repository, you can make a build script (build & deploy if hosted on Netlify) and it can resize and optimise images and put them into a new folder anytime it detects new content. Most importantly, remove EXIF data such as Geolocation.

      const path = require('path');
      const gm = require('gm');
      const fs = require('fs-extra');
      const klaw = require('klaw');
    
      const mediaDir = path.resolve(__dirname, 'media');
      const imagesDir = path.resolve(__dirname, 'images');
    
      const sizes = [
         {size: 1280, rename: false},
         {size: 640, rename: true},
         {size: 320, rename: true},
      ];
    
      const imagesToProcess = [];
    
      (async () => {
         await fs.ensureDir(imagesDir);
    
         klaw(mediaDir)
            .on('data', (item) => {
    
               const stat = fs.lstatSync(item.path);
               const copyPath = path.resolve(imagesDir, path.basename(item.path));
    
               if (stat.isFile() && !fs.pathExistsSync(copyPath)) {
    
                  imagesToProcess.push([item.path, copyPath]);
    
               }
    
            })
            .on('end', () => {
    
               imagesToProcess.reduce((promise, [originalImage, copyPath]) => {
    
                  sizes.reduce((promise, sizeObject) => {
    
                     return promise.then(() => new Promise((resolve) => {
    
                        gm(originalImage)
                           .noProfile()
                           .resizeExact(sizeObject.size, sizeObject.size)
                           .quality(75)
                           .write(copyPath.replace('.jpg', `-${sizeObject.size}.jpg`), () => resolve());
    
                     }));
    
                  }, promise);
    
               }, Promise.resolve());
    
            });
    
      })();