From 16cdbe9db4d4ad8eec2cd6103376d9c0d57d0fa3 Mon Sep 17 00:00:00 2001 From: Amy Date: Thu, 14 Oct 2021 23:59:45 -0400 Subject: [PATCH] Add image resizing using image-size --- package-lock.json | 31 +++++++++++++++++++++++++++++-- package.json | 2 ++ scripts/optimize-images.ts | 27 ++++++++++++++++++++++++--- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2ed85d03..4060220a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "@next/mdx": "11.0.1", "@squoosh/lib": "^0.4.0", "date-fns": "^2.11.1", - "fs-extra": "^10.0.0", "next": "11.0.1", "next-mdx-remote": "3.0.4", "prettier": "^2.3.0", @@ -23,6 +22,7 @@ }, "devDependencies": { "@types/fs-extra": "^9.0.13", + "@types/image-size": "^0.8.0", "@types/mdx-js__react": "^1.5.3", "@types/node": "^16.9.1", "@types/react": "^17.0.14", @@ -34,8 +34,10 @@ "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-react": "7.24.0", "eslint-plugin-react-hooks": "^4.2.0", + "fs-extra": "^10.0.0", "gray-matter": "^4.0.3", "ical-generator": "^3.0.0", + "image-size": "^1.0.0", "postcss": "^8.3.0", "postcss-calc": "^8.0.0", "postcss-flexbugs-fixes": "^5.0.2", @@ -1045,6 +1047,16 @@ "@types/unist": "*" } }, + "node_modules/@types/image-size": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@types/image-size/-/image-size-0.8.0.tgz", + "integrity": "sha512-hMlhu25ji75dXQk2uZkN3pTJ+lWrgKr8M1fTpyyFvuu+SJZBdGa5gDm4BVNobWXHZbOU11mBj0vciYp7qOfAFg==", + "deprecated": "This is a stub types definition. image-size provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "image-size": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.8", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", @@ -3529,6 +3541,7 @@ "version": "10.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -4581,6 +4594,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, "dependencies": { "universalify": "^2.0.0" }, @@ -9006,6 +9020,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, "engines": { "node": ">= 10.0.0" } @@ -10162,6 +10177,15 @@ "@types/unist": "*" } }, + "@types/image-size": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@types/image-size/-/image-size-0.8.0.tgz", + "integrity": "sha512-hMlhu25ji75dXQk2uZkN3pTJ+lWrgKr8M1fTpyyFvuu+SJZBdGa5gDm4BVNobWXHZbOU11mBj0vciYp7qOfAFg==", + "dev": true, + "requires": { + "image-size": "*" + } + }, "@types/json-schema": { "version": "7.0.8", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", @@ -12043,6 +12067,7 @@ "version": "10.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -12736,6 +12761,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, "requires": { "graceful-fs": "^4.1.6", "universalify": "^2.0.0" @@ -16069,7 +16095,8 @@ "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true }, "unpipe": { "version": "1.0.0", diff --git a/package.json b/package.json index e4873513..3112ee4a 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ }, "devDependencies": { "@types/fs-extra": "^9.0.13", + "@types/image-size": "^0.8.0", "@types/mdx-js__react": "^1.5.3", "@types/node": "^16.9.1", "@types/react": "^17.0.14", @@ -46,6 +47,7 @@ "fs-extra": "^10.0.0", "gray-matter": "^4.0.3", "ical-generator": "^3.0.0", + "image-size": "^1.0.0", "postcss": "^8.3.0", "postcss-calc": "^8.0.0", "postcss-flexbugs-fixes": "^5.0.2", diff --git a/scripts/optimize-images.ts b/scripts/optimize-images.ts index dadf9f98..5bd005fc 100644 --- a/scripts/optimize-images.ts +++ b/scripts/optimize-images.ts @@ -13,14 +13,17 @@ import path from "path"; // @ts-ignore import { ImagePool } from "@squoosh/lib"; import fse from "fs-extra"; +import { default as getImageDimensions } from "image-size"; const IMAGES_SOURCE_DIRECTORY = "images"; const IMAGES_DESTINATION_DIRECTORY = "public/images"; void optimizeImages(); +const IMAGE_MINIMUM_SIZE = 300; + const IMAGE_ENCODE_OPTIONS = { mozjpeg: {} }; -const GET_ENCODER_FROM_EXTENSION: { [imageExtension: string]: string } = { +const GET_CODEC_FROM_EXTENSION: { [imageExtension: string]: string } = { jpg: "mozjpeg", jpeg: "mozjpeg", }; @@ -40,19 +43,37 @@ export async function optimizeImages() { ); const fileExtension = imagePath.split(".").pop() ?? ""; - if (!GET_ENCODER_FROM_EXTENSION[fileExtension]) { + if (!GET_CODEC_FROM_EXTENSION[fileExtension]) { await fse.copy(sourcePath, destinationPath); return; } const rawImageFile = await fse.readFile(sourcePath); const ingestedImage = imagePool.ingestImage(rawImageFile); + const { width, height } = getImageDimensions(rawImageFile); await ingestedImage.decoded; + + if (width && height) { + const resizeEnabled = + width > IMAGE_MINIMUM_SIZE && height > IMAGE_MINIMUM_SIZE; + const smallerDimension = width < height ? "width" : "height"; + + // specifying only one dimension maintains the aspect ratio + const preprocessOptions = { + resize: { + enabled: resizeEnabled, + [smallerDimension]: IMAGE_MINIMUM_SIZE, + }, + }; + + await ingestedImage.preprocess(preprocessOptions); + } + await ingestedImage.encode(IMAGE_ENCODE_OPTIONS); const encodedImage = await ingestedImage.encodedWith[ - GET_ENCODER_FROM_EXTENSION[fileExtension] + GET_CODEC_FROM_EXTENSION[fileExtension] ]; await fse.outputFile(destinationPath, encodedImage.binary); })