Requires Node 12+ and Webpack 5+
This is an image loader built around @11ty/eleventy-img (uses sharp) to convert and optimize images. With the power of eleventy-img
this loader can also download (and cache) remote images - e.g. from your headless CMS - using fetch files.
The purpose of this loader is to reduce dependencies for your 11ty and Webpack based projects. It'll use your existing 11ty packages, so there's no need for another image processor to handle images running through Webpack. Fewer dependencies mean faster builds.
ℹ Although
eleventy-img
can produce multiple output files for one input - with different formats and dimensions - the current version of this loader works in 1→1 mode (generates one file for one input).
npm install @szegheo/webpack-eleventy-img-loader --save-dev
ℹ This package has only
peerDependencies
as listed below, so probably you already have them in your 11ty based project — means no new dependencies will be installed in that case.
- webpack — version ^5.0.0
- @11ty/eleventy-img — version ^1.0.0 — (see option)
- @11ty/eleventy-cache-assets — version ^2.3.0 — (see option)
A typical use case to extract images from CSS using Webpack 5 Asset Modules:
webpack.config.js:
module.exports = {
//...
module: {
rules: [
//...
{
test: /\.(jpe?g|png|webp|avif|tiff|fetch)$/i,
type: 'asset', // or 'asset/resource'
generator: {
// just for the example (can be omitted)
filename: '[name]-[hash:8][ext]',
},
use: [
{
loader: 'webpack-eleventy-img-loader',
options: {
// rename output files (this will be used for [name] above)
rename: '[oldname]-[width]w'
}
}
]
},
// MiniCssExtractPlugin.loader
// css-loader
// sass-loader
]
}
};
example.scss:
section.demo {
background-image: url('/assets/images/bg-demo.jpg?width=800');
.webp & {
background-image: url('/assets/images/bg-demo.jpg?width=800&format=webp');
}
}
output:
bg-demo-800w-968dc568.jpeg
bg-demo-800w-e3b326cf.webp
ℹ Please note that the loader always normalizes .jpg to .jpeg for the output files! This rule comes from eleventy-img and it is for reason.
By default the loader only does image optimization and keeps the original format. The following query paramteres can be used to set how the output image needs to be generated:
Param | Accepts | Description |
---|---|---|
format |
jpeg | png | webp | avif |
Sets the format of the output image. |
width |
number |
Resize image to the given width. |
Example:
import image from './demo.jpg?width=800&format=webp';
ℹ The current version of eleventy-img does not support other modifications like setting
height
orcropping
but a feature request has already been open. Additional parameters are expected to be added.
Name | Type | Default | Descripton |
---|---|---|---|
rename |
{String} |
'[oldname]' |
Rename mask for the output file, which will be the [name] placeholder for Asset Modules. |
fetchFileExt |
{String} |
'fetch' |
Allows to overwrite the default extension for fetch files (JSON format containing the URL to the remote image). |
beforeFetch |
{Function} |
undefined |
Allows to modify URL and fetchOptions before fetching a remote image. |
sharpConfig |
{Object} |
undefined |
Allows to configure sharp optimization options for eleventy-img . |
cacheDownloads |
{Boolean} |
false |
Allow to store downloaded remote images in cacheDir. |
cacheResults |
{Boolean} |
false |
Allow to store result (optimized) images in cacheDir. |
cacheDir |
{String} |
undefined |
A path where cache files will be stored. |
cacheDuration |
{String} |
undefined |
Sets how long a cached item (output result / fetched remote image) is valid. |
concurrency |
{Number} |
undefined |
Maximum number of concurrency optimization processes in one time. |
fetchConcurrency |
{Number} |
undefined |
Maximum number of concurrency image downloads in one time. |
eleventyImage |
{String|Object} |
'@11ty/eleventy-img' |
Allows to manually provide dependency if needed for any reason. |
eleventyCache |
{String|Object} |
'@11ty/eleventy-cache-assets' |
Allows to manually provide dependency if needed for any reason. |
debug |
{Boolean} |
false |
Use debug mode (detailed console logs). |
Type: {String}
Default: '[oldname]'
Adds the ability to rename output file. You can use the following - always available - placeholders:
[oldname]
- holds the original filename without the extension[width]
- the final width of the output image[height]
- the final height of the output image
Example:
'[oldname]-[width]x[height]'
ℹ For remote images
[oldname]
holds the name of thefetch-file
, not the one found(?) in the url. Read more about fetching remote images using.fetch
files.
Important:
⚠ Do not use extension, path, subdir, or any other webpack specific placeholders here! Extension is generated automatically based on the mime type of the output file.
Type: {String}
Default: 'fetch'
A .fetch
file is just a simple JSON file containing the url
of the remote image. Using this option you can change its extension.
ℹ The value of this option must be in sync with your
Rule.test
config, otherwise the loader won't be able to process them! If you change it, change it there either.
Type: {Function}
Default: undefined
It's possible to change the request url
and set options for node-fetch
before fetching a remote image.
function (imageUrl, resourcePath) => {String|URL|Object}
Param | Type | Description |
---|---|---|
imageUrl |
{String} |
The url of the remote image. |
resourcePath |
{String} |
Local path to the current .fetch file. |
Example: returning {Srting}
beforeFetch: (imageUrl, resourcePath) => {
return imageUrl.replace('CMS-SERVER', 'myserver.example');
}
Example: returning {URL}
beforeFetch: (imageUrl, resourcePath) => {
let newURL = new URL(imageUrl);
newURL.username = process.env.SECRET_USER;
newURL.password = process.env.SECRET_PWD;
newURL.searchParams.set('somekey', 'someval');
return newURL;
}
Example: returning {Object}
with fetchOptions
beforeFetch: (imageUrl, resourcePath) => {
return {
fetchUrl: imageUrl, // required {String|URL}
fetchOptions: {
// options for node-fetch
method: 'GET'
}
};
}
Type: {Object}
Default: undefined
Allows to configure sharp optimization options for eleventy-img
. See "ADVANCED CONTROL OF SHARP IMAGE PROCESSOR". Defaults of sharp
will be used otherwise.
Example:
sharpConfig: {
sharpJpegOptions: { mozjpeg: true, quality: 85, progressive: true }
}
Type: {Boolean}
Default: false
Required options: cacheDir
, cacheDuration
⚠ While this was well tested during development, please use it with caution and make your own tests first using the
debug
option!
When enabled, the loader writes downloaded images to its permanent disk cache based on the full URL of the request (cache key). Next time, when a new build is started it validates the request URL against its cache. If the current image was found in the cache and it is not expired, it will use that instead downloading it again.
In case when a fetch request fails but a cache entry already exists (even if it’s expired), it will use the cached entry.
Type: {Boolean}
Default: false
Required options: cacheDir
, cacheDuration
⚠ While this was well tested during development, please use it with caution and make your own tests first using the
debug
option!
When enabled, the loader writes generated images to its permanent disk cache. Next time, when a new build is started it validates input images and their parameters against the cache. When a cached item for this condition was found and it is not expired, that will be immediately returned to Webpack instead re-generating the same file.
The cacheKey
is calculated using the hash sum of:
- the full
path
to the local resource file (image or fetch file with query params) - options for
eleventy-img
(size, format, sharp config, etc) - the
Buffer
holding binary content of the input image beeing processed
Type: {String}
Default: undefined
A path where cache files will be stored. Will be created if not exits.
Type: {String}
Default: undefined
Sets how long a cached item (output result / fetched remote image) is valid. This option is used by eleventy-cache-assets
(original docs).
Example:
cacheDuration: "1d" // file expires after 1 day
Where:
s
is secondsm
is minutesh
is hoursd
is daysw
is weeksy
is years
Type: {Number}
Default: undefined
(see description)
Sets the maximum number of concurrency optimization processes in one time. If set, this option is forwarded to eleventy-img
(see the docs).
Type: {Number}
Default: undefined
(see description)
Maximum number of concurrency image downloads in one time. If set, this option is forwarded to eleventy-cache-assets
(see the docs).
Type: {String|Object}
Default: '@11ty/eleventy-img'
Package @11ty/eleventy-img
will be automatically loaded, but it's possible to set it manually if needed. Load it with require
or give an exact path
to the package.
Type: {String|Object}
Default: '@11ty/eleventy-cache-assets'
Package @11ty/eleventy-cache-assets
will be automatically loaded, but it's possible to set it manually if needed. Load it with require
or give an exact path
to the package.
Type: {Boolean}
Default: false
Logs useful debug information to console when enabled.
Thanks to eleventy-img
this loader can download (fetch) - and even cache - remote images on-the-fly using local .fetch
files. Why is this good? Because using them you can work with remote images - probably on your headles CMS server - as they would real local images. Also you can safely add query params to the .fetch
file.
- A
.fetch
file is just a simpleJSON
file with theurl
of the remote image. - The
url
does not need to have a filename or extension. - The
url
can be modified using thebeforeFetch
option. Do not store tokens or passwords in fetch files! - The
filename
of thefetch
file will be used when naming the output file. - The original
extension
is determined by theMIME Type
of the fetched image. - It's possible to change the default
"fetch"
extension using thefetchFileExt
option.
my-cute-kitten.fetch:
{
"url": "https://loremflickr.com/1920/1080/kitten?lock=777"
}
example.css:
.example {
background-image: url('/assets/images/my-cute-kitten.fetch?width=320');
}
output: (…using rename: '[oldname]-[width]w'
)
my-cute-kitten-320w.jpeg
👉 In the example above the MIME Type of the remote image was
image/jpeg
, so the output format was kept unchanged because we didn't use theformat
query param on the fetch file.
npm run test
- Uses the ava JavaScript test runner (Assertions documentation)
- Requires internet connection to load remote test images (.fetch files)
- Uses memfs to write output files to an in-memory file-system (except cache files).
This package uses commitlint to ensure proper commit messages. Please follow the rules declared in @commitlint/config-conventional.