Upgrading to 6.0.15: image aliases made on demand
Exponential 6.0.15 makes image aliases when the browser asks for them, not while the page renders. This page says what changes for an existing installation that moves to the 6.0.15 line, what you have to do yourself, and how to go back.
Feature reference: Image aliases made on demand · Web server rules: Web server recipes for image aliases made on demand · Help: Image aliases
In short
- On-demand is the default after the upgrade.
settings/image.ini [AliasSettings] AliasGeneration=on-demand: a template call computes a missing alias (URL, size) instead of converting it; the alias is made when the browser asks for it. Templates need no change, the database no migration. - Going back is one line:
AliasGeneration=renderinsettings/override/image.ini.append.php, then clear the INI cache. It can be switched both ways at any time. - Add the rewrite rules that send a missing storage image and
content/imageto the new entry scriptindex_image.php(Apache: copy.htaccess_rootagain, or put the four lines into the virtual host; nginx, LiteSpeed, Caddy: the recipes). Without them the site works, but slower. - Add
index_image.phpto any allow-list of runnable root scripts, andAddType image/avif .avifwhere the server does not know AVIF. - Request shield: give
content/image,index_image.phpand storage misses a budget of their own, or pages with many new images get answers 429. - Themes with their own pagelayout load
exp_image_swap.js, or placeholders stay until a reload. - New: Setup > Image aliases with the policies
setup/aliasesandsetup/managealiases, the commandexp:image:alias, three job types for expqueue, the logimagealias.log, the secretimage_alias_signing.
Contents
What changes
| Area | Before 6.0.15 | From 6.0.15 |
|---|---|---|
| A template asks for a missing alias | converted while the page renders | computed; made when the browser asks (content/image or index_image.php) |
| The URL of a missing alias | its storage path | /content/image/<signed token>/<file name> (OnDemandURL=token); an alias that exists keeps its storage URL |
| A missing storage image | 404 from the web server | index_image.php makes it (when the path names a configured alias of a published image) or answers a placeholder |
| A slow or failed image | a broken image, or a slow page | a neutral SVG placeholder of the right size; exp_image_swap.js swaps in the real image |
| Command line scripts | convert while rendering | unchanged: always render mode |
| Velocity | as PHP-FPM | as PHP-FPM, on demand (its workers follow the setting) |
| Publishing an image | no alias made | the new images' aliases are made in the background when expqueue is installed (PreGenerate=enabled) |
| Waiting for another process's alias | without limit | at most [ImageConverterSettings] LockTimeout seconds (60), one lock per alias file instead of per original |
| Parallel alias writes of one image | the last writer could drop the others' entries | entries stored meanwhile are merged |
| Removing an object | aliases of other siteaccesses could stay on disk | every alias of the image is removed |
New files and names:
index_image.phpin the installation root (the light entry script), the viewcontent/image(no policy check, no session; insite.ini [RoleSettings] PolicyOmitList[]and[SiteAccessSettings] AnonymousAccessList[]).design/standard/javascript/exp_image_swap.js, listed indesign.ini [JavaScriptSettings] FrontendJavaScriptList[].settings/expqueue.iniwith the job typesimage.alias.generate,image.alias.bulk,image.alias.resync.- Setup > Image aliases (
setup/aliases, right after Cache in the Setup menu), the feedsetup/aliasesfeed, the policiessetup/aliasesandsetup/managealiases, and Advanced > Image aliases in the content tree's context menu. ./console exp:image:alias(bin/php/expimagealias.php).imagealias.login the site's log directory.- The secret
image_alias_signing(Setup > Secrets), created on first use;image_alias_signing_previousafter a rotation. - Cache directories
var/<site>/cache/imagealias-locks,imagealias-slots,imagealias-staging. config.cluster.phpmay defineCLUSTER_IMAGE_ALIAS_ON_DEMAND(default on).- New settings in
image.ini [AliasSettings](OnDemandURL, Delivery, MaxWait, DraftTokenLifetime, SigningKeyGrace, PreferredConverter, Negotiate, Placeholder, SwapScript, PreGenerate, PreGenerateAliasList, PreGenerateFormats, MaxParallel, BulkNice, CacheMaxAge),[AliasStaging],[AliasSource_pro], andFormats[]per alias block.
What you do
Update the code as usual (
./console exp:upgrade --apply --to=v6.0.15), then regenerate the autoloads and clear the caches; under Velocity,./console exp:velocity deploy --kernel(it restarts Velocity, which writes the new routes).Install the rewrite rules for your web server:
Apache with
.htaccess: save your own lines, thencp .htaccess_root .htaccessagain.Apache with
AllowOverride None: add to the virtual host, before the storage passthroughRewriteRule ^var/([^/]+/)?storage/images(-versioned)?/.* - [L](in a<Directory>block):RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^var/([^/]+/)?storage/images(-versioned)?/.* index_image.php [L] RewriteRule ^([^/]+/)?content/image/ index_image.php [L] RewriteRule ^index_image\.php - [L]nginx, nginx in front of Apache, LiteSpeed/OpenLiteSpeed, a Caddyfile of your own, a database cluster: the recipes.
Velocity: nothing beyond the restart.
Allow the script: add
_imageto an allow-list of root scripts (for exampleindex(_rest|_treemenu|_cluster|_webdav|_soap|_image)?\.php), as forindex_webdav.php.AVIF:
AddType image/avif .avifin a virtual host that reads no.htaccess;avifin the extension list of an nginx static location in front of Apache.Request shield: take
rules/exponential.rulesof the nextexp_request_shieldrelease (budgetEXP-IMAGES), or add an image budget to your own rule file now; thenrequest-shield checkandtest(how).Your theme: if its pagelayout writes its own script tags, load
exp_image_swap.js(for example{ezscript( array( 'exp_image_swap.js' ) )}at the bottom of the page). If a template operator builds image URLs itself from the alias list, let it take$handler->imageAlias( $alias )['url'].expqueue (recommended): with the job queue running, publishing makes the new aliases in the background and slow visitor misses are finished there. Without it everything is made on demand.
Tune for pages with many images:
MaxParallelabout half the CPU cores,Formats[]only on large aliases,PreGenerateAliasList[]if publishing makes too much work (Performance and tuning).Open Setup > Image aliases (or
./console exp:image:alias status) and look at the checks.
Going back to render mode
# settings/override/image.ini.append.php
[AliasSettings]
AliasGeneration=renderThen php bin/php/ezcache.php --clear-tag=ini --allow-root-user, the content view cache, and under Velocity
./console exp:velocity deploy (its workers keep the settings of their warm-up). Pages render as before 6.0.15: the
template call converts a missing alias. Aliases made on demand stay and are used; WebP/AVIF variants stay on disk until
their alias is removed. The rewrite rules may stay: index_image.php still serves existing files and placeholders.
Switch back by removing the line.
Things to check after the upgrade
- A page with images that were never shown: every image appears (placeholders first on a slow server), and
imagealias.loghasevent=generatelines. - A storage path of an alias not made yet answers the image (the rule is in place), an address that names nothing the
SVG placeholder with 404 and
X-Image-Placeholder: 1(the commands are in Check it). - No
Set-Cookieon image answers; no 429 from the request shield on a page with many images. - An
.avifvariant is sent asimage/avif. - A root-owned
settings/override/image.ini.append.phpcannot be saved from Setup > Image aliases: give it to the web server's user.