Migrieren Sie typo3conf zu _assets in Composer TYPO3 v12+

Migrieren Sie typo3conf zu _assets in Composer TYPO3 v12+

FYI. This blog is translated by machine. Please ignore any spelling and grammar errors; sorry for such inconvenience. We appreciate your understanding and support.

Seit TYPO3 v12 ist Ihnen wahrscheinlich die Einführung des Ordners ‘_assets’ in ‘public’ bekannt. Eine der wichtigsten Änderungen in Composer-basierten TYPO3 v12-Instanzen ist der Übergang von ‘typo3conf` zu `_assets’. Dieser Artikel bietet eine umfassende Anleitung zur Migration von Assets wie CSS/JS, Fluid und TypoScript. 

Weil... Sicherheit wichtig ist!

Der TYPO3-Kern wurde von ‘typo3conf` nach `_assets’ migriert, hauptsächlich um die Sicherheit zu erhöhen. Mit `typo3-cms-composer-installers` v4 ist das gesamte `typo3conf` Verzeichnis nicht mehr öffentlich zugänglich. Stattdessen werden Assets wie CSS, JS und Bilder nun im Ordner `_assets` untergebracht. Diese Änderung stellt sicher, dass PHP-, Fluid- und TypoScript-Dateien mit TYPO3 v12 und darüber hinaus nicht mehr zugänglich sind.

Wussten Sie das schon?

Das Sicherheitskonzept von 'typo3/cms-composer-installers' ist stark inspiriert durch das typo3-secure-web von Helmut Hummel. 

Mit der Einführung von typo3/cms-composer-installers Version 4 (kompatibel mit TYPO3 v11) und Version 5 (obligatorisch seit TYPO3 v12.0) wurde die Praxis, Erweiterungen im typo3conf-Ordner für Composer-basierte Projekte zu speichern, abgeschafft. Eine ausführliche Darstellung dieser Änderungen findet sich im Artikel "TYPO3 und Composer - wir haben einen langen Weg hinter uns". Weitere Details finden Sie im Blog-Beitrag "Composer Changes for TYPO3 v11 and v12" In diesem Beitrag beschreibe ich die Herausforderungen, die bei der Sicherstellung der Kompatibilität mit der neuen Version typo3/cms-composer-installers auftreten.

Die auffälligste Änderung ist, dass Assets nun in Webseiten integriert werden, ohne dass der Name der Extension angezeigt wird. In den Versionen vor typo3/cms-composer-installers v4 sah die Struktur folgendermaßen aus:

<!--  Example from a web page using typo3/cms-composer-installers v3 --!>
<link rel="stylesheet" href="/typo3conf/ext/site_package/Resources/Public/Css/styles.css" media="all">

Im Gegensatz dazu enthält der Ordner typo3conf ab Version 4 keine Erweiterungen mehr. Stattdessen werden die Public/Resources-Ordner der Erweiterungen in einem neuen _assets-Ordner unter einem Verzeichnis verknüpft, das durch einen Hash-Wert und nicht durch den Namen der Erweiterung identifiziert wird:

<!-- Example from a web page using typo3/cms-composer-installers v4+ --!>
<link rel="stylesheet" href="/_assets/KsfKf4qImEAWgeI6dASF6e1hdBu2W/Css/styles.css" media="all">

Es ist wichtig zu beachten, dass alle Assets auf einer Website nun im Ordner Resources/Public einer Erweiterung gespeichert werden müssen. Folglich müssen alle fest kodierten Asset-Pfade, die typo3conf/ext verwenden, angepasst werden, um die Kompatibilität mit der aktualisierten Version zu gewährleisten. Daher habe ich systematisch nach typo3conf/ext-Pfaden in benutzerdefinierten Erweiterungen von Projekten gesucht und sie nach und nach durch die unten beschriebenen Lösungen ersetzt. Anschließend habe ich die Release Candidate-Version von typo3/cms-composer-installers als Anforderung in die composer.json-Datei des Projekts aufgenommen.

