
Anforderungen
- Node.js >= 22 (Node 24 empfohlen)
- npm >= 10
Technologie-Stack
- Vite 8 – Build-Tool mit HMR
- Vue.js 3.5 – Interaktive Komponenten (TodoList, GallerySwiper, SwiperSlider)
- Bootstrap 5.3 – UI-Framework
- Sass 1.99 – CSS-Vorverarbeitung (Modern-Compiler-API)
- PostCSS – preset-env, pxtorem
- ESLint 10 / Stylelint 17 – Codequalität
- Swiper 12 – Touch-Slider (integriert über Vue-Komponenten)
- Jarallax 3 – Parallax-Scrolling
Schnellstart
cd Build
npm ci
npm run watch # Auto-rebuild on file changes
In einem mpc-Monorepo, in dem DDEV läuft, können Sie den Build auch aus dem Stammverzeichnis der Website starten: ddev mp-core-build (entspricht npm run build innerhalb libs/mp-core/Build/).
Die Ausgabe erfolgt in Resources/Public/ (JavaScripts, Stylesheets, Schriftarten, Icons, Bilder, Favicons, Backend-Layouts).
| Skript | Beschreibung |
|---|---|
build | Lint + Produktions-Build (minimiert, optimiert) + Bundle-Größenprüfung |
build:analyze | Produktions-Build mit rollup-plugin-visualizer (schreibt reports/bundle-stats.html) |
dev | Lint + Entwicklungs-Build mit Source-Maps |
watch | Entwicklungs-Build mit Dateiüberwachung |
check-size | Führen Sie das Bundle-Größen-Budget-Gate aus für Resources/Public/ |
lint | ESLint + Stylelint ausführen |
eslint / eslint.fix | JavaScript-Linting |
stylelint / stylelint.fix | CSS/SCSS-Linting |
Sauberes Build: rm -rf node_modules Resources/Public && npm ci && npm run build
Projektstruktur
Build-Verzeichnis
Build/
├── Assets/
│ ├── Fonts/ # Web fonts (WOFF2)
│ ├── Images/ # Source images, Icons/
│ ├── Scripts/ # JavaScript/Vue
│ │ ├── code/ # Feature modules
│ │ │ ├── Utils/ # Shared utilities (domUtils.js, …)
│ │ │ ├── Vue/ # vue-initialisation.js (component registry)
│ │ │ └── Navigation/ # Primary / Secondary / Tertiary
│ │ └── components/ # Vue SFCs
│ ├── Scss/ # SCSS (ITCSS layers)
│ │ ├── Base/ # Variables, fonts
│ │ ├── Elements/ # Base elements
│ │ ├── Mixins/ # SCSS mixins
│ │ ├── Modules/ # UI components
│ │ ├── Templates/ # Layout helpers
│ │ └── Extensions/ # TYPO3 extension overrides
│ └── Static/ # Copied as-is (BackendLayouts, Favicons)
├── vite.config.js
├── eslint.config.js
├── stylelint.config.js
└── postcss.config.js
Ressourcenverzeichnis
Resources/
├── Private/ # Fluid templates (not web-accessible)
│ ├── Backend/, Language/, Layouts/, Partials/, Templates/
├── Extensions/ # Extension template overrides
│ ├── fluid_styled_content/, form/, indexed_search/, news/
└── Public/ # Compiled assets (web-accessible)
├── Fonts/, Icons/, Images/, JavaScripts/, StyleSheets/, Favicons/
Bundle-Budgets
Jeder npm run build endet mit dem Aufruf von scripts/check-bundle-size.js. Das
Skript liest jede kompilierte JS-/CSS-Datei aus Resources/Public/, berechnet die
Größen für gzip (Stufe 9) und Brotli (Qualität 11), vergleicht diese mit
scripts/bundle-budgets.jsonund beendet die Ausführung mit einem Wert ungleich Null, wenn ein dateispezifisches oder
das Gesamtbudget überschritten wird. Eine WARN-Meldung (orangefarbene Warnung) wird ausgegeben, wenn ein
Bundle innerhalb von 10 % seines Budgets liegt – das ist das Signal, eine Refaktorisierung vorzunehmen, bevor
die nächste Funktion uns über die Grenze treibt.
Wenn ein Bundle aus legitimen Gründen gewachsen ist (neue Komponente, beabsichtigtes Upgrade einer Abhängigkeit),
aktualisieren Sie scripts/bundle-budgets.json im selben Commit wie die Größenänderung
vor. Erhöhen Sie niemals ein Budget, nur um die Überprüfung zu umgehen.
Baseline (03.06.2026)
Erfasst mit Vite 8, Bootstrap 5.3.8, Vue 3.5, Swiper 12.
| Bundle | Roh | Gzip | Brotli |
|---|---|---|---|
bootstrap.js | 65,9 KiB | 20,1 KiB | 17,9 KiB |
screen.js | 33,0 KiB | 9,6 KiB | 8,6 KiB |
vue.js | 239,8 KiB | 72,5 KiB | 63,8 KiB |
navigationPrimary.js | 1,7 KiB | 662 B | 560 B |
navigationSecondary.js | 5,6 KiB | 1,3 KiB | 1,2 KiB |
navigationTertiary.js | 4,4 KiB | 1,3 KiB | 1,1 KiB |
paginationTruncate.js | 1,7 KiB | 733 B | 579 B |
theme-init.js | 222 B | 183 B | 129 B |
bootstrap.css | 174,1 KiB | 24,2 KiB | 17,5 KiB |
screen.css | 67,4 KiB | 10,6 KiB | 9,1 KiB |
vue.css | 24,2 KiB | 3,9 KiB | 3,4 KiB |
navigationPrimary.css | 7,8 KiB | 1,8 KiB | 1,6 KiB |
navigationSecondary.css | 25,2 KiB | 3,6 KiB | 3,2 KiB |
navigationTertiary.css | 17,3 KiB | 3,2 KiB | 2,8 KiB |
ckeditor.css | 18,3 KiB | 2,7 KiB | 2,3 KiB |
print.css | 1,3 KiB | 559 B | 432 B |
| insgesamt | -- | 158,7 KiB | 135,8 KiB |
Nach der Refaktorisierung von „manual-chunk“ und „dynamic-import“ (siehe „Vendor-Aufteilung“
weiter unten) ist zu erwarten, vue.js erheblich schrumpfen, da die Vue-Laufzeitumgebung,
Swiper und die drei Vue-SFCs in langlebige vendor-* / pro-SFC-
Chunks verschoben werden. Führen Sie den Befehl npm run check-size einmal nach dem nächsten Build und senken Sie
die betroffenen Budgets in scripts/bundle-budgets.json.
„Vendor Splitting“
vite.config.js definiert eine manualChunks Map, die diese
node_modules Pfade in benannte Anbieter-Chunks zusammenfasst:
| Block | Inhalt |
|---|---|
vendor-vue | vue, @vue/* |
vendor-swiper | swiper |
vendor-bootstrap | bootstrap |
vendor-popper | @popperjs/core |
vendor-jarallax | jarallax |
Anbieter-Blöcke ändern sich nur, wenn sich die festgesteckte Abhängigkeit ändert; daher verbleiben sie über Deployments hinweg im HTTP-Cache, während sich unser eigener Anwendungscode ändert.
Code-Splitting bei Vue-Komponenten
code/Vue/vue-initialisation.js verwendet dynamische import() pro Komponente, sodass
jeder .vue SFC zu einem eigenen Chunk kompiliert. Eine Seite, die nur
SwiperSlider nie heruntergeladen TodoList oder GallerySwiper. Fügen Sie neue
Komponenten hinzu, indem Sie die componentLoaders Map in
vue-initialisation.js.
On-Demand-Anbieter: Jarallax
code/jarallax.js lädt das Jarallax-Anbieter-Bundle verzögert über dynamische
import('jarallax'), abhängig von einer document.querySelectorAll('.grid-parallax')
Präsenzprüfung. Der .grid-parallax Wrapper wird nur ausgegeben,
fluid_styled_content/Layouts/Container.html , wenn ein Editor das
Parallax-Kontrollkästchen (grid_parallax = 1) bei einem ce_container-artigen
Inhaltselement aktiviert.
Auswirkung: Seiten ohne Parallax-Container fordern den
vendor-jarallax-*.js Chunk (~26 KiB im Rohformat / ~7 KiB gzip / ~6 KiB brotli) an.
Dank der manualChunks
; lediglich die Netzwerkanfrage wechselt von „eager“ zu „deferred“.
Visualisierung des Bundles
npm run build:analyze
Schreibt Build/reports/bundle-stats.html (Treemap, gzip- und Brotli-fähig,
git-ignoriert). Direkt im Browser öffnen; kein Server erforderlich.
Vite-Einstiegspunkte
Definiert in Build/vite.config.js:
| Bundle | Zweck |
|---|---|
bootstrap.js | Initialisierung des Bootstrap-Frameworks |
screen.js | Haupt-Frontend (sticky Header, Theme usw.) |
vue.js | Vue.js 3-Komponenten (einschließlich Swiper-Integration) |
navigationPrimary/Secondary/Tertiary.js | Navigationsebenen |
print.js | Druckspezifische Stile |
backend.js | TYPO3-Backend-Stile |
ckeditor.js | CKEditor-RTE-Stile |
Hinweis: Swiper ist in das
vue.jsBundle integriert – es gibt keinen separatenswiper.jsEinstiegspunkt.
Neuen Eintrag hinzufügen
- Erstellen Sie eine JS-Datei in
Build/Assets/Scripts/ - Registrieren unter
vite.config.js - Ausführen
npm run watch - In Fluid einbinden:
<f:asset.script identifier="myfeature" src="EXT:mp_core/Resources/Public/JavaScripts/myfeature.js" />
<f:asset.css identifier="myfeature" href="EXT:mp_core/Resources/Public/StyleSheets/myfeature.css" />
JavaScript-Architektur
Funktionsmodule (Build/Assets/Scripts/code/)
Kern: main.js, i18n.js, i18nLinkHelper.js
UI: jarallax.js, modalGallery.js, openAccordionAndTabs.js, pagination.js, sticky.js, totop.js
Navigation: nav-toggle.js, Navigation/Primary/navigation.js, Navigation/Secondary/navigation.js, Navigation/Tertiary/navigation.js
Layout: moveHeaderDate.js, moveMeta.js, theme.js
Gemeinsam genutzte Hilfsfunktionen (code/Utils/domUtils.js)
debounce(func, wait)-- Leistungsoptimierte Handhabung von Größenanpassung und BildlauftoggleNavState(...)-- Geöffneter/geschlossener Zustand der NavigationhandleDropdownVisibility(element, showCb, hideCb)-- Bootstrap-Dropdown-EreignissetoggleAriaLabelAndTitle(element, openLabel, closeLabel)-- Barrierefreies Umschalten von Beschriftungen
Vue.js-Komponenten
Befindet sich in Build/Assets/Scripts/components/:
| Komponente | Beschreibung |
|---|---|
TodoList.vue | Interaktive To-Do-Liste mit localStorage, registriert als CType mpcore_todolist |
GallerySwiper.vue | Swiper-basiertes Galerie-Karussell für das Galerie-Inhaltselement |
SwiperSlider.vue | Generischer Swiper-Slider für Container-Slider-Elemente |
Die Registrierung der Komponenten erfolgt in code/Vue/vue-initialisation.js.
Vue-Mounts auf Elementen mit data-container="vue" und data-component="ComponentName" (siehe VueComponents.typoscript und Vorlagen für Inhaltselemente). Optionale data-* Attribute übergeben Props (z. B. data-card-title bei TodoList).
Eine neue Komponente erstellen
- Erstellen Sie
.vueDatei inBuild/Assets/Scripts/components/ - Registrieren in
code/Vue/vue-initialisation.js - Erstellen und über
<f:asset.script>in Fluid (dervue.jsEinstiegspunkt bindet registrierte Komponenten automatisch ein).
SCSS-Architektur (ITCSS)
Ebenen von geringer bis hoher Spezifität:
- Einstellungen (
Base/) – Variablen, Schriftarten, Farbtabellen - Tools (
Mixins/) – Funktionen, Mixins (keine CSS-Ausgabe) - Allgemein – Zurücksetzen, Normalisieren (aus Bootstrap)
- Elemente (
Elements/) – Grundlegende HTML-Elemente - Objekte – Layoutmuster
- Komponenten (
Modules/) – Gestaltete UI-Komponenten - Hilfsfunktionen – Hilfsklassen
Bootstrap-Anpassung
- Helles Design:
Build/Assets/Scss/Base/Bootstrap/_custom-variables.scss - Dunkles Design:
Build/Assets/Scss/Base/Bootstrap/_custom-variables-dark.scss
Verwaltung von Assets
| Asset-Typ | Muster |
|---|---|
| Bilder in SCSS | url('../../Images/Icons/icon.png') (relativer Pfad) |
| Schriftarten | @include font-face('Name', '../../Fonts/file', 400, normal, woff2) |
| Inline-SVG | svg-load('../Images/Icons/arrow.svg') |
| Statische Dateien | Build/Assets/Static/ -> kopiert nach Resources/Public/ |
Vorlagenintegration
Fluid
<f:asset.css identifier="screen" href="EXT:mp_core/Resources/Public/StyleSheets/screen.css" />
<f:asset.script identifier="screen" src="EXT:mp_core/Resources/Public/JavaScripts/screen.js" />
TypoScript
page {
includeCSS.screen = EXT:mp_core/Resources/Public/StyleSheets/screen.css
includeJSFooter.screen = EXT:mp_core/Resources/Public/JavaScripts/screen.js
}
Priorität der Vorlagenpfade: Höhere Zahlen haben Vorrang vor niedrigeren (0 = Kern, 10 = Erweiterung, 20+ = Projekt).
Ersetzungen durch Erweiterungen
| Erweiterung | Pfad | Anmerkungen |
|---|---|---|
| fluid_styled_content | Resources/Extensions/fluid_styled_content/Private/ | Im Bootstrap-5-Stil |
| Formular | Resources/Extensions/form/ | Bootstrap-Formulare + YAML-Konfiguration |
| Nachrichten | Resources/Extensions/news/ | Listen-, Detail- und Kategorieansichten |
| Indexierte Suche | Resources/Extensions/indexed_search/ | Bootstrap-Suchergebnisse |
Bewährte Vorgehensweisen
JavaScript: Modularer Code in code/, gemeinsam genutzte Muster in Utils/, Debounce bei Größenänderung/Scrollen, Event-Delegation, ARIA-Labels, Lint vor dem Commit.
SCSS: ITCSS-Ebenen beachten, CSS-Variablen für das Theming, logische Eigenschaften für RTL, maximal 3 Verschachtelungsebenen, Mobile-First- min-width Abfragen.
Vue.js: Single-File-Komponenten, bereichsbezogene Stile, Prop-Validierung, Composition-API für komplexe Logik.
Fehlerbehebung
| Problem | Lösung |
|---|---|
| 404-Fehler bei Schriftarten | Überprüfen Sie ../ Segmente aus SCSS auf Fonts/ |
| Fehlende Bilder im CSS | Überprüfe den Pfad im Assets/Images/ |
| Bundle zu groß | Nur benötigte Bootstrap-Komponenten importieren |
| Änderungen werden nicht angezeigt | Browser- und TYPO3-Cache leeren |
Wichtig: Niemals Resources/Public/ direkt. Bearbeiten Sie immer in Build/Assets/ und führen Sie npm run build.
Weiterführende Informationen
- Favicons – Favicon-Dateien und Fluid-Partial (nicht mit
output.html) - Konfiguration – Site Sets, TypoScript, TCA
- Vite | Vue.js | Bootstrap 5 | ITCSS