Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .bc-exclude.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,6 @@
// constructor changes of internal decorator, no break
preg_quote('ADDED: Parameter transport was added to Method __construct() of class Shopware\Elasticsearch\Profiler\ClientProfiler', '/'),
preg_quote('CHANGED: Parameter 0 of Shopware\Elasticsearch\Profiler\ClientProfiler#__construct() changed name from client to transport', '/'),

// Revert new feature, which was not released yet
preg_quote('REMOVED: Class Shopware\Storefront\DependencyInjection\TwigComponentBundlePass has been deleted', '/'),
preg_quote('REMOVED: Method Shopware\Storefront\Framework\Twig\Extension\ConfigExtension#componentImportMap() was removed', '/'),
preg_quote('REMOVED: Method Shopware\Storefront\Framework\Twig\TemplateConfigAccessor#componentImportMap() was removed', '/'),
preg_quote('REMOVED: Class Shopware\Storefront\Framework\Routing\StorybookRouteScopeAllowList has been deleted', '/'),
preg_quote('REMOVED: Method Shopware\Core\Framework\Bundle::getTwigComponentNamespace() was removed', '/'),
preg_quote('REMOVED: Method Shopware\Core\Framework\Bundle::getTwigComponentNamespace() was removed', '/'),

/** Internal annotation on {@see SwTwigFunction} was not recognized correctly */
preg_quote('CHANGED: Shopware\Core\Framework\Adapter\Twig\SwTwigFunction was marked "@internal"', '/'),
Expand Down
7 changes: 7 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,15 @@
"8025": {
"label": "Mailpit (Mail Testing)",
"onAutoForward": "silent"
},
"6006": {
"label": "Storybook",
"onAutoForward": "silent"
}
},
"shutdownAction": "none",
"remoteEnv": {
"PATH": "/usr/local/bin:/usr/bin:${containerEnv:PATH}"
},
"remoteUser": "www-data"
}
5 changes: 5 additions & 0 deletions .github/actions/ats/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ runs:
uses: shopware/setup-shopware@main
with:
mysql-version: "builtin"
npm-version: 11.8.0
shopware-version: ${{ github.ref }}
shopware-repository: ${{ github.repository }}
install: ${{ inputs.install }}
Expand Down Expand Up @@ -151,6 +152,10 @@ runs:
with:
node-version: 22

- name: Install npm
shell: bash
run: npm install -g npm@11.8.0

- name: Cache npm packages
uses: actions/cache@v4
with:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ jobs:
env:
COMPOSER_ROOT_VERSION: 6.7.9999999-dev
with:
npm-version: 11.8.0
shopware-version: ${{ github.ref }}
shopware-repository: ${{ github.repository }}
install-admin: true
Expand Down Expand Up @@ -369,6 +370,8 @@ jobs:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # 4
with:
node-version: 22
- name: Install npm
run: npm install -g npm@11.8.0

- name: Install dependencies
working-directory: new-shopware/tests/acceptance
Expand Down
41 changes: 41 additions & 0 deletions .github/workflows/storefront.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
uses: shopware/setup-shopware@main
with:
mysql-version: skip
npm-version: 11.8.0
shopware-version: ${{ github.ref }}
shopware-repository: ${{ github.repository }}
install-storefront: true
Expand Down Expand Up @@ -109,6 +110,7 @@ jobs:
uses: shopware/setup-shopware@main
with:
mysql-version: skip
npm-version: 11.8.0
shopware-version: ${{ github.ref }}
shopware-repository: ${{ github.repository }}
install-storefront: true
Expand All @@ -125,6 +127,42 @@ jobs:
files: build/artifacts/jest/cobertura-coverage.xml
flags: jest-storefront

vitest:
name: "Vitest Storefront Components"
runs-on: ubuntu-24.04
env:
APP_ENV: prod
APP_URL: http://localhost:8000
APP_SECRET: def00000bb5acb32b54ff8ee130270586eec0e878f7337dc7a837acc31d3ff00f93a56b595448b4b29664847dd51991b3314ff65aeeeb761a133b0ec0e070433bff08e48
OPENSEARCH_URL: elasticsearch:9200
ADMIN_OPENSEARCH_URL: elasticsearch:9200
BLUE_GREEN_DEPLOYMENT: 1
COMPOSER_ROOT_VERSION: 6.7.9999999-dev