Hier finden Sie einige Tipps und Tricks zum Umgang mit statischen Asset-Pfaden in Ihren CSS-Dateien.

TYPO3 <= v11

// Wrong: The old way to include the `typo3conf` path in CSS
.CssClass {
  background-image: url("/typo3conf/ext/site_package/Resources/Public/Images/TheImage.jpeg");
}

Option 1: Relativer Pfad (TYPO3 >= v12)

// Correct: Switch assets and CSS to relative paths if they share the same extension.
.CssClass {
  background-image: url("../Images/TheImage.jpeg");
}

Option 2: Inline einbetten (TYPO3 >= v12)

// Small images like icons can be embedded inline using data URIs to manage assets and CSS across different extensions.
.CssClass {
  background-image: url("data:image/jpeg;base64,...");
}

Option 3: Erstellen eines eigenen Ordners (TYPO3 >= v12)

// Storing assets in a separate public folder like public/my_assets/ simplifies referencing.
.CssClass {
  background-image: url("/my_assets/Images/TheImage.jpeg");
}

Option 4: Verwendung von PSR-15 Middleware (TYPO3 >= v12)

// A PSR-15 middleware option enables streaming assets through a static URL.
.CssClass {
  background-image: url("/psr15_assets/Images/TheImage.jpeg");
}

Option 5: Hart kodierter Pfad (nicht empfohlen, (TYPO3 >= v12))

// Use full asset paths if assets and CSS are in different extensions and cannot be relocated, but be aware this might cause issues during TYPO3 upgrades.
.CssClass {
  background-image: url("/_assets/KsfKf4qImEAWgeI6dASF6e1hdBu2W/Images/MyImage.jpeg");
}

Daten Attribute

Manchmal enthält der JavaScript-Code Dateiverweise, bei denen Pfade direkt in das Skript eingebettet sind. Ein Beispiel hierfür ist eine Leaflet-Anwendung, in der benutzerdefinierte Markierungssymbole für eine Karte definiert werden.

TYPO3 <= v11

const icon = L.icon({
  iconUrl: '/typo3conf/ext/site_package/Resources/Public/Icons/Map/marker.svg',
  iconSize: [25, 41],
  iconAnchor: [12,41],
  popupAnchor: [1, -34],
  tooltipAnchor: [16, -28],
  shadowUrl: '/typo3conf/ext/site_package/Resources/Public/Icons/Map/shadow.svg',
  shadowSize: [41, 41],
});

TYPO3 >= v12

Wir können dieses Problem lösen, indem wir die Pfade zu den Icons innerhalb von Datenattributen in HTML mit Hilfe des Fluid URI Resource View Helper angeben.

<div id="map"
  data-icon="{f:uri.resource(path: 'Icons/Map/marker.svg')}" 
  data-shadow="{f:uri.resource(path: 'Icons/Map/shadow.svg')}"
></div>

Jetzt können wir die Pfade zu den Symbolen in JavaScript abrufen:

const mapElement = document.getElementById('map');
const icon = L.icon({
  iconUrl: mapElement.dataset.icon,
  iconSize: [25, 41],
  iconAnchor: [12,41],
  popupAnchor: [1, -34],
  tooltipAnchor: [16, -28],
  shadowUrl: mapElement.dataset.shadow,
  shadowSize: [41, 41],
});

Pfad substitution

Angenommen, Ihr Skript befindet sich unter EXT:site/Resources/Public/JavaScript/some-script.js, können Sie document.currentScript.src verwenden, um einen korrekten (pseudo-relativen) Pfad zu erzeugen:

const prefix = document.currentScript.src.replace(/\/JavaScript\/.*\.js.*/, '');
const image = `${prefix}/Images/some-image.png`;

Wenn Sie ein JavaScript-Modul (type="module") verwenden, können Sie das folgende Snippet verwenden, um den Pfad zu ersetzen:

const prefix = import.meta.url.replace(/\/JavaScript\/.*\.js.*/, '');
const image = `${prefix}/Images/some-image.png`;

Webpack Encore

