Assets (CSS, JavaScript, Media)

The TYPO3 component responsible for rendering the HTML and adding assets to a TYPO3 frontend or backend page is called PageRenderer.

The PageRenderer collects all assets to be rendered, takes care of options such as concatenation or compression and finally generates the necessary tags.

There are multiple ways to add assets to the PageRenderer in TYPO3. For configuration options via TypoScript (usually used for the main theme files), see the TypoScript Reference. In extensions, both directly using the PageRenderer as well as using the more convenient AssetCollector is possible.

AssetCollector

The AssetCollector is a concept to allow custom CSS/JS code, inline or external, to be added multiple times in e.g. a Fluid template (via <f:asset.script> or <f:asset.css> Viewhelpers) but rendered only once in the output.

The priority flag (default: false) controls where the asset is included:

  • JavaScript will be output inside <head> if $priority == true or at the bottom of the <body> tag if $priority == false.

  • CSS will always be output inside <head>, yet grouped by $priority.

The AssetCollector helps to work with content elements as components, effectively reducing the CSS to be loaded. It leverages making use of HTTP/2 which removes the necessity to have all files concatenated into one file.

The AssetCollector class is implemented as a singleton (SingletonInterface). It replaces various other existing options in TypoScript and methods in PHP to insert Javascript code and CSS data.

Former methods:

use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;

$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
  • $GLOBALS['TSFE']->additionalHeaderData[$name] = $javascriptcode;

  • $GLOBALS['TSFE']->setJS($name, $javascriptcode)

  • $pageRenderer->addHeaderData($javascriptcode)

  • $pageRenderer->addCssFile($file)

  • $pageRenderer->addCssInlineBlock($name, $csscode)

  • $pageRenderer->addCssLibrary($file)

  • $pageRenderer->addJsFile($file)

  • $pageRenderer->addJsFooterFile($file)

  • $pageRenderer->addJsFooterLibrary($name, $file)

  • $pageRenderer->addJsFooterInlineCode($name, $javascriptcode)

  • $pageRenderer->addJsInlineCode($name, $javascriptcode)

  • $pageRenderer->addJsLibrary($name, $file)

The AssetCollector also collects information about "imagesOnPage", which can be used in cached and non-cached components.

The API

class TYPO3\CMS\Core\Page\AssetCollector

The Asset Collector is responsible for keeping track of - everything within <script> tags: javascript files and inline javascript code - inline CSS and CSS files

The goal of the asset collector is to: - utilize a single "runtime-based" store for adding assets of certain kinds that are added to the output - allow to deal with assets from non-cacheable plugins and cacheable content in the Frontend - reduce the "power" and flexibility (I'd say it's a burden) of the "god class" PageRenderer. - reduce the burden of storing everything in PageRenderer

As a side-effect this allows to: - Add a single CSS snippet or CSS file per content block, but assure that the CSS is only added once to the output.

Note on the implementation: - We use a Singleton to make use of the AssetCollector throughout Frontend process (similar to PageRenderer). - Although this is not optimal, I don't see any other way to do so in the current code.

https://developer.wordpress.org/reference/functions/wp_enqueue_style/

addJavaScript(string $identifier, string $source, array $attributes = [], array $options = [])
Parameters
  • $identifier (string) -- the identifier

  • $source (string) -- URI to JavaScript file (allows EXT: syntax)

  • $attributes (array) -- additional HTML <script> tag attributes, default: []

  • $options (array) -- ['priority' => true] means rendering before other tags, default: []

Return type

self

addInlineJavaScript(string $identifier, string $source, array $attributes = [], array $options = [])
Parameters
  • $identifier (string) -- the identifier

  • $source (string) -- JavaScript code

  • $attributes (array) -- additional HTML <script> tag attributes, default: []

  • $options (array) -- ['priority' => true] means rendering before other tags, default: []

Return type

self

addStyleSheet(string $identifier, string $source, array $attributes = [], array $options = [])
Parameters
  • $identifier (string) -- the identifier

  • $source (string) -- URI to stylesheet file (allows EXT: syntax)

  • $attributes (array) -- additional HTML <link> tag attributes, default: []

  • $options (array) -- ['priority' => true] means rendering before other tags, default: []

Return type

self

addInlineStyleSheet(string $identifier, string $source, array $attributes = [], array $options = [])
Parameters
  • $identifier (string) -- the identifier

  • $source (string) -- stylesheet code

  • $attributes (array) -- additional HTML <link> tag attributes, default: []

  • $options (array) -- ['priority' => true] means rendering before other tags, default: []

