loading...
Cover image for Optimizt — CLI image optimization tool for frontend devs

Optimizt — CLI image optimization tool for frontend devs

igoradamenko profile image Igor Adamenko ・5 min read

As frontend developers we have to care about pictures: compress PNG & JPEG, remove useless parts of SVG, create WebP for modern browsers, etc. On my everyday work we use several tools to do it: TinyPNG, Squoosh.app, SVGO, etc. Every developer in my team has their own bookmarked set of tools in browser, and sometimes image optimization is a bit tedious: drag this to one app, drag that to another, check this checkbox, remove that, etc.

About 6 months ago we've built a small CLI tool that does everything we need:

  1. Optimizes PNG, JPEG, GIF using imagemin, lossily or losslessly.

  2. Compresses SVG using SVGO (with saving files readability).

  3. Creates WebP versions for raster images.

And of course it does everything on the local machine, fully offline. Which is great because we've integrated it with our editors and now run the tool by hitting a shortcut.

Getting Started

Simply install the tool globally using npm:

npm i -g @funboxteam/optimizt

Now you're ready to optimize! Feel free to check the tool help by running optimizt --help or look at the repo description to get to know the options.

Examples!

Here's how it works for us now.

Let's say we're building landing page in React app using BEM methodology, SCSS & JSX. The whole page is a one big component, just because we want to load it separately using React.lazy.

Folder structure looks like this
…/src/app/views/landing
❯ tree 
.
├── __background
│   ├── landing__background--desktop.png
│   ├── landing__background--mobile.png
│   ├── landing__background.scss
│   ├── landing__background@2x--desktop.png
│   └── landing__background@2x--mobile.png
├── __column
│   └── landing__column.scss
├── __description
│   └── landing__description.scss
├── __headline
│   └── landing__headline.scss
├── __price
│   └── landing-capabilities__price.scss
├── __section
│   ├── _type
│   │   ├── _apps
│   │   │   ├── landing__section_type_apps.jpg
│   │   │   └── landing__section_type_apps@2x.jpg
│   │   ├── _device
│   │   │   ├── landing__section_type_device.jpg
│   │   │   └── landing__section_type_device@2x.jpg
│   │   ├── _map
│   │   │   ├── landing__section_type_map.jpg
│   │   │   └── landing__section_type_map@2x.jpg
│   │   ├── _notifications
│   │   │   ├── landing__section_type_notifications.jpg
│   │   │   └── landing__section_type_notifications@2x.jpg
│   │   ├── _pricing
│   │   │   ├── landing__section_type_pricing.jpg
│   │   │   └── landing__section_type_pricing@2x.jpg
│   │   └── _unique-features
│   │       ├── landing__section_type_unique-features.jpg
│   │       └── landing__section_type_unique-features@2x.jpg
│   └── landing__section.scss
├── __store-badge
│   ├── _type
│   │   ├── _apple
│   │   │   ├── landing__store-badge_type_apple.scss
│   │   │   └── landing__store-badge_type_apple.svg
│   │   └── _google
│   │       ├── landing__store-badge_type_google.png
│   │       └── landing__store-badge_type_google.scss
│   ├── landing__store-badge.jsx
│   └── landing__store-badge.scss
├── __title
│   ├── landing__title.scss
│   └── landing__title.svg
├── index.js
├── landing.jsx
└── landing.scss

18 directories, 33 files

There're lots of different images, and we want to:

  1. Optimize every SVG & PNG file, surely.
  2. Create WebP versions for the images of the background element, to try save a few bytes for users with modern browsers.
  3. Optimize JPEG images for section lossily, because they're not too big in terms of width & height and artifacts won't be visible for user.

We've set Optimizt as External Tool for WebStorm as described in the repo, so all these optimizations will take a couple of clicks!

First, let's run lossless optimization on the root folder:

Screen Shot 2020-10-10 at 12.05.52

Here's what we've got:

optimizt --lossless /project/src/app/views/landing
- Processing. Please wait...
- Optimizing 19 images (lossless)...
✔ src/app/views/landing/__section/_type/_apps/landing__section_type_apps.jpg 
   11.214 KB → 6.003 KB. Ratio: -46%
✔ src/app/views/landing/__section/_type/_apps/landing__section_type_apps@2x.jpg 
   24.946 KB → 13.134 KB. Ratio: -47%
✔ src/app/views/landing/__section/_type/_device/landing__section_type_device.jpg 
   6.897 KB → 3.732 KB. Ratio: -46%
✔ src/app/views/landing/__section/_type/_device/landing__section_type_device@2x.jpg 
   14.033 KB → 7.1 KB. Ratio: -49%
✔ src/app/views/landing/__section/_type/_map/landing__section_type_map.jpg 
   18.182 KB → 9.736 KB. Ratio: -46%
✔ src/app/views/landing/__section/_type/_map/landing__section_type_map@2x.jpg 
   51.131 KB → 28.637 KB. Ratio: -44%
✔ src/app/views/landing/__section/_type/_notifications/landing__section_type_notifications.jpg 
   9.63 KB → 5.141 KB. Ratio: -47%
✔ src/app/views/landing/__section/_type/_notifications/landing__section_type_notifications@2x.jpg 
   22.125 KB → 10.537 KB. Ratio: -52%
✔ src/app/views/landing/__section/_type/_pricing/landing__section_type_pricing.jpg 
   11.752 KB → 6.605 KB. Ratio: -44%
✔ src/app/views/landing/__section/_type/_pricing/landing__section_type_pricing@2x.jpg 
   25.202 KB → 14.3 KB. Ratio: -43%
✔ src/app/views/landing/__section/_type/_unique-features/landing__section_type_unique-features.jpg 
   7.719 KB → 3.556 KB. Ratio: -54%
