npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

lightspeed-image-loader

v0.0.8

Published

webpack loader for optimized, responsive images. Works with React, Vue, and all frontend setups.

Downloads

6

Readme

lightspeed-image-loader latest version Dependencies status devDependencies status

Lightspeed Image Loader

Lightspeed Image Loader

On-the-fly responsive image resizing and minification for webpack v4. Uses mozjpeg, Gifsicle, OptiPNG, and SVGO, supports WebP, and can even generate Medium.com-style low-quality image placeholders (LQIP) for loading.

Support

| Filetype | Resizing | Optimization | Converting to | | :------- | :------: | :----------: | :-----------: | | JPG | ✅ | ✅ | ✅ | | PNG | ✅ | ⚠️ SLOW | ⚠️ SLOW | | WebP | ✅ | ✅ | ✅ | | SVG | N/A | ✅ | N/A | | GIF | 🚫 | ✅ | 🚫 |

Note: GIF resizing/conversion isn’t supported due to lack of support in sharp. Overall, it’s a small price to pay for the build speed of the sharp library.

Installation

npm i --save-dev lightspeed-image-loader

Usage

Simple usage

In your production webpack config, add the following:

module: {
  rules: [
    {
      test: /\.(jpe?g|gif|png|svg)/i,
      use: 'lightspeed-image-loader'
    }
  ],
},

Then from your app, import image files normally. Specify specific optimizations per each file:

import imgSmall from './img/background-full.jpg?w=600&q=75'; /* 600px wide, 75% quality */
import imgLarge from './img/background-full.jpg?w=1200&q=50'; /* 1200px wide, 50% quality */

React

<img src={imgSmall} srcset={`${imgSmall} 600w, ${imgLarge} 1200w`} />

Vue

<img :src="imgSmall" :srcset="`${imgSmall} 600w, ${imgLarge} 1200w`">

Styled Components

const Header = styled.header`
  background-image: ${imgSmall};

  @media (min-width: 600px) {
    background-image: ${imgLarge};
  }
`;

Examples

Responsive (React)

import small from './myimage.jpg?w=600&q=80';
import medium from './myimage.jpg?w=1200&q=75';
import large from './myimage.jpg?w=1800&q=65';

..

<img
  srcset={`${medium} 1200w, ${large} 1800w`}
  src={small}
  alt="image description"
/>

WebP (React)

import webP from './myimage.jpg?f=webp';
import fallback from './myimage.jpg';

...

<picture>
  <source srcset={webP} type="image/webp" />
  <source srcset={fallback} type="image/jpeg" />
  <img src={fallback} alt="image description" />
</picture>

Base64 inlined image (Styled Components)

import inlineBg from './myimage.jpg?inline';

...

const Wrapper = styled.div`
  background-image: url(${inlineBg});
`;

Inline SVG (React)

import inlineSVG from './myimage.svg?inline';

...

<div dangerouslySetInnerHtml={{ __html: inlineSVG }} />

Resizing pixel art

import pixelArt from './pixel-art?w=2048&interpolation=nearest';

Blurry image placeholder while image loads (React)

import image from './myimage.jpg?w=1200';
import placeholder from './myimage.jpg?placeholder';

<div style={{ backgroundImage: `url(${placeholder}), backgroundSize: 'cover'` }}>
  <img src={image} />
</div>;

Due to the nature of SVG the placeholder will be small, but it will preserve its aspect ratio if used in an <img> tag and is made to be expanded. Either use width: 100%; height: auto to fill the area, or background-size to make it larger.

An SVG placeholder is used to avoid that white fuzzy border caused by CSS’ blur filter on normal images.

Note: placeholders can’t be generated for SVGs

Options

Specifying options per-image is the preferred method of this loader. By setting options per-file, you can fine-tune each image to find the best balance of quality and compression. Plus, you don’t have to touch your webpack config as your images change.

Query Options

| Name | Default | Description | | :-------------- | :--------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | width | (original) | Set image width (in pixels). Leave height blank to auto-scale. Specify width and height to ensure image is smaller than both. | | w | | Shortcut for width. | | height | (original) | Scale image height (in pixels). Leave width blank to auto-scale. Specify width and height to ensure image is smaller than both. | | h | | Shortcut for height. | | quality | 70 | Specify 1100 to set the image’s quality*. For each image, set it as low as possible before compression is noticeable at display size. | | q | | Shortcut for quality. | | interpolation | 'cubic' | When scaling, specify 'nearest' for nearest-neighbor (pixel art), 'cubic' for cubic interpolation, or 'lanczos2' or 'lanczos3' for Lanczos with a=2 or a=3. 'cubic' is this loader’s default (because it’s what most are used to), as opposed to'lanczos3' which is sharp’s default (present for other loaders) | | inline | false | Set to ?inline or ?inline=true to return the individual image in base64 data URI, or raw SVG code 🎉. | | format | (same) | Specify jpg, webp, or png to convert format from the original. | | f | | Shortcut for format. | | placeholder | false | Specify ?placeholder to return a low-quality image placeholder (technically this can be used alongside other options, but it’s not advised). | | skip | false | Set to ?skip to bypass resizing & optimization entirely. This is particularly useful for SVGs that don’t optimize well. |