steps:
- name: Setup Shopware
uses: shopware/setup-shopware@main
with:
mysql-version: skip
npm-version: 11.8.0
shopware-version: ${{ github.ref }}
shopware-repository: ${{ github.repository }}
install-storefront: true

- name: Run Vitest Storefront components with coverage
working-directory: src/Storefront/Resources/app/storefront
run: |
npm run build:components
npm run unit:components:coverage -- --coverage.reporter=cobertura --coverage.reportsDirectory=build/artifacts/vitest

- name: Upload coverage
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # 5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
files: build/artifacts/vitest/cobertura-coverage.xml
flags: vitest-storefront-components

license-check:
runs-on: ubuntu-24.04
name: "License check"
Expand All @@ -136,6 +174,8 @@ jobs:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # 4
with:
node-version: 22
- name: Install npm
run: npm install -g npm@11.8.0
- name: Cache npm packages
uses: actions/cache@v5
with:
Expand All @@ -161,6 +201,7 @@ jobs:
- lint
- lint-admin-modules
- jest
- vitest
- license-check
- twig-lint-storefront

Expand Down
74 changes: 74 additions & 0 deletions RELEASE_INFO-6.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,80 @@ When merchants rename a media file, its URL automatically updates so they can do

## Storefront

### New Component System

We introduced a new component system to the Storefront, which makes it easier to create reusable templates. It is one foundation of a new content system, which will be released at a later stage, but components can also be used anywhere in existing templates. The component system is based on [Twig UX components](https://symfony.com/bundles/ux-twig-component/current/index.html), plus some additional features like SCSS and JS handling for your components.

To dive into the full possibilities, please refer to the [official documentation](https://developer.shopware.com/docs/concepts/framework/storefront-components.html).

### New Dev-Server for development based on Vite

With the new component system we introduced a separate build process based on Vite. With that there is also a new dev-server feature available that also supports usual theme file updates for SCSS and JS. It offers a better developer experience, because it does not need a proxy. You can simply work in your normal Storefront while the dev-server is active.

```
composer storefront:dev-server
```

The current `composer watch:storefront` command is deprecated for the next major version. Use the new dev-server instead.

### Theme config available as native CSS custom properties

With the new content system we want to move away from the PHP-based SCSS compilation. As a first step, we made the theme configuration available as native CSS custom properties. You can start using them instead of SCSS variables for colors and other visual settings in CSS. The CSS custom properties are available under the same name as the SCSS variables.

**Example**
```CSS
.btn-primary {
background: var(--sw-color-brand-primary);
}
```

Available are all config fields that does not have set `scss: false` in the theme configuration.

### Single file references in theme.json

The `theme.json` file now supports single file references, allowing you to include individual files from other bundles rather than pulling in an entire theme or plugin. This gives themes fine-grained control over exactly which files are compiled.

This is available for both `style` and `script` entries:

**Bundle-relative references** — Include a single specific file from another bundle or theme using `@BundleName/path/to/file`:

```json
{
"style": [
"@MyTheme/app/storefront/src/scss/overrides.scss",
"@MyTheme"
],
"script": [
"@MyPlugin/app/storefront/dist/storefront/my-plugin.js",
"@Plugins"
]
}
```

### New global JavaScript event system

With the new component system we also start to improve the general possibilities in the Storefront. One of these improvements is a new global event system that is available via a new central `Shopware` object. This system is easier to use than the instance scoped events from the current JS plugin system. The event system is based on the native Node [event emitter](https://nodejs.org/en/learn/asynchronous-work/the-nodejs-event-emitter) and can be used in a similar way. You will find some additional features, like interceptable events which can be used to hook into certain methods, like changing request parameters before they get send. We want to offer this as a new extension system, especially for the new component system.

```JavaScript
window.Shopware.emit('Filter:Change', { foo: 'bar' });
```

```JavaScript
window.Shopware.on('Filter:Change', ({ foo }) => {
// do something
});
```

For more detailed information, refer to the [documentation](./src/Storefront/Resources/app/storefront/src/component-system/README.md).

### New plugin manager function to call plugin methods

We added a new method to the Storefront plugin manager which allows to call a specific plugin method on all existing instances of that plugin.

```JavaScript
window.PluginManager.callPluginMethod(pluginName, methodName, ...args)
```

### Single-hit search redirect now matches EAN and manufacturer number

The storefront search already redirected to the product detail page when a search term exactly matched a product's number and produced a single result.
Expand Down
30 changes: 30 additions & 0 deletions adr/2026-04-16-storefront-component-build-time-scss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: Build-time SCSS compilation for Storefront components
date: 2026-04-20
area: storefront
tags: [storefront, scss, vite, components, theme-compiler]
---

## Context

* The Storefront component system introduces theme-agnostic Twig UX components that can be contributed by the Storefront, plugins, and apps.
* The existing SCSS compilation pipeline runs inside PHP (`ThemeCompiler` via `scssphp/scssphp`) as part of `theme:compile`. It was designed for the monolithic per-theme stylesheet (`all.css`) and is tightly coupled to the theme lifecycle.
* Running component SCSS through the PHP compiler would mean component styles are recompiled on every `theme:compile`, even when the component source has not changed.
* The PHP compiler does not have access to the same Sass load paths, Node.js ecosystem packages, or modern Sass features that are available in the JS build toolchain.
* Compiling component SCSS inside the PHP compiler would also require the compiler to know which component files belong to which bundle, adding more complexity to the theme system.
* For apps, component source files are only available inside the app's zip archive. Resolving them through the PHP compiler would require downloading and unpacking the zip on every `theme:compile` just to discover and process SCSS files.

## Decision

* Component SCSS is compiled at **build time** by Vite (the same toolchain already used to compile component JavaScript), not by the PHP theme compiler.
* Each bundle's `Resources/views/components/**/*.scss` files are compiled to individual CSS files and placed in `Resources/public/storefront/components/` alongside their JS counterparts.
* The compiled CSS files are theme-agnostic and are published through Shopware's normal asset flow (`assets:install` to `public/bundles/<bundle>/storefront/components`). Theme compile reads bundle-local Vite build meta files and provides CSS information for components in the import map saved in the theme runtime config.
* Theme customisation that previously relied on injecting SCSS variables at compile time (e.g. `$sw-color-brand-primary`) is replaced by **native CSS custom properties** (`var(--sw-color-brand-primary)`). The current active theme's configuration is written as a `<style>` block of `--sw-*` custom properties into the storefront page template at render time.

## Consequences
Comment thread
Phil23 marked this conversation as resolved.

* **Component SCSS cannot use SCSS theme variables** (`$sw-*`). Components that need runtime-configurable values must use CSS custom properties (`var(--sw-*)`). SCSS abstracts from Bootstrap or the Shopware skin layer (mixins, functions, fixed design tokens) remain fully available.
* **Component SCSS cannot use runtime feature-flag state**. Feature flags are runtime information, while component SCSS is compiled at build time. Conditional styling that depends on feature flags must be handled at runtime (for example via markup/classes/data attributes or JavaScript), not via SCSS feature checks.
* Component CSS is compiled once per deployment, not on every `theme:compile`. A build step (`composer build:js:storefront` or the individual component build) must run whenever component SCSS source changes.
* Developers adding a new bundle with components must ensure their component stylesheets do not depend on SCSS variables that are only resolved at theme-compile time.
* Extensions (plugins and apps) must ship the pre-compiled CSS files as part of their release artifact. The compiled output from `Resources/public/storefront/components/` must be included in the extension files so that they can be copied without requiring a build step on the merchant's server.
35 changes: 28 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@
"symfony/translation-contracts": "~3.6.0",
"symfony/twig-bridge": "~7.4.0",
"symfony/twig-bundle": "~7.4.0",
"symfony/ux-twig-component": "~2.35.0",
Comment thread
SpiGAndromeda marked this conversation as resolved.
"symfony/validator": "~7.4.0",
"symfony/var-exporter": "~7.4.0",
"symfony/yaml": "~7.4.0",
Expand Down Expand Up @@ -301,6 +302,10 @@
"static-analyze": "Launches the PHP Stan static analysis tool",
"storefront:unit": "Launches the jest unit test-suite for the Storefront",
"storefront:unit:watch": "Launches the interactive jest unit test-suite watcher for the Storefront",
"storefront:components:unit": "Launches the Vitest unit test-suite for Storefront components",
"storefront:components:unit:watch": "Launches the interactive Vitest unit test-suite watcher for Storefront components",
"storefront:dev-server": "Starts the Vite dev server for the Storefront (port 5175 by default, override with STOREFRONT_VITE_PORT)",
"storefront:storybook": "Runs the Storybook development server for the Storefront component library",
"stylelint": "Codestyle checks all SCSS files of Administration and Storefront",
"stylelint:admin": "Code Style checks for all Admin SCSS files",
"stylelint:admin:fix": "Code Style checks for all Admin SCSS files and fixes them if possible",
Expand All @@ -312,7 +317,7 @@
"translation:lint": "Validates existence of snippets in all core-supported languages",
"translation:update": "Updates all installed translations from the translations GitHub repository",
"watch:admin": "Enables hot module reloading for the Admin",
"watch:storefront": "Enables hot module reloading for the Storefront"
"watch:storefront": "Enables hot module reloading for the Storefront. Deprecated! Use 'storefront:dev-server' instead."
},
"scripts": {
"admin:code-mods": "@npm:admin run code-mods --",
Expand Down Expand Up @@ -363,8 +368,8 @@
"@php bin/console feature:dump",
"@npm:storefront run production",
"cd src/Storefront/Resources/app/storefront && node copy-to-vendor.js",
"@php bin/console theme:compile --sync || true",
"@php bin/console assets:install"
"@php bin/console assets:install",
"@php bin/console theme:compile --sync || true"
],
"check:license": "bash -c \"vendor/bin/composer-license-checker check -a $(sed -z 's/\\n/ -a /g' .allowed-licenses)\"",
"ecs": [
Expand Down Expand Up @@ -466,17 +471,15 @@
"reset": [
"@init:db",
"@build:js",
"@php bin/console theme:change --sync --all Storefront",
"@php bin/console assets:install"
"@php bin/console theme:change --sync --all Storefront"
],
"setup": [
"@composer install -o",
"mkdir -p custom/plugins || true",
"@init:db",
"@init:js",
"@build:js",
"@php bin/console theme:change --sync --all Storefront",
"@php bin/console assets:install"
"@php bin/console theme:change --sync --all Storefront"
],
"static-analyze": [
"@phpstan src/"
Expand All @@ -488,6 +491,24 @@
"Composer\\Config::disableProcessTimeout",
"@npm:storefront run unit-watch"
],
"storefront:components:unit": [
"@npm:storefront run unit:components"
],
"storefront:components:unit:watch": [
"Composer\\Config::disableProcessTimeout",
"@npm:storefront run unit:components:watch"
],
"storefront:dev-server": [
"Composer\\Config::disableProcessTimeout",
"@php bin/console bundle:dump",
"@php bin/console feature:dump",
"@php bin/console theme:dump",
"@npm:storefront run dev:server"
],
"storefront:storybook": [
"Composer\\Config::disableProcessTimeout",
"@npm:storefront run storybook"
],
"stylelint": [
"@stylelint:admin src/**/*.scss",
"@stylelint:storefront src/**/*.scss"
Expand Down
1 change: 1 addition & 0 deletions config/bundles.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true],
Shopware\Core\Profiling\Profiling::class => ['all' => true],
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],
Shopware\Core\Framework\Framework::class => ['all' => true],
Expand Down
1 change: 1 addition & 0 deletions src/Core/Framework/App/Template/TemplateLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class TemplateLoader extends AbstractTemplateLoader
private const ALLOWED_TEMPLATE_DIRS = [
'storefront',
'documents',
'components',
];

private const ALLOWED_FILE_EXTENSIONS = '*.twig';
Expand Down
12 changes: 12 additions & 0 deletions src/Core/Framework/Bundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ public function getMigrationPath(): string
return $this->getPath() . str_replace('\\', '/', $migrationSuffix);
}

/**
* Returns the PHP class namespace used to register Twig components for this bundle with
* Symfony UX TwigComponent. Override this method to use a different namespace structure.
*/
public static function getTwigComponentNamespace(): string
{
$class = static::class;
$pos = strrpos($class, '\\');

return ($pos !== false ? substr($class, 0, $pos) : '') . '\\Resources\\views\\components\\';
}

final public function getContainerPrefix(): string
{
return (new CamelCaseToSnakeCaseNameConverter())->normalize($this->getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function process(ContainerBuilder $container): void
/** @phpstan-ignore phpat.restrictNamespacesInCore (Existence of Storefront dependency is checked before usage. Don't do that! Will be fixed with https://github.com/shopware/shopware/issues/12966) */
if ($container->hasDefinition(ThemeCompiler::class)) {
/** @phpstan-ignore phpat.restrictNamespacesInCore */
$container->getDefinition(ThemeCompiler::class)->replaceArgument(7, $assets);
$container->getDefinition(ThemeCompiler::class)->setArgument('$packages', $assets);
}
}
}
Loading
Loading