{"id":13423807,"url":"https://github.com/humaans/next-img","last_synced_at":"2026-02-27T17:28:44.427Z","repository":{"id":52883384,"uuid":"268319171","full_name":"humaans/next-img","owner":"humaans","description":"A Next.js plugin for embedding optimized images.","archived":false,"fork":false,"pushed_at":"2024-12-30T10:33:46.000Z","size":49238,"stargazers_count":272,"open_issues_count":6,"forks_count":11,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-07T07:47:45.356Z","etag":null,"topics":["javascript","jpeg","lighthouse-score","nextjs","nextjs-plugin","png","web","webp"],"latest_commit_sha":null,"homepage":"https://humaans.github.io/next-img/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/humaans.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"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":"2020-05-31T16:29:31.000Z","updated_at":"2025-03-03T05:32:08.000Z","dependencies_parsed_at":"2022-08-23T10:21:05.277Z","dependency_job_id":"95b0e798-9b48-4ad4-8679-f0e7639e5b21","html_url":"https://github.com/humaans/next-img","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humaans%2Fnext-img","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humaans%2Fnext-img/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humaans%2Fnext-img/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humaans%2Fnext-img/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/humaans","download_url":"https://codeload.github.com/humaans/next-img/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243767281,"owners_count":20344898,"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":["javascript","jpeg","lighthouse-score","nextjs","nextjs-plugin","png","web","webp"],"created_at":"2024-07-31T00:00:42.971Z","updated_at":"2026-02-27T17:28:44.422Z","avatar_url":"https://github.com/humaans.png","language":"JavaScript","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://user-images.githubusercontent.com/324440/84087760-bbff5f80-a9e2-11ea-8aeb-db605876d9cf.png\" alt=\"next-img\" title=\"next-img\"\u003e\n\u003c/p\u003e\n\n\u003ch4 align=\"center\"\u003eNext.js plugin for embedding optimized images.\u003c/h4\u003e\n\u003cbr /\u003e\n\nFeatures\n\n- **no CDN required** — images are optimized at build time, not at runtime\n- **static export** — works with `output: 'export'`, no server needed\n- **import** png/jpg images with query params to control sizes and densities\n- **output** to webp format with optimized fallbacks\n- **resize** to multiple screen sizes and densities in a single import\n- **optimize** using `sharp` at build time with results cached in your repo\n- **lazy load** in modern browsers with prop forwarding (`loading=\"lazy\"`)\n- **prevent layout shift** with automatic width/height attributes\n- **streamlined usage** with the built in `\u003cPicture /\u003e` component\n- **art direction** with different images for different breakpoints\n- **fast** builds using a persistent cache that can be checked into version control\n\nBy default **next-img** is configured to use:\n\n- 1 breakpoint at `768px`\n- 2 pixel densities of 1x, 2x\n- to output the original and webp formats\n\nAll of these settings and more can be changed in your `next.config.js` or in the individual image imports.\n\nDeveloped and used by [Humaans](https://humaans.io/).\n\n## Motivation\n\nBy default Next.js or Webpack doesn't help you much with optimizing images. This means custom configuration or scripting, processing images by hand, using an image CDN or not optimising images at all. **next-img** provides and alternative streamlined approach for adding images to your Next.js projects. It combines a Next.js plugin, a custom webpack loader and a React component to make serving images in an optimal fashion in a way that is almost as easy as typing `\u003cimg src='foo.png' /\u003e`.\n\nIn short, it takes the following:\n\n```js\n\u003cPicture src={require('./images/jelly.jpg?sizes=375,800')} alt='Jellyfish' /\u003e\n```\n\nImports, resizes, optimizes, caches (persistently in the git repo) and outputs the following HTML:\n\n```html\n\u003cpicture\u003e\n  \u003csource\n    type=\"image/webp\"\n    srcset=\"\n      /_next/static/images/jelly-375@1x-5e609945b16eba99bf2aaa3007d3ba92.webp  375w,\n      /_next/static/images/jelly-375@2x-850e7fd87fceda1e7cefcb628a07f5c4.webp  750w,\n      /_next/static/images/jelly-800@1x-1481a104c8ce38822aeafdbe97a17e69.webp  800w,\n      /_next/static/images/jelly-800@2x-fc18765bd3b819714ca2da58e10907c9.webp 1600w\n    \"\n    sizes=\"(max-width: 768px) 375px, 800px\"\n  /\u003e\n  \u003csource\n    type=\"image/jpeg\"\n    srcset=\"\n      /_next/static/images/jelly-375@1x-259e4b1f32b3bdd4349806c4a5763a54.jpg  375w,\n      /_next/static/images/jelly-375@2x-295d4cc8111d4e911dbc9ad4dd1d8322.jpg  750w,\n      /_next/static/images/jelly-800@1x-090d866969aba9b237e71ee52512a7c4.jpg  800w,\n      /_next/static/images/jelly-800@2x-33f1639cadf8c4c5f19eb5c19e20a67d.jpg 1600w\n    \"\n    sizes=\"(max-width: 768px) 375px, 800px\"\n  /\u003e\n\n  \u003cimg\n    src=\"/_next/static/images/jelly-375@1x-259e4b1f32b3bdd4349806c4a5763a54.jpg\"\n    srcset=\"\n      /_next/static/images/jelly-375@1x-259e4b1f32b3bdd4349806c4a5763a54.jpg  375w,\n      /_next/static/images/jelly-375@2x-295d4cc8111d4e911dbc9ad4dd1d8322.jpg  750w,\n      /_next/static/images/jelly-800@1x-090d866969aba9b237e71ee52512a7c4.jpg  800w,\n      /_next/static/images/jelly-800@2x-33f1639cadf8c4c5f19eb5c19e20a67d.jpg 1600w\n    \"\n    width=\"375\"\n    height=\"250\"\n    alt=\"Jellyfish\"\n  /\u003e\n\u003c/picture\u003e\n```\n\n[View examples](https://humaans.github.io/next-img/).\n\n## Usage\n\nInstall the package\n\n```\nnpm install next-img\n```\n\nAdd the plugin to your `next.config.js`:\n\n```js\nconst withImg = require('next-img/plugin')\n\nmodule.exports = withImg({\n  nextImg: {\n    breakpoints: [768],\n  },\n})\n```\n\nIn your application, import the images and embed using the `\u003cPicture /\u003e` component:\n\n```js\nimport { Picture } from 'next-img'\nimport jelly from './images/jelly.jpg?sizes=375,800'\n\nexport default () =\u003e \u003cPicture src={jelly} /\u003e\n```\n\nOr inline:\n\n```js\nimport { Picture } from 'next-img'\n\nexport default () =\u003e \u003cPicture src={require('./images/jelly.jpg?sizes=375,800')} /\u003e\n```\n\nThis particular example will generate the following images:\n\n- 375px wide image to show on small screens with low pixel density of 1x\n- 750px wide image to show on small screens with high pixel density of 2x or more\n- 800px wide image to show on large screens with low pixel density of 1x\n- 1600px wide image to show on large screens with high pixel density of 2x or more\n\nThe resized and optimized images will be saved to the `resources` directory in the root of your project during the development. This means, that if you tweak the image import parameters or plugin configuration, you might generate extra images that are no longer used by your project. In that case execute `next-img` command to remove any unnecessary images and build any missing ones:\n\n```\nnpx next-img\n```\n\nNow check in the `resources` directory to your source control to be reused later for development and production builds. You can turn this feature off by setting `persistentCache: false` in the plugin configuration, in which case the images will be only stored in a temporary cache inside `.next` directory.\n\n[View more usage examples](https://humaans.github.io/next-img/).\n\n## Configuration\n\nDefault plugin configuration options:\n\n```js\n{\n  // global settings for images, can be overriden per image\n  breakpoints: [768],\n  densities: ['1x', '2x'],\n\n  // output image quality configuration\n  jpeg: {\n    quality: 80,\n    webp: {\n      quality: 90,\n      reductionEffort: 6,\n    },\n  },\n\n  png: {\n    quality: 100,\n    webp: {\n      reductionEffort: 6,\n      lossless: true,\n    },\n  },\n\n  // the directory within Next.js build output\n  imagesDir: 'images',\n  // the output image name template\n  imagesName: '[name]-[size]@[density]-[hash].[ext]',\n  // advanced - customise the image public path\n  imagesPublicPath: null,\n  // advanced - customise the image output path\n  imagesOutputPath: null,\n\n  // persistent cache allows for fast deploy and\n  // development workflow by avoiding reprocessing\n  // images that were previously processed\n  persistentCache: true,\n  persistentCacheDir: 'resources',\n\n  // this directory within .next is used in case persistent cache is turned off\n  cacheDir: path.join('cache', 'next-img')\n}\n```\n\nRefer to [sharp documentation](https://sharp.pixelplumbing.com/api-output) for `jpeg/png/webp` compression options.\n\n## Import Params\n\nWhen importing an image, you can use query parameters to customise the optimisation:\n\n- **sizes** - a list of comma separated sizes you will be showing images at. Note that you do not need to take into account the pixel densities here. That is, if you're showing an image at `320px` wide on your website, simply specify `320` here, the plugin will produce any necessary larger versions based on the `densities` configuration.\n- **densities** - a list of comma separated densities you need each image size to be produced at. By default `1x` and `2x` sizes of images will be produced, specify `1x` if you want to produce only one image per size, or `1x,2x,3x`, etc. if you want more densities.\n- **jpeg** - quality configuration options for `jpeg` images. Note, the `jpeg-\u003ewebp` settings need to be nested under this param, e.g. `?jpeg[webp][quality]=95`\n- **png** - quality configuration options for `png` images. Note, the `png-\u003ewebp` settings need to be nested under this param, e.g. `?png[webp][lossless]=false\u0026png[webp][nearLossless]=true`\n\nExamples:\n\n```js\nimport img1 from './images/img.jpg'\nimport img2 from './images/img.jpg?sizes=375,900'\nimport img3 from './images/img.jpg?sizes=375,900\u0026densities=1x'\nimport img4 from './images/img.jpg?sizes=375,900\u0026densities=1x,2x,3x'\nimport img5 from './images/img.jpg?sizes=375,900\u0026densities=1x,2x,3x\u0026jpeg[quality]=70\u0026jpeg[webp][quality]=70'\n```\n\n## Picture Props\n\n`next-img` comes with a React component making embedding images easier.\n\nHere are the props this component access:\n\n- **src** the imported image, or an array of imported images.\n- **breakpoints** - a list of breakpoints to override the global configuration.\n- **sizes** - a custom [html sizes attribute](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#How_do_you_create_responsive_images), by default the sizes attribute is generated based on the available images and breakpoints.\n- **the rest of the props and ref** are forwarded to the `img` tag. This allows the use of attributes such as `alt`, `loading=\"lazy\"`, etc..\n\n#### A note on how sizes/media attributes are generated\n\nWhen a single image is provided via the `src` prop, then each size will be configured to show up per each breakpoint available using the html [`sizes attribute`](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#How_do_you_create_responsive_images) attribute.\n\nFor example, with breakpoints `[375, 768]` and `?sizes=100,400,800` the `\u003cPicture\u003e` component will apply the following `sizes` attribute:\n\n```\n(max-width: 375px) 100px,\n(max-width: 768px) 400px,\n                   800px\n```\n\nWhen an array of images is provided via the `src` prop, then each image will be configured to show up per each breakpoint available using the html [`media attribute`](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#Art_direction).\n\nFor example, with breakpoints `[375, 768]` and `src=[img1, img2, img3]` the `\u003cPicture\u003e` component will apply the following `media` attribute:\n\n```html\n\u003cpicture\u003e\n  \u003csource media=\"(max-width: 480px)\" sizes=\"{{img1 width}}\" /\u003e\n  \u003csource media=\"(max-width: 768px)\" sizes=\"{{img2 width}}\" /\u003e\n  \u003csource sizes=\"{{img3 width}}\" /\u003e\n  \u003cimg ... /\u003e\n\u003c/picture\u003e\n```\n\n## Turbopack Compatibility\n\nThis plugin currently requires **webpack** and is not compatible with Turbopack. If you're using Next.js 16+ (which defaults to Turbopack), you'll need to opt into webpack mode:\n\n```\nnext dev --webpack\nnext build --webpack\n```\n\nThe core limitation is that Turbopack does not support the [`emitFile`](https://github.com/vercel/next.js/issues/78592) loader API, which next-img relies on to output processed images into the build. Until Turbopack adds support for this API, webpack mode is required.\n\n## FAQ\n\n**Do I have to use the `\u003cPicture /\u003e` component?**\n\nThe Picture component is optional. You can handle the imported image object however you want.\n\n**Couldn't the images be optimized further?**\n\nYes, you could probably get ~10%-20% or more compression if you pass the `jpg/png` through ImageOptim or other tools. Thing is, since this plugin outputs an already well optimized webp and you'll be serving webp to most modern browsers, that removes the need to squeeze that extra file size for `jpg/png` since they are the _fallback_ images. However, there might be use cases where custom compression algorhithms are needeed and we might add support for arbitrary transformations in this plugin in the future.\n\n## Development\n\n```\nnpm install\n```\n\nYou can use the docs site as the playground:\n\n```\ncd docs\nnpm install\nnpm start\n```\n\nTo rebuild the persistent image cache:\n\n```\nnpx next-img\n```\n\n## Ideas\n\n- Allow turning `webp/jpg/png` output off\n- Add `?raw` query support that doesn’t process the image in any way\n- Inline small images as base64\n- Add support for gif and webp as source images\n- Translate relative sizes `?sizes=100vw,50vw,900px` to pixels based on breakpoint configuration, so image sizing can follow your design system automatically\n","funding_links":[],"categories":["Extensions","JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhumaans%2Fnext-img","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhumaans%2Fnext-img","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhumaans%2Fnext-img/lists"}