Image Optimization for TYPO3 

Extension key

|extension_key|

Package name

netresearch/nr-image-optimize

Version

1.1

Language

en


The netresearch/nr-image-optimize extension provides on-demand image optimization for TYPO3. Images are processed lazily via middleware when first requested, with support for modern formats (WebP, AVIF), responsive srcset generation, and automatic format negotiation.

Introduction 

Learn what the extension does, its features, and system requirements.

Installation 

Install via Composer or the Extension Manager.

Configuration 

Configure the SourceSetViewHelper, render modes, responsive srcset, and lazy loading.

Usage 

Integrate responsive images into your Fluid templates with practical examples.

Maintenance 

Manage processed images and check system requirements in the backend module.

Developer reference 

Architecture overview and PHP API reference.

Introduction 

What does it do? 

The |extension_name| extension (|extension_key|) optimizes images in TYPO3 on demand. Instead of processing every image at upload time, images are converted and resized lazily when first requested through the /processed/ URL path.

This approach reduces server load during content editing and ensures that only images actually viewed by visitors are processed.

Features 

  • Lazy image processing. Images are optimized only when a visitor first requests them.
  • Modern format support. Automatic WebP and AVIF conversion with fallback to original formats.
  • Responsive images. Built-in SourceSetViewHelper for srcset and sizes generation.
  • Render modes. Choose between cover and fit resize strategies.
  • Width-based srcset. Optional responsive srcset with configurable width variants and sizes attribute.
  • Fetch priority. Native fetchpriority attribute support for Core Web Vitals optimization.
  • Middleware-based processing. Lightweight frontend middleware intercepts /processed/ requests.
  • Backend maintenance module. View statistics, check system requirements, and clear processed images.
  • Powered by Intervention Image. Uses the Intervention Image library for reliable image manipulation.

Requirements 

  • PHP 8.1, 8.2, 8.3, or 8.4.
  • TYPO3 12.4.
  • Intervention Image library 3.11+ (installed automatically via Composer).

Installation 

Manual installation 

  1. Download the extension from the TYPO3 Extension Repository.
  2. Upload to typo3conf/ext/.
  3. Activate the extension in the Extension Manager.

Setup 

The extension works out of the box after installation. No additional configuration is required. Images accessed through the /processed/ path are automatically optimized by the frontend middleware.

Configuration 

The extension works out of the box with sensible defaults. Images are automatically optimized when accessed via the /processed/ path. All configuration happens through ViewHelper attributes in your Fluid templates.

SourceSetViewHelper 

The SourceSetViewHelper generates responsive <img> tags with srcset attributes.

Basic ViewHelper usage
{namespace nr=Netresearch\NrImageOptimize\ViewHelpers}

<nr:sourceSet file="{image}"
              width="1200"
              height="800"
              quality="85"
              sizes="(max-width: 768px) 100vw, 50vw"
/>
Copied!

Parameters 

file

file
Type
object
Required

true

Image file resource (FAL file reference). Either file or path must be provided.

path

path
Type
string

URI string path to the image, typically generated via f:uri.image(). Use path instead of file when passing a pre-resolved image URI. Either file or path must be provided.

width

width
Type
integer

Target width in pixels.

height

height
Type
integer

Target height in pixels.

quality

quality
Type
integer
Default
100

JPEG/WebP quality (1--100).

sizes

sizes
Type
string

Responsive sizes attribute for the generated <img> tag.

format

format
Type
string
Default
auto

Output format. Allowed values: auto, webp, avif, jpg, png.

mode

mode
Type
string
Default
cover

Render mode. cover resizes images to fully cover the given dimensions. fit resizes images to fit within the given dimensions.

responsiveSrcset

responsiveSrcset
Type
boolean
Default
false

Enable width-based responsive srcset instead of density-based 2x srcset.

widthVariants

widthVariants
Type
string|array
Default
480, 576, 640, 768, 992, 1200, 1800

Width variants for responsive srcset (comma-separated string or array).

fetchpriority