* Note: GIFsicle and OptiPNG don’t use a 1–100 quality scale, so quality will convert for you. However, if using loader options below, you’ll need to specify the proper options there.

Example

import myImage from './large.jpg?q=50&w=1200&f=webp'; // Convert to WebP, 50% quality, and 1200px wide

Note: this loader will not upscale images because it increases file size without improving image quality. If you need to upscale pixel art, do it in CSS with image-rendering: crisp-edges.

Loader options

The main advantage of this loader is being able to specify quality and width inline, but there are some settings which make sense to set globally, such as SVGO settings, or a fallback quality. In these cases, pass options to the loader as usual:

| Name | Default | Description | | :----------- | :------------------ | :-------------------------------------------------------------------------------------------------- | | outputPath | output.path | Override webpack’s default output path for these images (setting from file-loader). | | publicPath | output.publicPath | Override webpack’s default output path for these images (setting from file-loader). | | emitFile | true | Set to false to skip processing file (setting from file-loader). | | gifsicle | (object) | Specify Gifsicle options (view options). | | mozjpeg | (object) | Specify mozjpeg options (view options). | | optipng | (object) | Specify OptiPNG options (view options). | | pngquant | (object) | Specify PNGquant options (view options). | | svgo | (object) | Specify SVGO options. |

Note: because this loader passes images on to file-loader, you should be able to use any of its options within this config. However, don’t use this loader for anything other than images!

Example

module: {
  rules: [
    {
      test: /(jpe?g|gif|png|svg)$/i,
      use: {
        loader: 'lightspeed-image-loader',
        options: {
          mozjpeg: {
            quality: 60, // 1 – 100, higher is heavier
          },
          optipng: {
            optimizationLevel: 5, // 0 = light; 7 = heavy compression
          },
          svgo: {
            addClassesToSVGElement: true,
            mergePaths: true,
            removeStyleElement: true,
          },
          webp: {
            quality: 80,
          },
        },
      },
    },
  ],
},

WebP

Because WebP currently is only supported by Chrome, you’ll still need to configure fallbacks. For that reason, you can only convert per-file:

import webP from './original.jpg?f=webp';
import fallback from './original.jpg';

For tips on using WebP effectively, read this CSS Tricks article.

Troubleshooting

If python --version returns ^3 on your system, you’ll likely encounter the frequently-discussed node-gyp error:

Error: Python executable \"/usr/local/bin/python\" is v3.x.x, which is not supported by gyp.

If which python2.7 works on your system, run npm config set python python2.7 (or yarn config set python python2.7 if using yarn).

If your machine doesn’t have python2.7, install Python 2.x using Homebrew or some other means, and set that executable with npm config set python /path/to/python2 or yarn config set python /path/to/python2

FAQ

Why do I have to use one import per size?

There are several advantages to this method:

  • Control: You can declare options per-size, and fix issues where a particular image size requires different settings.
  • Speed: Specifying options per-file keeps the loader fast by only applying operations you specify (e.g., a placeholder image isn’t needlessly generated if you don’t specify one—this can severely slow down build times with many images)
  • Simplicity: There’s no syntax to memorize; one reference = one image URL or data-URI

Why doesn’t this loader chain nicely with others?

Two reasons: first, image optimization / resizing has a particular order that needs to be kept: resizing first, then optimization. Always. If there’s only one proper order for images, and if one loader does it all, why chain?

Second, and more importantly, webpack doesn’t make it easy to handle the same file extension in different ways. This makes sense for, say, JS, but less so for images. This loader prioritizes practical image handling over webpack’s loader philosophy, allowing you to take the same file extension and serve it multiple different ways depending on the need.

LQIP (placeholder images) aren’t showing!

The placeholder SVGS are compressed further by mini-svg-data-uri, which requires double quotes for <img src="[placeholder]" /> and background-image: url("[placeholder]"). Check to make sure your code is outputting double quotes in HTML/CSS.

The tradeoff is much smaller bundles, and better GZIP performance without sacrificing browser support.

Special Thanks

This loader wouldn’t be possible without the significant achievements of: