Skip to content

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:

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:

AliasTargetZweckDarfst du importieren?
#extensions_public/extensions/core/backend/Cross-Plugin-Imports ohne ../../../../-PfadeJa
#widgets/plugin-registryapp/widgets/plugin-registry.jsAuto-generierte Widget-Map fuer den Pagebuilder-Rendering-LoopNein — 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:

ts
// 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

ts
import { registerUserCenterItem } from '#extensions/shop/widgets/user/template/useUserCenter'

Stabil, lesbar, macht Cross-Plugin-Abhaengigkeiten explizit sichtbar.

Typische Use-Cases

ts
// 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

js
// _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:

ts
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.vue

Existiert 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

SituationAlias
"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:

  1. /admin/cache → "Cache leeren"
  2. Plugin-Installation/Deinstallation (Shop-, E-Learning- oder eigenes Plugin)
  3. Manueller Trigger (vueRegistry.php direkt aufrufen)

Nicht automatisch bei:

  • Nuxt-Dev-Server-Start (npm run dev reloaded 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_template in 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:

ts
// _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:

ts
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

ts
// 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