fetchpriority
Type
string

Native HTML fetchpriority attribute. Allowed values: high, low, auto. Omitted when empty.

Source set configuration 

Define source sets per media breakpoint via the set attribute:

Source set with breakpoint-specific dimensions
<nr:sourceSet
    path="{f:uri.image(
        image: image,
        width: '960',
        height: '690',
        cropVariant: 'default'
    )}"
    set="{
        480:{width: 160, height: 90},
        800:{width: 400, height: 300}
    }"
/>
Copied!

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.
Using fit mode
<nr:sourceSet
    path="{f:uri.image(
        image: image,
        width: '960',
        height: '690',
        cropVariant: 'default'
    )}"
    width="960"
    height="690"
    mode="fit"
/>
Copied!

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.

Backward compatibility 

By default responsiveSrcset is false, preserving the existing 2x density-based srcset behavior. All existing templates continue to work without modifications.

Usage 

This chapter shows practical examples for integrating responsive images into your Fluid templates.

Register the namespace 

Add the ViewHelper namespace at the top of your Fluid template or register it globally:

Inline namespace declaration
{namespace nr=Netresearch\NrImageOptimize\ViewHelpers}
Copied!

Basic responsive image 

Simple responsive image with quality setting
<nr:sourceSet file="{image}"
              width="1200"
              height="800"
              quality="85"
              sizes="(max-width: 768px) 100vw, 50vw"
/>
Copied!

Responsive width-based srcset 

Enable width-based srcset generation with a sizes attribute for improved responsive image handling. This is opt-in per usage.

Enable responsive srcset with default variants
<nr:sourceSet
    path="{f:uri.image(
        image: image,
        maxWidth: size,
        cropVariant: 'default'
    )}"
    width="{size}"
    height="{size * ratio}"
    alt="{image.properties.alternative}"
    lazyload="1"
    mode="fit"
    responsiveSrcset="1"
/>
Copied!

Custom width variants 

Specify custom breakpoints for srcset
<nr:sourceSet
    path="{f:uri.image(
        image: image,
        maxWidth: size,
        cropVariant: 'default'
    )}"
    width="{size}"
    height="{size * ratio}"
    responsiveSrcset="1"
    widthVariants="320,640,1024,1920,2560"
    sizes="(max-width: 640px) 100vw,
           (max-width: 1024px) 75vw, 50vw"
/>
Copied!

Output comparison 

Legacy mode (responsiveSrcset=false or not set):

Density-based 2x srcset output
<img src="/processed/fileadmin/image.w625h250m1q100.jpg"
     srcset="/processed/fileadmin/image.w1250h500m1q100.jpg x2"
     width="625"
     height="250"
     loading="lazy">
Copied!

Responsive mode (responsiveSrcset=true):

Width-based srcset output
<img src="/processed/fileadmin/image.w1250h1250m1q100.png"
     srcset="/processed/fileadmin/image.w480h480m1q100.png 480w,
             /processed/fileadmin/image.w576h576m1q100.png 576w,
             /processed/fileadmin/image.w640h640m1q100.png 640w,
             /processed/fileadmin/image.w768h768m1q100.png 768w,
             /processed/fileadmin/image.w992h992m1q100.png 992w,
             /processed/fileadmin/image.w1200h1200m1q100.png 1200w,
             /processed/fileadmin/image.w1800h1800m1q100.png 1800w"
     sizes="auto, (min-width: 992px) 991px, 100vw"
     width="991"
     loading="lazy"
     alt="Image">
Copied!

Fetch priority for Core Web Vitals 

Use the fetchpriority attribute to hint the browser about resource prioritization, improving Largest Contentful Paint (LCP) scores:

High priority for above-the-fold hero image
<nr:sourceSet file="{heroImage}"
              width="1920"
              height="1080"
              fetchpriority="high"
/>
Copied!

Maintenance 

The extension provides a backend module accessible via Admin Tools > Processed Images Maintenance.

Overview 