Return type

self

addMedia(string $fileName, array $additionalInformation)
Parameters
  • $fileName (string) -- the fileName

  • $additionalInformation (array) -- One dimensional hash map (array with non numerical keys) with scalar values

Return type

self

removeJavaScript(string $identifier)
Parameters
  • $identifier (string) -- the identifier

Return type

self

removeInlineJavaScript(string $identifier)
Parameters
  • $identifier (string) -- the identifier

Return type

self

removeStyleSheet(string $identifier)
Parameters
  • $identifier (string) -- the identifier

Return type

self

removeInlineStyleSheet(string $identifier)
Parameters
  • $identifier (string) -- the identifier

Return type

self

removeMedia(string $identifier)
Parameters
  • $identifier (string) -- the identifier

Return type

self

getMedia()
Return type

array

getJavaScripts(bool $priority = NULL)
Parameters
  • $priority (bool) -- the priority, default: NULL

Return type

array

getInlineJavaScripts(bool $priority = NULL)
Parameters
  • $priority (bool) -- the priority, default: NULL

Return type

array

getStyleSheets(bool $priority = NULL)
Parameters
  • $priority (bool) -- the priority, default: NULL

Return type

array

getInlineStyleSheets(bool $priority = NULL)
Parameters
  • $priority (bool) -- the priority, default: NULL

Return type

array

hasJavaScript(string $identifier)
Parameters
  • $identifier (string) -- the identifier

Return type

bool

hasInlineJavaScript(string $identifier)
Parameters
  • $identifier (string) -- the identifier

Return type

bool

hasStyleSheet(string $identifier)
Parameters
  • $identifier (string) -- the identifier

Return type

bool

hasInlineStyleSheet(string $identifier)
Parameters
  • $identifier (string) -- the identifier

Return type

bool

hasMedia(string $fileName)
Parameters
  • $fileName (string) -- the fileName

Return type

bool

Note

If the same asset is registered multiple times using different attributes or options, both sets are merged. If the same attributes or options are given with different values, those registered last will overwrite the existing ones. With the has methods it can be checked if an asset exists before generating it again, hence avoiding redundancy.

ViewHelper

There are also two ViewHelpers, the f:asset.css and the f:asset.script Viewhelper which use the AssetCollector API.

Rendering order

Currently, CSS and JavaScript registered with the AssetCollector will be rendered after their PageRenderer counterparts. The order is:

  • <head>

  • page.includeJSLibs.forceOnTop

  • page.includeJSLibs

  • page.includeJS.forceOnTop

  • page.includeJS

  • AssetCollector::addJavaScript() with 'priority'

  • page.jsInline

  • AssetCollector::addInlineJavaScript() with 'priority'

  • </head>

  • page.includeJSFooterlibs.forceOnTop

  • page.includeJSFooterlibs

  • page.includeJSFooter.forceOnTop

  • page.includeJSFooter

  • AssetCollector::addJavaScript()

  • page.jsFooterInline

  • AssetCollector::addInlineJavaScript()

Note

JavaScript registered with AssetCollector is not affected by config.moveJsFromHeaderToFooter.

Examples

Add a JavaScript file to the collector with script attribute data-foo="bar":

//use TYPO3\CMS\Core\Page\AssetCollector;
//use TYPO3\CMS\Core\Utility\GeneralUtility;

GeneralUtility::makeInstance(AssetCollector::class)
   ->addJavaScript('my_ext_foo', 'EXT:my_ext/Resources/Public/JavaScript/foo.js', ['data-foo' => 'bar']);

Add a JavaScript file to the collector with script attribute data-foo="bar" and priority which means rendering before other script tags:

GeneralUtility::makeInstance(AssetCollector::class)
   ->addJavaScript('my_ext_foo', 'EXT:my_ext/Resources/Public/JavaScript/foo.js', ['data-foo' => 'bar'], ['priority' => true]);

Add a JavaScript file to the collector with type="module" (by default, no type= is output for JavaScript):

GeneralUtility::makeInstance(AssetCollector::class)
   ->addJavaScript('my_ext_foo', 'EXT:my_ext/Resources/Public/JavaScript/foo.js', ['type' => 'module']);

Check if a JavaScript file with the given identifier exists:

$assetCollector = GeneralUtility::makeInstance(AssetCollector::class);
if ($assetCollector->hasJavaScript($identifier)) {
    // result: true - JavaScript with identifier $identifier exists
} else {
    // result: false - JavaScript with identifier $identifier does not exist
}

Events

There are two events available that allow additional adjusting of assets: