.. include:: /Includes.rst.txt
.. _configuration:
=============
Configuration
=============
The extension works out of the box with sensible defaults. All
three operating modes -- on-demand frontend processing, on-upload
compression, and bulk CLI -- activate automatically after
installation. This page documents the extension points that can
be tweaked.
.. _configuration-viewhelper:
SourceSetViewHelper
===================
The ``SourceSetViewHelper`` generates responsive ```` tags
with ``srcset`` attributes.
.. code-block:: html
:caption: Basic ViewHelper usage
{namespace nr=Netresearch\NrImageOptimize\ViewHelpers}
.. _configuration-parameters:
Parameters
----------
.. confval:: path
:name: confval-path
:type: string
:required: true
Public path to the source image (for example
``/fileadmin/foo.jpg``), typically generated via
``f:uri.image()``.
.. confval:: width
:name: confval-width
:type: int|float
:Default: 0
Base width in pixels for the rendered ````. ``0``
resolves automatically from the source file.
:ref:`Clamped by the processor ` to
1--8192 when baked into the variant URL.
.. confval:: height
:name: confval-height
:type: int|float
:Default: 0
Base height in pixels. ``0`` preserves aspect ratio
relative to :confval:`width `.
:ref:`Clamped by the processor `
to 1--8192.
.. confval:: set
:name: confval-set
:type: array
:Default: []
Responsive set in the form
``{maxWidth: {width: int, height: int}}``. Each entry
becomes a ````
tag.
.. confval:: alt
:name: confval-alt
:type: string
:Default: empty string
Alternative text for the image. Always rendered (even
when empty) to keep assistive-tech compatibility.
.. confval:: title
:name: confval-title
:type: string
:Default: empty string
HTML-escaped title attribute.
.. confval:: class
:name: confval-class
:type: string
:Default: empty string
CSS classes for the ```` tag. Include
``lazyload`` to switch from native to JS-based lazy
loading (see :ref:`configuration-lazy-loading`).
.. confval:: mode
:name: confval-mode
:type: string
:Default: cover
Render mode. ``cover`` resizes images to fully cover
the given dimensions (crop/fill). ``fit`` resizes images
to fit within the given dimensions.
.. confval:: lazyload
:name: confval-lazyload
:type: boolean
:Default: false
Add ``loading="lazy"`` (native lazy loading).
.. confval:: responsiveSrcset
:name: confval-responsive-srcset
:type: boolean
:Default: false
Enable width-based responsive ``srcset`` instead of the
density-based ``2x`` output (preserved for backward
compatibility).
.. confval:: widthVariants
:name: confval-width-variants
:type: string|array
:Default: 480, 576, 640, 768, 992, 1200, 1800
Width variants for responsive ``srcset``
(comma-separated string or array). Only honored when
:confval:`responsiveSrcset `
is enabled.
.. confval:: sizes
:name: confval-sizes
:type: string
:Default: auto, (min-width: 992px) 991px, 100vw
Responsive ``sizes`` attribute for the generated
```` tag.
.. confval:: fetchpriority
:name: confval-fetchpriority
:type: string
:Default: empty string
Native HTML ``fetchpriority`` attribute. Allowed
values: ``high``, ``low``, ``auto``. Omitted when
empty.
.. confval:: attributes
:name: confval-attributes
:type: array
:Default: []
Extra HTML attributes merged into the rendered tag.
.. note::
Quality and output format are not exposed as ViewHelper
arguments. Quality defaults to 75 and is baked into the
generated ``/processed/...q...`` URL; the variant's
file extension is inherited from the source image. Use
:ref:`the URL format ` and
:ref:`variant negotiation `
to influence the served format.
.. _configuration-source-sets:
Source set configuration
========================
Define source sets per media breakpoint via the ``set``
attribute:
.. code-block:: html
:caption: Source set with breakpoint-specific dimensions
.. _configuration-render-modes:
Render modes
============
``cover``
Default. Resizes images to fully cover the provided
width and height.
``fit``
Resizes images so they fit within the provided width
and height.
.. code-block:: html
:caption: Using fit mode
.. _configuration-lazy-loading:
Lazy loading
============
Both modes support lazy loading via the native
``loading="lazy"`` attribute. When using JS-based lazy
loading (``class="lazyload"``), the ``data-srcset``
attribute is added automatically.
.. _configuration-backward-compatibility:
Backward compatibility
======================
By default :confval:`responsiveSrcset `
is ``false``, preserving the existing 2x density-based
``srcset`` behavior. All existing templates continue to work
without modifications.
.. _configuration-url-format:
Variant URL format
==================
Processed variants are served from a dedicated URL path. The
ViewHelper generates these URLs automatically, but any markup
that writes a URL of this form will be intercepted by the
:ref:`ProcessingMiddleware `:
.. code-block:: text
:caption: URL template
/processed/..[?]
````
Public path of the source image, including the
``/fileadmin/`` (or other storage) prefix. Path traversal
sequences (``..``) are rejected at URL-parsing time.
````
Concatenation of one or more of:
``w``
Target width in pixels.
``h``
Target height in pixels.
``q``
Quality (1--100).
``m``
Processing mode (``0`` = cover, ``1`` = scale/fit).
````
Source image extension. The processor decides at
response time whether to serve the original, the
``.webp`` sidecar, or the ``.avif`` sidecar, based on
which of these files exist on disk (see
:ref:`configuration-variant-negotiation`).
.. code-block:: text
:caption: Example URL
/processed/fileadmin/photos/hero.w1200h800m0q85.jpg
.. _configuration-variant-negotiation:
Variant negotiation
===================
When the processor generates a variant, it writes the original
file to disk and additionally produces a ``.webp`` and an
``.avif`` sidecar (same base name), unless the format is turned
off (see :ref:`configuration-sidecar-formats`).
The processor does not inspect the ``Accept`` request header.
On each request it serves the first non-empty file it finds on
disk, in this order: the ``.avif`` sidecar, the ``.webp``
sidecar, the original format.
Two query parameters let callers opt out of sidecar generation
for individual URLs:
``skipWebP=1``
Do not produce a WebP variant for this URL.
``skipAvif=1``
Do not produce an AVIF variant for this URL.
The flags only control generation. The query string is not part
of the variant file name, so a URL with a skip flag shares its
files with the same URL without it: a sidecar already written
for that variant is served either way.
These flags are useful when specific consumers (for example
e-mail clients or legacy RSS renderers) cannot handle modern
formats.
.. _configuration-sidecar-quality:
WebP/AVIF output quality
========================
.. versionadded:: 2.4.0
The ``qualityWebp`` and ``qualityAvif`` extension configuration
settings.
The primary variant's quality is controlled per-request via the
``q`` URL segment (see :ref:`configuration-url-format`). The
``.webp`` and ``.avif`` sidecars previously reused that same numeric
quality, but AVIF's quality scale is steeper than WebP's or JPEG's --
at matching numbers an AVIF file comes out larger than the WebP
sidecar, defeating the point of serving AVIF at all.
Two extension configuration settings control sidecar quality
independently of the primary variant:
``qualityWebp`` (default ``75``)
Output quality for the generated WebP variant. At ``100`` the WebP
variant is encoded lossless and typically comes out several times
larger than the primary JPEG variant.
``qualityAvif`` (default ``60``)
Output quality for the generated AVIF variant. The lower default
keeps AVIF variants genuinely smaller than WebP while staying
visually comparable.
.. versionchanged:: 2.6.0
AVIF output quality is capped at ``99``: ``qualityAvif`` for the
AVIF variant, and the URL quality (``q100``) for processed AVIF
originals. At ``100`` ImageMagick switches to lossless AVIF
encoding, which returns no image data, so no AVIF variant was
written and a processed AVIF original failed with HTTP 500.
.. code-block:: php
:caption: config/system/additional.php
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['nr_image_optimize']['qualityWebp'] = 75;
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['nr_image_optimize']['qualityAvif'] = 60;
The settings can also be edited via the backend:
*Admin Tools > Settings > Extension Configuration >
nr_image_optimize*.
.. attention::
Per-format quality is not part of the processed-variant cache
filename. Changing either setting only affects newly generated
variants -- clear already-processed images (see
:ref:`maintenance-clear`) to apply the new quality to existing
ones.
.. _configuration-sidecar-formats:
WebP/AVIF generation
====================
.. versionadded:: 2.6.0
The ``generateWebp`` and ``generateAvif`` extension configuration
settings.
By default the processor writes a ``.webp`` and an ``.avif`` file next
to every processed variant. Two switches turn either format off for the
whole installation, for example to save storage when one sidecar format
is enough:
``generateWebp`` (default ``1``)
Write a ``.webp`` sidecar for each processed variant.
``generateAvif`` (default ``1``)
Write an ``.avif`` sidecar for each processed variant.
.. code-block:: php
:caption: config/system/additional.php
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['nr_image_optimize']['generateWebp'] = false;
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['nr_image_optimize']['generateAvif'] = true;
The per-URL ``skipWebP`` and ``skipAvif`` query parameters (see
:ref:`configuration-variant-negotiation`) still apply on top: a format
is generated only if its switch is on and the URL does not skip it.
.. attention::
The switches only control generation. Sidecars already on disk are
still served. Clear already-processed images (see
:ref:`maintenance-clear`) to remove them.
.. _configuration-cache-headers:
Cache headers
=============
Processed variant URLs are effectively content-addressed -- any
change to dimensions, quality, or format produces a different
URL. The processor therefore responds with an immutable,
long-lived cache header:
.. code-block:: text
Cache-Control: public, max-age=31536000, immutable
This value is a compile-time constant and not user-configurable.
.. _configuration-image-driver:
Image driver selection
======================
Intervention Image is instantiated through
:php:class:`~Netresearch\\NrImageOptimize\\Service\\ImageManagerFactory`,
which selects the best available driver at runtime:
1. **Imagick** when the ``imagick`` PHP extension is loaded
(preferred -- supports AVIF natively if the underlying
ImageMagick build does).
2. **GD** when ``imagick`` is unavailable and the ``gd``
extension is loaded.
If neither extension is present, the factory throws a
``RuntimeException`` with a descriptive message. Use the
:ref:`backend maintenance module `
to verify driver availability on your host.
.. _configuration-middleware:
Middleware registration
=======================
:file:`Configuration/RequestMiddlewares.php` registers the
``ProcessingMiddleware`` on the frontend pipeline **before**
``typo3/cms-frontend/site``. This ordering is required so the
middleware can intercept ``/processed/`` URLs before
TYPO3's frontend routing claims them. The registration has no
user-configurable options.
.. _configuration-limits:
Processor limits
================
The processor enforces the following bounds when parsing a URL:
``MAX_DIMENSION``
Width and height are clamped to 1--8192 pixels to prevent
denial-of-service via excessive memory allocation.
``MIN_QUALITY`` / ``MAX_QUALITY``
Quality is clamped to 1--100.
``LOCK_MAX_RETRIES``
Up to 10 attempts (at 100 ms intervals) to acquire the
per-variant processing lock before returning HTTP 503.
Prevents duplicate work when multiple clients hit the
same uncached variant simultaneously.
.. _configuration-trusted-storage-symlinks:
Trusted storage symlinks
=========================
.. versionadded:: 2.3.0
The ``additionalTrustedStorageSymlinks`` extension configuration
setting.
The processor validates that both the source image and the
target variant resolve (via ``realpath()``) to a location
inside an allowed root -- the public webroot, or a Local FAL
storage's own base path -- before reading or writing anything.
This rejects requests for images reached through a symlink that
escapes those roots (for example a symlink accidentally or
maliciously pointing at :file:`/etc`).
Some deployments relocate TYPO3 core's own
:file:`_processed_` image cache -- a subdirectory *inside* a FAL
storage's own directory, e.g. :file:`fileadmin/_processed_` --
onto local/ephemeral storage, to keep frequently-rewritten
derivative images off shared/NFS storage. That leaves only a
symlink behind inside the storage, which the FAL-storage
basePath lookup above does not see (it only resolves the
storage's own base path, never looks inside it), so variant
requests for such images are rejected even though the original
file is legitimately part of the deployed application.
The ``additionalTrustedStorageSymlinks`` extension configuration
setting closes this gap on an explicit, per-instance, opt-in
basis: a comma-separated list of directory names that, when
found as a symlink directly inside a Local FAL storage's base
path, are resolved and added to the allow-list too.
.. code-block:: php
:caption: config/system/additional.php
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['nr_image_optimize']['additionalTrustedStorageSymlinks'] = '_processed_';
The setting can also be edited via the backend:
*Admin Tools > Settings > Extension Configuration >
nr_image_optimize*.
.. attention::
This widens the set of filesystem locations the processor
will read from and publicly serve variants of. Only add
well-known, infrastructure-managed names here -- never a
name an untrusted party (e.g. an FTP-only content account)
could create on their own. The default is empty, which
keeps today's behavior unchanged for every installation that
does not configure it.
.. _configuration-additional-trusted-roots:
Additional trusted roots
=========================
.. versionadded:: 2.4.0
The ``additionalTrustedRoots`` extension configuration setting.
Some deployments need to serve variants of images that live under
an absolute filesystem path that is neither the public webroot,
a Local FAL storage's own base path, nor one of the hardcoded
TYPO3-internal locations (``var/``, symlinked
:file:`processed`/:file:`uploads`, or extension-published
:file:`_assets/` directories) -- for example a custom mount
managed outside of FAL.
The ``additionalTrustedRoots`` extension configuration setting
closes this gap on an explicit, per-instance, opt-in basis: a
comma-separated list of *absolute* filesystem paths that are
realpath-resolved and added to the allow-list directly.
.. code-block:: php
:caption: config/system/additional.php
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['nr_image_optimize']['additionalTrustedRoots'] = '/mnt/custom-assets';
The setting can also be edited via the backend:
*Admin Tools > Settings > Extension Configuration >
nr_image_optimize*.
.. attention::
This widens the set of filesystem locations the processor
will read from and publicly serve variants of. Only add paths
you fully trust. Relative paths are rejected outright (never
resolved against the PHP process's working directory). The
default is empty, which keeps today's behavior unchanged for
every installation that does not configure it.