Schauen Sie sich die Dokumentation von Sebastian Schreiber für die typo3_encore-Erweiterung an, um zu erfahren, wie Sie diese für die Verwendung von typo3/cms-composer-installers Version 4 konfigurieren.

Bitte lesen Sie Sebastian Schreibers Dokumentation für die typo3_encore-Erweiterung, um zu erfahren, wie Sie sie mit typo3/cms-composer-installers Version 4 einrichten.

TYPO3 >= v11

<!-- Old way of direct add `typo3conf` path --!>
<svg><use xlink:href="/typo3conf/ext/site_package/Resources/Public/Images/icons.svg#symbol"></use></svg>

TYPO3 >= v12

<!-- The solution now is to use the Uri.resource ViewHelper <f:uri.resource>  --!>
<link href="{f:uri.resource(path:'Css/MyCss.css')}" rel="stylesheet" />

Option 1: Bewährte Praxis mit EXT: Syntax

<!-- Syntax --!>
<link href="{f:uri.resource(path:'EXT:site_package/Resources/Public/Css/MyCss.css')}" rel="stylesheet" />
<!-- Output --!>
<link href="typo3/sysext/site_package/Resources/Public/Css/MyCss.css" rel="stylesheet" />

Option 2: Standard

<!-- Syntax --!>
<link href="{f:uri.resource(path:'Css/MyCss.css')}" rel="stylesheet" />
<!-- Output --!>
<link href="typo3conf/ext/site_package/Resources/Public/Css/MyCss.css" rel="stylesheet" />

Option 3: Mit Durchwahlname

<!-- Syntax --!>
<link href="{f:uri.resource(path:'Css/MyCss.css', extensionName: 'OtherExtension')}" rel="stylesheet" />
<!-- Output --!>
<link href="typo3conf/ext/other_extension/Resources/Public/Css/MyCss.css" rel="stylesheet" />

TYPO3 <= v11

<?php
declare(strict_types=1);
namespace Acme\Site\Provider;
use TYPO3\CMS\Core\Utility\GeneralUtility;
final class LogoProvider
{
    private const PATH_LOGO = 'typo3conf/ext/site/Resources/Public/Images/logo.png';
    public static function getLogo(): string
    {
        return GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . self::PATH_LOGO;
    }
}

TYPO3 >= v12

<?php
declare(strict_types=1);
namespace Acme\Site\Provider;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
final class LogoProvider
{
    private const PATH_LOGO = 'EXT:site/Resources/Public/Images/logo.png';
    public static function getLogo(): string
    {
        return rtrim(GeneralUtility::getIndpEnv('TYPO3_SITE_URL'), '/')
            . PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName(self::PATH_LOGO));
    }
}

Dennoch verwenden viele Leute TypoScript, um Assets wie Schriften, Bilder und css/js-Dateien hinzuzufügen.

// In TypoScript, Example of adding path using EXT:name.
page.headerData.10 = TEXT
page.headerData.10 {
  value = <link rel="preload" href="{path : EXT:site/Resources/Public/Fonts/Roboto.woff2}" as="font" type="font/woff2" crossorigin="anonymous">
  insertData = 1
}


// Another example is OpenGraph image is an absolute URL in meta tags:
page.meta {
  og:image.cObject = TEXT
  og:image.cObject {
    typolink {
      parameter.cObject = IMG_RESOURCE
      parameter.cObject.file = EXT:site/Resources/Public/Images/opengraph.png
      returnLast = url
      forceAbsoluteUrl = 1
    }
  }
}

Häufig ist es erforderlich, TSConfig-Dateien einzubinden.

TYPO3 <= v11

<INCLUDE_TYPOSCRIPT: source="FILE:typo3conf/ext/site/Configuration/TSconfig/User/name.tsconfig">

TYPO3 >= v12

<INCLUDE_TYPOSCRIPT: source="FILE:EXT:site_package/Configuration/TSconfig/User/name.tsconfig">

Möchten Sie Ihre eigene Konfiguration einfügen, z.B. CSS hinzufügen?

