Zum Inhalt springen

Frontend

Build-System, Asset-Pipeline, JavaScript/SCSS-Architektur und Best Practices.

MP-Core Logo

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).

SkriptBeschreibung
buildLint + Produktions-Build (minimiert, optimiert) + Bundle-Größenprüfung
build:analyzeProduktions-Build mit rollup-plugin-visualizer (schreibt reports/bundle-stats.html)
devLint + Entwicklungs-Build mit Source-Maps
watchEntwicklungs-Build mit Dateiüberwachung
check-sizeFühren Sie das Bundle-Größen-Budget-Gate aus für Resources/Public/
lintESLint + Stylelint ausführen
eslint / eslint.fixJavaScript-Linting
stylelint / stylelint.fixCSS/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.

BundleRohGzipBrotli
bootstrap.js65,9 KiB20,1 KiB17,9 KiB
screen.js33,0 KiB9,6 KiB8,6 KiB
vue.js239,8 KiB72,5 KiB63,8 KiB
navigationPrimary.js1,7 KiB662 B560 B
navigationSecondary.js5,6 KiB1,3 KiB1,2 KiB
navigationTertiary.js4,4 KiB1,3 KiB1,1 KiB
paginationTruncate.js1,7 KiB733 B579 B
theme-init.js222 B183 B129 B
bootstrap.css174,1 KiB24,2 KiB17,5 KiB
screen.css67,4 KiB10,6 KiB9,1 KiB
vue.css24,2 KiB3,9 KiB3,4 KiB
navigationPrimary.css7,8 KiB1,8 KiB1,6 KiB
navigationSecondary.css25,2 KiB3,6 KiB3,2 KiB
navigationTertiary.css17,3 KiB3,2 KiB2,8 KiB
ckeditor.css18,3 KiB2,7 KiB2,3 KiB
print.css1,3 KiB559 B432 B
insgesamt--158,7 KiB135,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:

BlockInhalt
vendor-vuevue, @vue/*
vendor-swiperswiper
vendor-bootstrapbootstrap
vendor-popper@popperjs/core
vendor-jarallaxjarallax

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:

BundleZweck
bootstrap.jsInitialisierung des Bootstrap-Frameworks
screen.jsHaupt-Frontend (sticky Header, Theme usw.)
vue.jsVue.js 3-Komponenten (einschließlich Swiper-Integration)
navigationPrimary/Secondary/Tertiary.jsNavigationsebenen
print.jsDruckspezifische Stile
backend.jsTYPO3-Backend-Stile
ckeditor.jsCKEditor-RTE-Stile
 

Hinweis: Swiper ist in das vue.js Bundle integriert – es gibt keinen separaten swiper.js Einstiegspunkt.

 

Neuen Eintrag hinzufügen

  1. Erstellen Sie eine JS-Datei in Build/Assets/Scripts/
  2. Registrieren unter vite.config.js
  3. Ausführen npm run watch
  4. 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 Bildlauf
  • toggleNavState(...) -- Geöffneter/geschlossener Zustand der Navigation
  • handleDropdownVisibility(element, showCb, hideCb) -- Bootstrap-Dropdown-Ereignisse
  • toggleAriaLabelAndTitle(element, openLabel, closeLabel) -- Barrierefreies Umschalten von Beschriftungen

Vue.js-Komponenten

Befindet sich in Build/Assets/Scripts/components/:

KomponenteBeschreibung
TodoList.vueInteraktive To-Do-Liste mit localStorage, registriert als CType mpcore_todolist
GallerySwiper.vueSwiper-basiertes Galerie-Karussell für das Galerie-Inhaltselement
SwiperSlider.vueGenerischer 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

  1. Erstellen Sie .vue Datei in Build/Assets/Scripts/components/
  2. Registrieren in code/Vue/vue-initialisation.js
  3. Erstellen und über <f:asset.script> in Fluid (der vue.js Einstiegspunkt bindet registrierte Komponenten automatisch ein).

SCSS-Architektur (ITCSS)

Ebenen von geringer bis hoher Spezifität:

  1. Einstellungen (Base/) – Variablen, Schriftarten, Farbtabellen
  2. Tools (Mixins/) – Funktionen, Mixins (keine CSS-Ausgabe)
  3. Allgemein – Zurücksetzen, Normalisieren (aus Bootstrap)
  4. Elemente (Elements/) – Grundlegende HTML-Elemente
  5. Objekte – Layoutmuster
  6. Komponenten (Modules/) – Gestaltete UI-Komponenten
  7. 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-TypMuster
Bilder in SCSSurl('../../Images/Icons/icon.png') (relativer Pfad)
Schriftarten@include font-face('Name', '../../Fonts/file', 400, normal, woff2)
Inline-SVGsvg-load('../Images/Icons/arrow.svg')
Statische DateienBuild/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

ErweiterungPfadAnmerkungen
fluid_styled_contentResources/Extensions/fluid_styled_content/Private/Im Bootstrap-5-Stil
FormularResources/Extensions/form/Bootstrap-Formulare + YAML-Konfiguration
NachrichtenResources/Extensions/news/Listen-, Detail- und Kategorieansichten
Indexierte SucheResources/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

ProblemLö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 angezeigtBrowser- 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

Seite teilen