Andy-set-studio / learneleventyfromscratch.com

In this Eleventy course, we go from a completely empty directory to a full-blown marketing site for a design agency, and along the way, we dive really deep into Eleventy and front-end development best practices.

Home Page:https://learneleventyfromscratch.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Lesson 18-20: Transform gulp pipeline to use ESM (to fix issue with `gulp-imagemin`)

sophiabrandt opened this issue · comments

gulp-imagemin in its latest version is now ESM only (see also #24 ).

In my personal project I have changed the gulp pipeline to use ESM and was able to update all dependencies to their latest versions.

I want to leave my code here for anyone who's interested in doing the same, too.

I followed this guide.

1. Update packages

Updated package.json:

{
  "devDependencies": {
    "get-google-fonts": "^1.2.2",
    "gulp": "^4.0.2",
    "gulp-clean-css": "^4.3.0",
    "gulp-imagemin": "^8.0.0",
    "gulp-sass": "^5.1.0",
    "sass": "^1.64.1"
  }
}

2. Update gulp to use ESM

Change the file endings of all gulp files to .mjs:

  • gulp-tasks/fonts.mjs
  • gulp-tasks/images.mjs
  • gulp-tasks/sass.mjs
  • gulpfile.mjs

3. Change syntax

gulpfile.mjs:

import gulp from "gulp";
const { parallel, watch: gulpWatch } = gulp;

// Pull in each task
import fonts from "./gulp-tasks/fonts.mjs";
import images from "./gulp-tasks/images.mjs";
import sass from "./gulp-tasks/sass.mjs";

// Set each directory and contents that we want to watch and
// assign the relevant task. `ignoreInitial` set to true will
// prevent the task being run when we run `gulp watch`, but it
// will run when a file changes.
const watcher = () => {
  gulpWatch("./src/images/**/*", { ignoreInitial: true }, images);
  gulpWatch("./src/scss/**/*.scss", { ignoreInitial: true }, sass);
};

// The default (if someone just runs `gulp`) is to run each task in parallel
export default parallel(fonts, images, sass);

// This is our watcher task that instructs gulp to watch directories and
// act accordingly
export const watch = watcher;

gulp-tasks/fonts.mjs:

import GetGoogleFonts from "get-google-fonts";

const fonts = async () => {
  // Setup of the library instance by setting where we want
  // the output to go. CSS is relative to output font directory
  const instance = new GetGoogleFonts({
    outputDir: "./dist/fonts",
    cssFile: "./fonts.css",
  });

  // Grabs fonts and CSS from google and puts in the dist folder
  const result = await instance.download(
        'https://fonts.googleapis.com/css2?family=Literata:ital,wght@0,400;0,700;1,400&family=Red+Hat+Display:wght@400;900'
  );

  return result;
};

export default fonts;

gulp-tasks/images.mjs:

import gulp from "gulp";
import imagemin, { mozjpeg, optipng } from "gulp-imagemin";

// Grabs all images, runs them through imagemin
// and plops them in the dist folder
const images = () => {
  // We have specific configs for jpeg and png files to try
  // to really pull down asset sizes
  return gulp
    .src("./src/assets/images/**/*")
    .pipe(
      imagemin(
        [
          mozjpeg({ quality: 60, progressive: true }),
          optipng({ optimizationLevel: 5, interlaced: null }),
        ],
        {
          silent: true,
        },
      ),
    )
    .pipe(gulp.dest("./dist/assets/images"));
};

export default images;

gulp-tasks/sass.mjs:

import gulp from "gulp";
import cleanCSS from "gulp-clean-css";
import * as dartSass from "sass";
import gulpSass from "gulp-sass";
const sassProcessor = gulpSass(dartSass);

// Flags whether we compress the output etc
const isProduction = process.env.NODE_ENV === 'production';

// An array of outputs that should be sent over to includes
const criticalStyles = ['critical.scss', 'home.scss', 'page.scss', 'work-item.scss'];

// Takes the arguments passed by `dest` and determines where the output file goes
const calculateOutput = ({history}) => {
  // By default, we want a CSS file in our dist directory, so the
  // HTML can grab it with a <link />
  let response = './dist/css';

  // Get everything after the last slash
  const sourceFileName = /[^(/|\\)]*$/.exec(history[0])[0];

  // If this is critical CSS though, we want it to go
  // to the _includes directory, so nunjucks can include it
  // directly in a <style>
  if (criticalStyles.includes(sourceFileName)) {
    response = './src/_includes/css';
  }

  return response;
};

// The main Sass method grabs all root Sass files,
// processes them, then sends them to the output calculator
const sass = () => {
  return gulp
    .src("./src/scss/*.scss")
    .pipe(sassProcessor().on("error", sassProcessor.logError))
    .pipe(
      cleanCSS(
        __prod__
          ? {
              level: 2,
            }
          : {},
      ),
    )
    .pipe(gulp.dest(calculateOutput, { sourceMaps: !__prod__ }));
};

export default sass;