[BUGFIX] TYPO3 v14: pre-resolve typo3_encore: TypoScript includes#1
Open
contemas-tschmidt wants to merge 2 commits into
Open
[BUGFIX] TYPO3 v14: pre-resolve typo3_encore: TypoScript includes#1contemas-tschmidt wants to merge 2 commits into
contemas-tschmidt wants to merge 2 commits into
Conversation
Remove TYPO3 12 compatibility
In TYPO3 v14, RequestHandler::processHtmlBasedRenderingSettings runs
every page.includeCSS / includeJS* entry through SystemResourceFactory
before forwarding to the PageRenderer. The factory rejects
"typo3_encore:<entry>" pseudo-paths as un-resolvable and the entry is
silently dropped (catch SystemResourceException -> continue;). Even
calling pageRenderer->addCssFile('typo3_encore:app') directly fails for
the same reason.
The legacy render-preProcess PageRenderer hook (PageRendererHooks)
therefore never sees these entries on v14 because they never reach
->cssFiles / ->jsLibs. End result: zero <link>/<script> tags
on the FE for any TS-driven encore include. (Fluid templates that
already use <e:renderWebpackLinkTags/> directly keep working — they
bypass TypoScript.)
Fix: add an AfterTypoScriptDeterminedEvent listener that walks the
page TypoScript array, resolves each "typo3_encore:" entry through
entrypoints.json, and calls pageRenderer's addCssFile / addJsFile /
addJsLibrary / addJsFooterFile / addJsFooterLibrary with the concrete
file paths the SystemResourceFactory accepts. Settings are read
directly from the FrontendTypoScript setup array because Extbase's
ConfigurationManager is not yet request-bound at this point in the
middleware chain (SettingsService -> ConfigurationManager would throw
NoServerRequestGivenException).
Multiple files inside one entry get distinct addJs*Library names via
basename() — the existing TagRenderer uses the same pattern.
Without this, runtime.js + entry.js collide on a single jsLibs key
and only the first survives.
Listener is gated behind Typo3Version::getMajorVersion() >= 14 so v13
keeps using the legacy render-preProcess hook (which v13's
RequestHandler still feeds through addCssFile without
SystemResourceFactory pre-filtering).
08e36b9 to
bf9d371
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On TYPO3 v14, every page.includeCSS / includeJS* entry routed through the legacy
PageRendererHooks::renderPreProcess hook ends up with no
<link>/<script>tagon the FE.
Root cause
v14's
RequestHandler::processHtmlBasedRenderingSettingswas changed (vs v13) toresolve every TS include via
SystemResourceFactorybefore it reaches thePageRenderer:
typo3_encore:appdoesn't match any registered SystemResource scheme, isn't a FALpath, isn't a relative public file →
CanNotResolveSystemResourceException→continue;and the entry is silently dropped. The legacyrender-preProcessPageRenderer hook never sees these entries because they never reach
$cssFiles/$jsLibs.Even calling
pageRenderer->addCssFile('typo3_encore:app')directly would fail inv14 —
addCssFileruns throughSystemResourceFactorytoo (handleAddedResource()).SystemResourceIdentifierFactoryisfinal readonlywith a hardcodedmatchon the four built-in identifier types (PKG, FILE, URI, legacy EXT:), so registering
a custom
typo3_encore:scheme isn't an option without core changes.Fix
Add
Classes/Integration/TypoScriptIncludesEventListener.phplistening onAfterTypoScriptDeterminedEvent. It:includeCSS./includeCSSLibs./includeJSlibs./includeJSFooterlibs./includeJS./includeJSFooter.).typo3_encore:<entry>(ortypo3_encore:<build>:<entry>) value,resolves the matching
entrypoints.jsonand looks up the concrete CSS / JSfile URLs.
pageRenderer->addCssFile / addJsFile / addJsLibrary / addJsFooterFile / addJsFooterLibrary— those URLs are real public paths thev14 SystemResourceFactory accepts when later invoked by the PageRenderer
(the eventual
addCssFileresolution uses the relative-public-path branchand succeeds).
When v14's
RequestHandler::processHtmlBasedRenderingSettingslater tries toprocess the same
typo3_encore:TypoScript entries it still drops themsilently — but by then the actual encore assets are already registered with
the singleton PageRenderer.
Why settings are read from FrontendTypoScript directly
Extbase's
ConfigurationManageris not yet request-bound atAfterTypoScriptDeterminedEventtime ($GLOBALS['TYPO3_REQUEST']is also unsetthat early — see
ApplicationType.phpdoc). Going throughSettingsService→ConfigurationManager::getConfiguration()throwsNoServerRequestGivenException.Reading
plugin.tx_typo3encore.settings.*directly offFrontendTypoScript::getSetupArray()and constructingEntrypointLookupsmanually side-steps the Extbase request dependency entirely.
Multi-file entries
Webpack entries can split into multiple files (
runtime.js + app.js). PageRendererkeys
jsLibsby$nameand silently drops duplicates. Each file is registeredunder
basename($file)as a unique name — the same trick the existingTagRendereruses.Gating
The listener is registered only on
Typo3Version::getMajorVersion() >= 14. v13keeps the legacy
render-preProcesspath because v13's RequestHandler doesn'tfilter through SystemResourceFactory.
Test plan
dev-typo3-14, FE<head>had no<link>/<script>tags. With this patch,app.css+runtime.js+app.jsshow up as expected.runtime.js + app.jsfor one entrypoint) now emitsboth, not just the first.
media="print"fromincludeCSS.app.media = printis honoured.listener would be nice but the AfterTypoScriptDeterminedEvent is hard to
mock cleanly — open to suggestions.
legacy path intact, but a maintainer with v13 setup should sanity-check).
🤖 Generated with Claude Code