{"id":27106985,"url":"https://github.com/lukavarga/optimusimg","last_synced_at":"2025-04-06T20:19:35.097Z","repository":{"id":32916715,"uuid":"145474321","full_name":"lukaVarga/OptimusIMG","owner":"lukaVarga","description":"Optimises images for web","archived":false,"fork":false,"pushed_at":"2024-04-13T22:34:23.000Z","size":13837,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-04-14T12:18:50.539Z","etag":null,"topics":["image","image-analysis","image-optimisation","image-optimization","images","javascript","lazy-loading","progressive-image-loading","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lukaVarga.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-20T21:54:05.000Z","updated_at":"2024-06-19T02:09:36.798Z","dependencies_parsed_at":"2023-01-14T22:45:14.108Z","dependency_job_id":"eecf38ad-ea58-4044-8dc9-30e133101801","html_url":"https://github.com/lukaVarga/OptimusIMG","commit_stats":{"total_commits":132,"total_committers":4,"mean_commits":33.0,"dds":0.3787878787878788,"last_synced_commit":"843ac1dc394a123757ae9d6e7e8eac852caa11d9"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukaVarga%2FOptimusIMG","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukaVarga%2FOptimusIMG/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukaVarga%2FOptimusIMG/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukaVarga%2FOptimusIMG/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lukaVarga","download_url":"https://codeload.github.com/lukaVarga/OptimusIMG/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247543822,"owners_count":20955897,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["image","image-analysis","image-optimisation","image-optimization","images","javascript","lazy-loading","progressive-image-loading","typescript"],"created_at":"2025-04-06T20:19:34.417Z","updated_at":"2025-04-06T20:19:35.091Z","avatar_url":"https://github.com/lukaVarga.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Version Release](https://github.com/lukaVarga/OptimusIMG/actions/workflows/semantic-release.yml/badge.svg?style=for-the-badge)](https://github.com/lukaVarga/OptimusIMG/actions/workflows/semantic-release.yml)\n[![Tests](https://github.com/lukaVarga/OptimusIMG/actions/workflows/test-runner.yml/badge.svg)](https://github.com/lukaVarga/OptimusIMG/actions/workflows/test-runner.yml)\n[![Codecov coverage](https://img.shields.io/codecov/c/github/lukaVarga/OptimusIMG.svg?style=for-the-badge)](https://codecov.io/gh/lukaVarga/OptimusIMG)\n\n\n[![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/optimusimg.svg?style=for-the-badge)](https://bundlephobia.com/result?p=optimusimg)\n![GitHub issues](https://img.shields.io/github/issues/lukaVarga/OptimusIMG.svg?style=for-the-badge)\n![GitHub](https://img.shields.io/github/license/lukaVarga/OptimusIMG.svg?style=for-the-badge)\n\n![GitHub release](https://img.shields.io/github/release/lukaVarga/OptimusIMG.svg?style=for-the-badge)\n[![npm](https://img.shields.io/npm/v/optimusimg.svg?style=for-the-badge)](https://www.npmjs.com/package/optimusimg)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=for-the-badge)](https://github.com/semantic-release/semantic-release)\n\n# OptimusIMG\nOptimusIMG is a Node.js module for optimising images in build and runtime.\nIt helps you detect which images need further optimisation during your web application\nbuild process and uses optimisation tricks for a faster and better user experience\nduring runtime.\n\nOptimusIMG runtime library has no JavaScript dependencies, it can run in any SPA (Angular, React, Vue, ...) or any classic webpage environment.\nThe source is written in Typescript, while the `dist` and `build` files are compiled to plain JS (ES5).\n\n## Installation\n`npm install --save optimusimg`\n\n## Requirements\n`node \u003e= 8` and `npm \u003e= 5.2.8`. It is possible to use `npm \u003c 5.2.8` but you will need to install additional global npm packages (eg. `npx`).\n\n## Browser support\nOptimusIMG is supported in all major browsers which support ES5 (`IE \u003e= 10`, `Chrome \u003e= 23`, `Firefox \u003e= 21`, `Edge`, `Safari \u003e= 6`, `Opera \u003e= 15`)\n\n## Usage\nOnce you add OptimusIMG to your project (npm, submodule, or,\nwhen using only runtime optimisations, by linking minified js file for a specific version - https://unpkg.com/optimusimg@:version/dist/OptimusIMG.min.js,\nor for latest version - https://unpkg.com/optimusimg/dist/OptimusIMG.min.js),\nyou can use OptimusIMG's functions for optimisation.\n\n### Runtime useage\nOptimusIMG currently has three runtime branches - `HtmlElementsCheck`, `LazyLoad` and `ProgressiveLoad`. It also exposes some image helpers.\n\n#### HtmlElementsCheck\n`HtmlElementsCheck` will output console warnings if it detects any images with the proper class which are not properly prepared for responsive development.\nYou can configure `HtmlElementsCheck` function with the following options:\n```\nenableConsoleOutput?: boolean; // defaults to true\nclassName?: string; // defaults to 'optimusIMG', will take only images with this class in account\n```\n\n#### LazyLoad\n`LazyLoad` is responsible for lazily loading images and carousels. You can configure `LazyLoad` with the following options:\n```\nclassName?: string; // defaults to 'optimusIMG', will lazily-load all images with this class\ncarouselClassName?: string; // defaults to 'optimusIMG-carousel', will lazily-load all carousels with this class\ncarouselToggleImageBtn?: string; // defaults to 'optimusIMG-carousel--toggle-btn', you MUST add this class to all potential buttons which can toggle images of your carousel\n```\n\nTo ensure `LazyLoad` works properly, you will have to:\n- change `src` (or `srcset`, or both) property of images with `className` into a `data-optimus-lazy-src` (or into `data-optimus-lazy-srcset`, in case you are using `srcset`), eg: change `\u003cimg src=\"foo\" srcset=\"bar\" class=\"optimusIMG\"\u003e` into `\u003cimg data-optimus-lazy-src=\"foo\" data-optimus-lazy-srcset=\"bar\" class=\"optimusIMG\"\u003e`\n- add `data-optimus-interval` attribute to all carousels which have the `carouselClassName`. The value of the `data-optimus-interval` should be a number in milliseconds, greater than `1000`.\nIf your carousel automatically switches images based on a set time interval, the `data-optimus-interval` should match that interval\n- add `data-optimus-img-index` to all carousel toggle image buttons which have the `carouselToggleImageBtn` class.\nAllowed values are: `next`, `previous` (for next/previous buttons) or any image index, eg `5`, for buttons which allow the user to directly toggle to that specific image.\n\nIt 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).\n\n#### ProgressiveLoad\n`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).\n`ProgressiveLoad` is not configurable.\n\nTo ensure `ProgressiveLoad` works properly, you will have to:\n- 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 as `data-optimus-high-res-src` (or as `data-optimus-high-res-srcset`) image data property\n- if you are using the OptimusIMG `LazyLoad` function\n    - change `data-optimus-lazy-src` (or `data-optimus-lazy-srcset`, or both) from eg. `/images/foobar.jpeg` to the (generated with `npx prepare-progressive-images`) progressive image version path `/images/foobar-OptimusIMG-progressive.jpeg`,\n    OptimusIMG will then handle the progressive load functionality under the hood automatically both for single images and carousels which are lazily loaded\n- else\n    - change `src` (or `srcset`, or both) from eg. `/images/foobar.jpeg` to the (generated with `npx prepare-progressive-images`) progressive image version path `/images/foobar-OptimusIMG-progressive.jpeg`\n    - manually trigger `OptimusIMG.ProgressiveLoad.execute()` function whenever you load new images into view (eg. carousel image change event for carousels which are not utilizing OptimusIMG `LazyLoad` functionality, on document\n    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, ..)\n\n`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),\nto the high quality original image variant as soon as the original variant is loaded.\n\n#### Triggering functions\nYou can trigger re-run of any OptimusIMG function.\nThis is useful in case you do not with to duplicate your configuration. like this (example in turbolinks, jQuery and Typescript app, custom configuration):\n```\n// Triggers the LazyLoad for the first time\nconst LAZY_LOAD: LazyLoad = OptimusIMG.LazyLoad(customConfiguration);\n\n...\n\n$(document).on('turbolinks:load', () =\u003e {\n    // Triggers LazyLoad after every turbolinks load\n    LAZY_LOAD.execute();\n});\n```\nOr like this (example for vanilla JS, default configuration)\n```\n// Triggers the LazyLoad for the first time\nvar LAZY_LOAD = OptimusIMG.LazyLoad();\n\n...\n\nfunction loadPartial() {\n  var xhttp = new XMLHttpRequest();\n  xhttp.onreadystatechange = function() {\n    if (this.readyState == 4 \u0026\u0026 this.status == 200) {\n     document.getElementById(\"partial-container\").innerHTML = this.responseText;\n     // Triggers the LazyLoad in response to eg. ajax function response\n     LAZY_LOAD.execute(); // Considering there is no custom configuration, you could easily do OptimusIMG.LazyLoad(); as well\n    }\n  };\n  xhttp.open(\"GET\", \"some-partial.html\", true);\n  xhttp.send();\n}\n```\n\n**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,\neg. `OptimusIMG.ProgressiveLoad.execute()`, calling `OptimusIMG.ProgressiveLoad()` will **not** trigger the progressive load functionality.\n\n#### React example\nThe following will trigger lazy loading after a component is mounted.\n```\nimport { RUNTIME as OptimusIMG } from 'optimusimg/build/runtime/index.js';\n\n...\n\n\tcomponentDidMount() {\n\t\t...\n\t\tOptimusIMG.LazyLoad(configuration?: ILazyLoad);\n\t}\n\n...\n```\n\n#### Angular example\nThe following will trigger lazy loading after eg. a `CarouselComponent` is mounted.\n```\nimport { Component, OnInit } from '@angular/core';\nimport LazyLoad from 'optimusimg/src/runtime/lazy_load';\n\n@Component({\n  selector: 'app-carousel',\n  templateUrl: './carousel.component.html',\n  styleUrls: ['./carousel.component.scss']\n})\nexport class CarouselComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {\n    new LazyLoad();\n  }\n\n  ...\n}\n```\n\n#### Loading OptimusIMG via cdn and executing functions\n```\n\u003cscript src=\"https://unpkg.com/optimusimg@2.3.0/dist/OptimusIMG.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n    ...\n    // Triggers lazy load\n    OptimusIMG.LazyLoad();\n    // Triggers html elements check\n    OptimusIMG.HtmlElementsCheck();\n    // Triggers progressive load\n    OptimusIMG.ProgressiveLoad.execute();\n\u003c/script\u003e\n```\n\n#### Image Helpers\nOptimusIMG 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\n\n##### loadImageInBackground\nThe 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.\nYou 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. \n```\nimport { loadImageInBackground } from 'optimusimg/build/runtime/helpers';\n\n...\nloadImageInBackground('url-of-the-image-you-wish-to-load')\n...\n```\n\n\n### Buildtime useage\nOptimusIMG comes with buildtime scripts. For example, OptimusIMG will prepare a progressive version of your images\nwhich will be used for speeding up the initial load and will, in combination with runtime `ProgressiveImages` function,\nautomatically load the high-res (original) version of your image and swap the images once the high-res version is loaded.\n\nOptimusIMG also has an image analysis buildtime function which will warn you in case it detects possible optimisations for specific images.\n\nTo 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`):\n\n#### Requirements for buildtime functions\n- `npm@5.2.0` or higher (as it ships with npx). To find out which version of npm you are using, type `npm --version`\n    - If you are running `npm \u003c 5.2.0` and cannot upgrade, then you can do `npm install -g npx`\n\n#### npx prepare-progressive-images\nPrepare progressive images function supports images in `.jpg` (or `.jpeg`) and `.png` formats / file extensions.\nThe 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.\nThe images will be in the same formats as the originals and will differ from the original image by `-OptimusIMG-progressive` extension.\n\nThe progressive image variants will, in conjunction with the runtime `ProgressiveLoad` functionality, be used for ensuring\nthe initial load of the webpage is as quick as possible.\n\nPlease do not change the name of these images.\n\n#### npx analyse-images\nAnalyse images function supports images in `.jpg` (or `.jpeg`) and `.png` formats / file extensions.\nThe function will analyse all images within the folder (and all subfolders) you specify and let you know of possible optimisations.\n\nPlease note: in case you have a lot of (big) images in your project, the function might take a couple of minutes to finish analysis.\n\n## Contributing\nClone, `npm install`, code, lint, test, push and open a pull request.\nI am only accepting PRs with a 100% code coverage.\n\n### Commit messages\nTo ensure commit messages follow the same pattern, please use `npm run commit` instead of the standard `git commit`\nand follow the commit instructions in the terminal.\n\n### Testing\nOptimusIMG uses Jest for testing. To trigger tests - `npm run test`\n\n### Linting\nOptimusIMG uses TSLint for linting. To trigger linting - `npm run lint`\n\n## License\nOptimusIMG is licensed under the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukavarga%2Foptimusimg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flukavarga%2Foptimusimg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukavarga%2Foptimusimg/lists"}