OptimusIMG is a Node.js module for optimising images in build and runtime. It helps you detect which images need further optimisation during your web application build process and uses optimisation tricks for a faster and better user experience during runtime.
OptimusIMG runtime library has no JavaScript dependencies, it can run in any SPA (Angular, React, Vue, ...) or any classic webpage environment.
The source is written in Typescript, while the dist
and build
files are compiled to plain JS (ES5).
npm install --save optimusimg
node >= 8
and npm >= 5.2.8
. It is possible to use npm < 5.2.8
but you will need to install additional global npm packages (eg. npx
).
OptimusIMG is supported in all major browsers which support ES5 (IE >= 10
, Chrome >= 23
, Firefox >= 21
, Edge
, Safari >= 6
, Opera >= 15
)
Once you add OptimusIMG to your project (npm, submodule, or, when using only runtime optimisations, by linking minified js file for a specific version - https://unpkg.com/optimusimg@:version/dist/OptimusIMG.min.js, or for latest version - https://unpkg.com/optimusimg/dist/OptimusIMG.min.js), you can use OptimusIMG's functions for optimisation.
OptimusIMG currently has three runtime branches - HtmlElementsCheck
, LazyLoad
and ProgressiveLoad
. It also exposes some image helpers.
HtmlElementsCheck
will output console warnings if it detects any images with the proper class which are not properly prepared for responsive development.
You can configure HtmlElementsCheck
function with the following options:
enableConsoleOutput?: boolean; // defaults to true
className?: string; // defaults to 'optimusIMG', will take only images with this class in account
LazyLoad
is responsible for lazily loading images and carousels. You can configure LazyLoad
with the following options:
className?: string; // defaults to 'optimusIMG', will lazily-load all images with this class
carouselClassName?: string; // defaults to 'optimusIMG-carousel', will lazily-load all carousels with this class
carouselToggleImageBtn?: string; // defaults to 'optimusIMG-carousel--toggle-btn', you MUST add this class to all potential buttons which can toggle images of your carousel
To ensure LazyLoad
works properly, you will have to:
- change
src
(orsrcset
, or both) property of images withclassName
into adata-optimus-lazy-src
(or intodata-optimus-lazy-srcset
, in case you are usingsrcset
), eg: change<img src="foo" srcset="bar" class="optimusIMG">
into<img data-optimus-lazy-src="foo" data-optimus-lazy-srcset="bar" class="optimusIMG">
- add
data-optimus-interval
attribute to all carousels which have thecarouselClassName
. The value of thedata-optimus-interval
should be a number in milliseconds, greater than1000
. If your carousel automatically switches images based on a set time interval, thedata-optimus-interval
should match that interval - add
data-optimus-img-index
to all carousel toggle image buttons which have thecarouselToggleImageBtn
class. Allowed values are:next
,previous
(for next/previous buttons) or any image index, eg5
, for buttons which allow the user to directly toggle to that specific image.
It is strongly advised you use the LazyLoad
functionality, which will also make use of the ProgressiveLoad
functionality automatically (in case any of the images that are lazily loaded is of OptimusIMG progressive image variant).
ProgressiveLoad
is responsible for progressively loading images. It works in conjunction with prepare-progressive-images
buildtime function which generates images to be used for progressive loading (see details in the buildtime section).
ProgressiveLoad
is not configurable.
To ensure ProgressiveLoad
works properly, you will have to:
- generate progressive images using
npx prepare-progressive-images
(see details in buildtime section) or generate your own versions of low resolution images and provide a high-resolution image URL asdata-optimus-high-res-src
(or asdata-optimus-high-res-srcset
) image data property - if you are using the OptimusIMG
LazyLoad
function- change
data-optimus-lazy-src
(ordata-optimus-lazy-srcset
, or both) from eg./images/foobar.jpeg
to the (generated withnpx prepare-progressive-images
) progressive image version path/images/foobar-OptimusIMG-progressive.jpeg
, OptimusIMG will then handle the progressive load functionality under the hood automatically both for single images and carousels which are lazily loaded
- change
- else
- change
src
(orsrcset
, or both) from eg./images/foobar.jpeg
to the (generated withnpx prepare-progressive-images
) progressive image version path/images/foobar-OptimusIMG-progressive.jpeg
- manually trigger
OptimusIMG.ProgressiveLoad.execute()
function whenever you load new images into view (eg. carousel image change event for carousels which are not utilizing OptimusIMGLazyLoad
functionality, on document ready and ajax responses which load new images in case you are utilizing jQuery for that, on component init/mount/etc lifecycle event in case you are using eg. Angular, Vue.js, ReactJS, ..)
- change
ProgressiveLoad
utilizes CSS transitions to ensure a performant and easy on the eyes transition from the generated progressive image variant (which is used for ensuring as quick as possible initial webpage load),
to the high quality original image variant as soon as the original variant is loaded.
You can trigger re-run of any OptimusIMG function. This is useful in case you do not with to duplicate your configuration. like this (example in turbolinks, jQuery and Typescript app, custom configuration):
// Triggers the LazyLoad for the first time
const LAZY_LOAD: LazyLoad = OptimusIMG.LazyLoad(customConfiguration);
...
$(document).on('turbolinks:load', () => {
// Triggers LazyLoad after every turbolinks load
LAZY_LOAD.execute();
});
Or like this (example for vanilla JS, default configuration)
// Triggers the LazyLoad for the first time
var LAZY_LOAD = OptimusIMG.LazyLoad();
...
function loadPartial() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("partial-container").innerHTML = this.responseText;
// Triggers the LazyLoad in response to eg. ajax function response
LAZY_LOAD.execute(); // Considering there is no custom configuration, you could easily do OptimusIMG.LazyLoad(); as well
}
};
xhttp.open("GET", "some-partial.html", true);
xhttp.send();
}
Please note: ProgressiveLoad
is an exception - in case you wish to trigger ProgressiveLoad
manually, you will only be able to trigger it by calling the .execute()
method,
eg. OptimusIMG.ProgressiveLoad.execute()
, calling OptimusIMG.ProgressiveLoad()
will not trigger the progressive load functionality.
The following will trigger lazy loading after a component is mounted.
import { RUNTIME as OptimusIMG } from 'optimusimg/build/runtime/index.js';
...
componentDidMount() {
...
OptimusIMG.LazyLoad(configuration?: ILazyLoad);
}
...
The following will trigger lazy loading after eg. a CarouselComponent
is mounted.
import { Component, OnInit } from '@angular/core';
import LazyLoad from 'optimusimg/src/runtime/lazy_load';
@Component({
selector: 'app-carousel',
templateUrl: './carousel.component.html',
styleUrls: ['./carousel.component.scss']
})
export class CarouselComponent implements OnInit {
constructor() {}
ngOnInit() {
new LazyLoad();
}
...
}
<script src="https://unpkg.com/optimusimg@2.3.0/dist/OptimusIMG.min.js"></script>
<script>
...
// Triggers lazy load
OptimusIMG.LazyLoad();
// Triggers html elements check
OptimusIMG.HtmlElementsCheck();
// Triggers progressive load
OptimusIMG.ProgressiveLoad.execute();
</script>
OptimusIMG has some image helpers available for use, such as loading image in background with JS. To use the helper functions, you need to import the helper
The helper function loads image in the background and returns a promise. The promise will resolve when the image is loaded, or reject when the image cannot be loaded. You can use it eg. to pre-load an image in JS (as, by default, most browsers will cache the image) before eg. injecting the image in the view.
import { loadImageInBackground } from 'optimusimg/build/runtime/helpers';
...
loadImageInBackground('url-of-the-image-you-wish-to-load')
...
OptimusIMG comes with buildtime scripts. For example, OptimusIMG will prepare a progressive version of your images
which will be used for speeding up the initial load and will, in combination with runtime ProgressiveImages
function,
automatically load the high-res (original) version of your image and swap the images once the high-res version is loaded.
OptimusIMG also has an image analysis buildtime function which will warn you in case it detects possible optimisations for specific images.
To run buildtime functions, you need to npm install --save optimusimg
(if you haven't done so already) and then use npx function
(eg. npx prepare-progressive-images
):
npm@5.2.0
or higher (as it ships with npx). To find out which version of npm you are using, typenpm --version
- If you are running
npm < 5.2.0
and cannot upgrade, then you can donpm install -g npx
- If you are running
Prepare progressive images function supports images in .jpg
(or .jpeg
) and .png
formats / file extensions.
The function will make a copy of all images within the folder (and all subfolders) you specify and modify them to be used in runtime for progressive loading.
The images will be in the same formats as the originals and will differ from the original image by -OptimusIMG-progressive
extension.
The progressive image variants will, in conjunction with the runtime ProgressiveLoad
functionality, be used for ensuring
the initial load of the webpage is as quick as possible.
Please do not change the name of these images.
Analyse images function supports images in .jpg
(or .jpeg
) and .png
formats / file extensions.
The function will analyse all images within the folder (and all subfolders) you specify and let you know of possible optimisations.
Please note: in case you have a lot of (big) images in your project, the function might take a couple of minutes to finish analysis.
Clone, npm install
, code, lint, test, push and open a pull request.
I am only accepting PRs with a 100% code coverage.
To ensure commit messages follow the same pattern, please use npm run commit
instead of the standard git commit
and follow the commit instructions in the terminal.
OptimusIMG uses Jest for testing. To trigger tests - npm run test
OptimusIMG uses TSLint for linting. To trigger linting - npm run lint
OptimusIMG is licensed under the MIT license.