TYPO3 <= v11

editor:
  config:
    contentCss: '/typo3conf/ext/site_package/Resources/Public/Css/rte.css'

TYPO3 >= v12

editor:
  config:
    contentCss: 'EXT:site/Resources/Public/Css/rte.css'

Sie können eine eigene Middleware erstellen, um den Inhalt einer statischen Datei wie manifest.webmanifest zu generieren. Eine weitere Möglichkeit ist die Speicherung von Assets außerhalb von TYPO3, z. B. in Ihrem Web-Root oder einem speziellen statischen Verzeichnis wie static/.

Der Hash wird in TYPO3 Versionen 11 und 12 mit der Methode \TYPO3\CMS\Core\Utility\PathUtility->getAbsoluteWebPath() erzeugt.

Ausgehend vom vollständigen Dateipfad eines Assets, wie z.B. /var/www/html/vendor/site_vendor/site_package/Resources/Public/Css/Custom.css, werden der Wurzelpfad des Composers (in diesem Fall /var/www/html) und das mit Resources/Public beginnende Segment entfernt. Der verbleibende Pfad (in unserem Beispiel /vendor/site_vendor/site_package/) wird dann mit md5 gehasht.

Auf diese Weise bleibt der Hash konsistent, es sei denn, es werden Änderungen an der PathUtility-Methode oder Änderungen am Vendor-Ordner in der composer.json-Datei des Projekts vorgenommen. Es wird dringend empfohlen, die oben genannten Methoden zu verwenden, um Asset-Pfade zu generieren und sie nicht fest zu codieren.

Sie können stolz auf TYPO3 sein, denn es ist mit dem Composer-Modus noch sicherer geworden. In diesem Modus ist der Code Ihrer Erweiterung nicht mehr öffentlich verfügbar; nur die Assets sind zugänglich.

Das Paket ‘typo3/cms-composer-installers’ speichert sowohl Core- als auch Custom-Extensions im Ordner ‘vendor’.

Die ‘Resources/Public’-Ordner dieser Erweiterungen werden dann in den `_assets`-Ordner im Web-Root verlinkt, mit einem Hash-Ordnernamen, um den Namen der Erweiterung zu verschleiern.

Wenn Sie auf TYPO3 Version 12 oder höher im Composer-Modus aktualisieren, stellen Sie sicher, dass Sie die Pfade zu Ihrem benutzerdefinierten Extension-Code aktualisieren, einschließlich CSS/JS und Pfadeinstellungen in PHP, Fluid, TypoScript und RTE...

Viel Spaß bei der Migration auf _assets!

Your One-Stop Solutions for Custom TYPO3 Development

  • A Decade of TYPO3 Industry Experience
  • 350+ Successful TYPO3 Projects
  • 87% Repeat TYPO3 Customers
TYPO3 Service
service

Post a Comment

×
Captcha Code Kann das Bild nicht gelesen werden? Klicken Sie hier, um zu aktualisieren
  • user
    Andreas Fuchs 2024-08-02 um 11:51 am

    This blog post was really helpful for moving my TYPO3 setup to Composer in version 12. The guide on shifting assets from typo3conf to _assets was clear and easy to understand. The instructions and tips for handling CSS, JS, Fluid, and TypoScript were great. I recommend this for anyone migrating to TYPO3 v12!

  • user
    Sandra Frei 2024-07-21 um 6:28 pm

    The step-by-step guide and clear examples made the transition much easier to understand. I appreciate the emphasis on security and how the new structure improves it.One question I have is about the best practices for managing assets in a multi-extension setup—are there any specific strategies you recommend for that?

  • user
    Claudia Trommler 2024-06-11 um 12:25 pm

    Thank you for this comprehensive guide. It made the migration process much less intimidating. Our TYPO3 instance is running perfectly now. Can you recommend any tools to automate part of this migration?

  • user
    Patrick Dietrich 2024-06-04 um 3:10 pm

    I was struggling with this migration until I found your blog. The detailed explanations and examples were exactly what I needed.