View statistics about processed images:

  • File count and total size.
  • Directory count.
  • Largest files.
  • File type distribution.

System requirements check 

Verify all technical prerequisites and tool availability:

  • PHP version and extensions (Imagick, GD).
  • ImageMagick / GraphicsMagick capabilities (WebP, AVIF support).
  • Composer dependencies (Intervention Image).
  • TYPO3 version compatibility.
  • CLI tools (magick, convert, identify, gm -- optional).

Clear processed images 

Remove all on-demand generated images. Images are regenerated automatically when first accessed again.

Developer reference 

Architecture 

The extension uses a middleware-based approach for image processing:

  1. ProcessingMiddleware intercepts frontend requests matching the /processed/ path.
  2. Processor handles image optimization, format conversion, and caching.
  3. SourceSetViewHelper generates responsive <img> markup in Fluid templates.
  4. MaintenanceController provides the backend module for statistics and cleanup.

Directory structure 

  • Classes/

    • Controller/

      • MaintenanceController.php
    • Middleware/

      • ProcessingMiddleware.php
    • Service/

      • SystemRequirementsService.php
    • Processor.php
    • ViewHelpers/

      • SourceSetViewHelper.php
  • Configuration/

    • Backend/

      • Modules.php
    • Icons.php
    • RequestMiddlewares.php
    • Services.yaml

Processing middleware 

class ProcessingMiddleware
Fully qualified name
\Netresearch\NrImageOptimize\Middleware\ProcessingMiddleware

Frontend middleware registered before typo3/cms-frontend/site. Intercepts requests whose path starts with /processed/ and delegates image processing to the Processor class.

Processor 

class Processor
Fully qualified name
\Netresearch\NrImageOptimize\Processor

Core image processing engine. Parses the requested URL to extract dimensions, quality, mode, and format parameters. Uses the Intervention Image library for actual image manipulation. Processed images are cached on disk to avoid repeated processing.

SourceSetViewHelper 

class SourceSetViewHelper
Fully qualified name
\Netresearch\NrImageOptimize\ViewHelpers\SourceSetViewHelper

Fluid ViewHelper that generates <img> tags with srcset attributes for responsive image delivery. Supports both density-based (2x) and width-based responsive srcset modes.

Testing 

Run the full test suite
composer ci:test
Copied!

Individual test commands:

Available test commands
composer ci:test:php:cgl      # Code style
composer ci:test:php:lint     # PHP syntax
composer ci:test:php:phpstan  # Static analysis
composer ci:test:php:unit     # PHPUnit tests
composer ci:test:php:rector   # Code quality
Copied!

Changelog 

1.1.0 

New in version 1.1.0

Comprehensive quality review: security hardening, performance improvements, backend maintenance module, responsive srcset, and expanded test coverage.

  • Added backend maintenance module with directory statistics, system requirements check, and clear processed images action.
  • Added responsive width-based srcset generation as opt-in feature.
  • Added widthVariants parameter for custom breakpoints.
  • Added sizes parameter for responsive image sizing.
  • Added fetchpriority attribute for resource hints.
  • Added path traversal hardening and XSS prevention.
  • Added DoS prevention via dimension and quality clamping.
  • Added HTTP caching headers (Cache-Control: immutable, ETag, Last-Modified).
  • Added 15 language localizations.
  • Added 33+ unit tests, fuzz tests, and functional tests.
  • Added full TYPO3 documentation structure.

1.0.3 

  • Fixed Processor::getValueFromMode() TypeError for non-matching URLs (crawler/bot srcset descriptors).

1.0.2 

  • Fixed nullable dirname access in SourceSetViewHelper.

1.0.1 

  • Added ext_emconf.php for classic installation.

1.0.0 

  • Initial stable release.
  • GitHub Actions CI workflows.

0.1.5 

  • Fixed strtolower() null argument error.
  • Fixed array offset access on boolean value.
  • Allowed numeric characters in file extensions.
  • Added extension icon.
  • Corrected crop variant examples.
  • Improved lazy loading behavior.