✔ src/app/views/landing/__section/_type/_unique-features/landing__section_type_unique-features@2x.jpg 
   21.723 KB → 10.475 KB. Ratio: -52%
✔ src/app/views/landing/__background/landing__background--desktop.png 
   189.406 KB → 102.371 KB. Ratio: -46%
✔ src/app/views/landing/__background/landing__background--mobile.png 
   64.264 KB → 33.865 KB. Ratio: -47%
✔ src/app/views/landing/__background/landing__background@2x--desktop.png 
   678.988 KB → 384.898 KB. Ratio: -43%
✔ src/app/views/landing/__background/landing__background@2x--mobile.png 
   224.362 KB → 123.186 KB. Ratio: -45%
✔ src/app/views/landing/__title/landing__title.svg 
   7.172 KB → 3.834 KB. Ratio: -47%
✔ src/app/views/landing/__store-badge/_type/_apple/landing__store-badge_type_apple.svg 
   16.331 KB → 10.106 KB. Ratio: -38%
✔ src/app/views/landing/__store-badge/_type/_google/landing__store-badge_type_google.png 
   12.951 KB → 4.557 KB. Ratio: -65%
✔ Optimizing completed
  Done!

A screenshot of this output in WebStorm UI
Screen Shot 2020-10-10 at 12.08.47

Next, let's optimize images for section element lossily. Clicks in the editor UI are the same, so there's no screenshot, we're jumping right to the output:

optimizt /project/src/app/views/landing/__section
- Processing. Please wait...
- Optimizing 12 images (lossy)...
✔ src/app/views/landing/__section/_type/_apps/landing__section_type_apps.jpg 
   6.003 KB → 5.501 KB. Ratio: -8%
✔ src/app/views/landing/__section/_type/_apps/landing__section_type_apps@2x.jpg 
   13.134 KB → 11.932 KB. Ratio: -9%
✔ src/app/views/landing/__section/_type/_device/landing__section_type_device.jpg 
   3.732 KB → 3.646 KB. Ratio: -2%
✔ src/app/views/landing/__section/_type/_device/landing__section_type_device@2x.jpg 
   7.1 KB → 7.013 KB. Ratio: -1%
✔ src/app/views/landing/__section/_type/_map/landing__section_type_map.jpg 
   9.736 KB → 8.296 KB. Ratio: -15%
✔ src/app/views/landing/__section/_type/_map/landing__section_type_map@2x.jpg 
   28.637 KB → 23.157 KB. Ratio: -19%
✔ src/app/views/landing/__section/_type/_notifications/landing__section_type_notifications.jpg 
   5.141 KB → 4.986 KB. Ratio: -3%
✔ src/app/views/landing/__section/_type/_notifications/landing__section_type_notifications@2x.jpg 
   10.537 KB → 10.052 KB. Ratio: -5%
✔ src/app/views/landing/__section/_type/_pricing/landing__section_type_pricing.jpg 
   6.605 KB → 5.959 KB. Ratio: -10%
✔ src/app/views/landing/__section/_type/_pricing/landing__section_type_pricing@2x.jpg 
   14.3 KB → 12.519 KB. Ratio: -12%
✔ Optimizing completed
  Done!

Finally, let's create WebP for background element images:

optimizt --webp /project/src/app/views/landing/__background
- Processing. Please wait...
- Creating WebP for 4 images...
✔ src/app/views/landing/__background/landing__background--desktop.webp 
   102.371 KB → 33.195 KB. Ratio: -68%
✔ src/app/views/landing/__background/landing__background--mobile.webp 
   33.865 KB → 13.658 KB. Ratio: -60%
✔ src/app/views/landing/__background/landing__background@2x--desktop.webp 
   384.898 KB → 96.453 KB. Ratio: -75%
✔ src/app/views/landing/__background/landing__background@2x--mobile.webp 
   123.186 KB → 37.834 KB. Ratio: -69%
✔ Creating WebP completed
  Done!

Cool! Let's see what we've just done here:

  1. We've prepared all the graphics for our landing page in... ten seconds? Including every image compression and WebP creation.

  2. We've saved around 1 MB of traffic for our users by 52% compression of different assets in total.

And we've done everything right from our editor! But we could have done the same easily from the CLI too 👌

Hope you find the tool useful for your development routines. Glad to hear any suggestions about the possible improvement! 🐨

P. S.: If you know how to integrate Optimizt with your editor (Sublime Text, VSCode, Atom, Vim, etc) to make it work similar to the example above (call by firing an action on a folder or file in the project tree), feel free to make a PR to describe it in the README. We will appreciate that!

GitHub logo funbox / optimizt

CLI image optimization tool

@funboxteam/optimizt

Optimizt avatar: OK sign with Mona Lisa picture between the fingers

npm

Optimizt is a CLI tool that helps you prepare images during frontend development.

It can compress PNG, JPEG, GIF and SVG lossy and lossless and create WebP versions for raster images.

По-русски

Rationale

As frontend developers we have to care about pictures: compress PNG & JPEG, remove useless parts of SVG create WebP for modern browsers, etc. One day we got tired of using a bunch of apps for that and created one tool that does everything we want.

Usage

Install the tool:

npm i -g @funboxteam/optimizt

Optimize!

optimizt path/to/picture.jpg

Command line flags

  • --webp — create WebP versions for the passed paths instead of compressing them.
  • -l, --lossless — optimize losslessly instead of lossily.
  • -v, --verbose — show additional info, e.g. skipped files.
  • -V, --version — show tool version.
  • -h, --help — show help.

Examples

# one image optimization
optimizt path/to/picture.jpg
# list of images optimization losslessly
optimizt --lossless

Discussion

pic
Editor guide