Nuxt-Aliases
newmeta-Themes definieren zwei Nuxt-Aliases mit fundamental unterschiedlichem Zweck — #extensions und #widgets/plugin-registry. Sie werden oft verwechselt. Diese Seite erklaert, wozu welcher Alias gut ist, und vor allem: welcher Alias nicht fuer User-Imports ist.
Die zwei Aliases
_theme/vue-base/nuxt.config.ts:
import { resolve } from 'node:path'
export default defineNuxtConfig({
alias: {
// Cross-Plugin-Imports
'#extensions': resolve(process.cwd(), '../../_public/extensions/core/backend'),
// Auto-generierte Pagebuilder-Widget-Map — NICHT manuell bearbeiten!
'#widgets/plugin-registry': resolve(process.cwd(), 'app/widgets/plugin-registry.js'),
}
})Beide Aliases sind auf den ersten Blick aehnlich (#-Prefix, beide mit "widget" im Namen), haben aber komplett verschiedene Aufgaben:
| Alias | Target | Zweck | Darfst du importieren? |
|---|---|---|---|
#extensions | _public/extensions/core/backend/ | Cross-Plugin-Imports ohne ../../../../-Pfade | Ja |
#widgets/plugin-registry | app/widgets/plugin-registry.js | Auto-generierte Widget-Map fuer den Pagebuilder-Rendering-Loop | Nein — keine User-Imports |
#extensions — Cross-Plugin-Imports
Dieser Alias ist fuer User-Imports gedacht: wenn ein Plugin A etwas aus einem anderen Plugin B braucht (Composable, Vue-Komponente, Helper-Datei), importiert es ueber diesen Alias — statt ueber lange relative Pfade.
Problem ohne Alias
Ohne #extensions braucht E-Learning fuenf ../ um ins Shop-Plugin zu kommen:
// E-Learning-Widget laedt Shop-User-Composable
import { registerUserCenterItem } from '../../../shop/widgets/user/template/useUserCenter'Das funktioniert, ist aber fragil:
- Bricht bei Umstrukturierung
- Unleserlich
- Keine IDE-Autocomplete aus dem Kontext
Mit #extensions
import { registerUserCenterItem } from '#extensions/shop/widgets/user/template/useUserCenter'Stabil, lesbar, macht Cross-Plugin-Abhaengigkeiten explizit sichtbar.
Typische Use-Cases
// User-Center-Registry importieren (Shop-Plugin)
import { registerUserCenterItem } from '#extensions/shop/widgets/user/template/useUserCenter'
// Vue-Komponente aus einem anderen Plugin
import MyCoursesView from '#extensions/elearning/widgets/elearning/template/MyCoursesUserCenter.vue'
// Helper aus einem Plugin
import { resolvePageUrl } from '#extensions/menueditor/widgets/menu/helpers/urls'
// Plugin-eigener Store importieren
import { useSw6Store } from '#extensions/shopware6/widgets/shared/sw6Store'Regel: alles unter _public/extensions/core/backend/ ist ueber #extensions/... erreichbar.
Details zur User-Center-Registrierung: Widgets › User-Center-Items.
#widgets/plugin-registry — NICHT fuer User-Imports
Dieser Alias zeigt auf eine auto-generierte JavaScript-Datei, die beim Cache-Rebuild erzeugt wird. Sie enthaelt ein Mapping widget_template → Vue-Komponente und wird ausschliesslich vom Pagebuilder-Rendering-Loop konsumiert.
Wie die Datei aussieht
// _theme/vue-base/app/widgets/plugin-registry.js
// AUTO-GENERATED — nicht manuell bearbeiten
// Theme: vue-base
import NewsletterWidget from '/absolute/pfad/.../emailmarketing/widgets/newsletter/template/index.vue'
import TitleBannerElementWidget from '/absolute/pfad/.../titleBannerElement/widgets/.../index.vue'
import ShopWidget from '/absolute/pfad/.../shop/widgets/shop/template/index.vue'
// … weitere Imports pro installiertem Widget
export default {
'newsletter': NewsletterWidget,
'titleBannerElement': TitleBannerElementWidget,
'shop': ShopWidget,
'checkout': CheckoutWidget,
// …
}Die Datei wird vom Core-Script vueRegistry.php (unter _public/extensions/core/backend/cache_settings/script/) beim Cache-Rebuild generiert. Das Script scannt alle widgets/*/template/index.vue-Dateien und erzeugt die Imports automatisch. Der Ziel-Pfad ist themenspezifisch: _theme/{theme}/app/widgets/plugin-registry.js.
Wer konsumiert sie?
Ausschliesslich PagebuilderWidget.vue:
import widgetRegistry from '#widgets/plugin-registry'
const Component = computed(() => widgetRegistry[widget.type])Am Laufzeit-Rendering eines platzierten Widgets sucht Vue ueber widget.type (z. B. "testimonial") die passende Komponente in der Map.
Nicht in eigenen Imports verwenden
#widgets/plugin-registry ist kein stabiler Import-Endpunkt:
- Datei wird bei jedem Cache-Rebuild komplett ueberschrieben
- Schluessel sind
widget_template-Strings, keine stabilen Identifier - Enthaelt absolute Pfade aus dem Build-Kontext — funktioniert nur im Theme des aktiven Projekts
Wer in eigenen Code die Widget-Komponente eines anderen Widgets braucht: direkten Import via #extensions/{plugin}/widgets/{widget}/template/index.vue verwenden.
Custom-Theme-Overrides
Der Registry-Generator beruecksichtigt Theme-spezifische Overrides:
_theme/{theme}/app/custom/{plugin}/widgets/{widget_template}/template/index.vueExistiert eine Override-Datei, wird sie statt der Original-Datei importiert. Der generierte plugin-registry.js enthaelt dann den Override-Pfad unter demselben widget_template-Key. Das erlaubt Themes, beliebige Plugin-Widgets ohne Plugin-Modifikation zu uebersteuern.
Details: Widgets › Widget-Anatomie › Custom-Theme-Overrides.
Entscheidungs-Hilfe
| Situation | Alias |
|---|---|
| "Ich will ein Composable aus einem anderen Plugin nutzen" | #extensions/{plugin}/.../composable |
| "Ich will eine Vue-Komponente aus einem anderen Plugin importieren" | #extensions/{plugin}/widgets/.../index.vue |
| "Ich will fuer mein eigenes Widget die Shop-Komponente anzeigen" | #extensions/shop/widgets/.../index.vue |
| "Ich will programmatisch alle Pagebuilder-Widgets auflisten" | NICHT ueber #widgets/plugin-registry — eigene Scan-Logik bauen |
"Ich will die Widget-Komponente fuer widget_template=testimonial laden" | Direkt via #extensions/{plugin}/widgets/testimonial/template/index.vue |
| "Ich will die Widget-Registry im Frontend debuggen" | Einmalig als Debug via import registry from '#widgets/plugin-registry'; console.log(registry) — aber niemals in Produktion |
Wann wird plugin-registry.js neu gebaut?
Der vueRegistry-Rebuild laeuft bei:
/admin/cache→ "Cache leeren"- Plugin-Installation/Deinstallation (Shop-, E-Learning- oder eigenes Plugin)
- Manueller Trigger (
vueRegistry.phpdirekt aufrufen)
Nicht automatisch bei:
- Nuxt-Dev-Server-Start (
npm run devreloaded nur Vue-Dateien, nicht die Registry) - Repository-Checkout (
git pull) - Aenderung einer existierenden
template/index.vue(die wird per Hot-Reload sowieso aktuell geladen, Registry bleibt gueltig)
Erforderlich bei:
- Neuem Widget unter
widgets/{widget}/template/index.vue - Neuem Custom-Theme-Override unter
_theme/{theme}/app/custom/... - Umbenennung eines
widget_templatein einem Plugin
Details zum Cache-System: Design-Tokens › Cache-Integration.
TypeScript-Typing fuer #extensions
Standardmaessig hat der Alias keine Types — jede Datei dahinter muss ihre Types selbst exportieren. Beispiel:
// _public/extensions/core/backend/shop/widgets/user/template/useUserCenter.ts
export interface UserCenterItem { … }
export function registerUserCenterItem(item: UserCenterItem) { … }Beim Import kommt die Type-Info automatisch mit:
import { registerUserCenterItem, type UserCenterItem } from '#extensions/shop/widgets/user/template/useUserCenter'Fuer Vue-Komponenten aus anderen Plugins funktioniert defineComponent/defineProps genauso wie bei lokalen Imports.
Haeufige Fehler
#widgets/plugin-registry importieren
// FALSCH — Registry wird beim Cache-Rebuild ueberschrieben, Imports sind nicht stabil
import widgetRegistry from '#widgets/plugin-registry'
// RICHTIG — direkter Import ueber #extensions
import TestimonialWidget from '#extensions/widgetsBase/widgets/testimonial/template/index.vue'Wer den Registry-Zugriff absolut braucht (z. B. ein Custom-Widget-Picker), muss eigene Scan-Logik bauen — nicht diese Map konsumieren.
Plugin-Ordner-Namen mit Bindestrich oder Gross-/Kleinschreibung
#extensions/MenuEditor/... matcht nicht menueditor/. Der Alias macht keinerlei Normalisierung — exakter Ordnername, exakte Gross-/Kleinschreibung.
Alias aus Drittanbieter-Package importieren
#extensions funktioniert nur im Theme-Code (_theme/vue-base/app/ und darunter) sowie in Plugin-Code, der vom Theme eingebunden wird. npm-Packages haben keinen Zugriff auf Alias — dort muessen absolute oder relative Pfade genutzt werden.
#extensions Pfad anpassen in Projekt-Fork
Ein Projekt-Fork (_theme/projekt01/) hat seine eigene nuxt.config.ts. Der #extensions-Pfad ../../_public/extensions/core/backend bleibt gleich, weil das Plugin-Verzeichnis global ist. Aber beim Anlegen eines neuen Themes nicht den #extensions-Eintrag auslassen — sonst brechen alle Cross-Plugin-Imports aus Widget-Code.
Siehe auch
- Theme-Struktur — wo
nuxt.config.tsim Theme-Ordner liegt - Environment-Variablen —
.envhat keine Alias-Konfiguration - Deployment — Cache-Rebuild als Deploy-Step
- Design-Tokens › Cache-Integration — wann
plugin-registry.jsneu generiert wird - Widgets › Widget-Anatomie › Custom-Theme-Overrides — wie Overrides in der Registry landen
- Widgets › User-Center-Items — Cross-Plugin-Import via
#extensions