Verified on Shopware 6.7

Vite in Shopware 6

Shopware has been transitioning from Webpack to Vite for storefront builds. Vite is faster, simpler, and provides a much better developer experience - but overriding its configuration in Shopware requires understanding where the extension points are.

Here are 5 real-world override examples from production projects.

1. Custom Entry Points

By default, Shopware bundles all storefront JS into a single entry. If you need separate entry points (e.g., for a heavy feature that only loads on certain pages):

// <plugin-root>/Resources/app/storefront/build/vite.config.js
export default (config) => {
    // Add a custom entry point
    if (!config.build) config.build = {};
    if (!config.build.rollupOptions) config.build.rollupOptions = {};

    config.build.rollupOptions.input = {
        ...config.build.rollupOptions.input,
        'product-configurator': './src/product-configurator/main.js',
    };

    return config;
};

Then load it conditionally in your Twig template:

{% if page.product.configuratorSettings|length > 0 %}
    <script type="module" src="{{ asset('bundles/yourplugin/storefront/product-configurator.js') }}"></script>
{% endif %}

2. Path Aliases

When your plugin has deep directory structures, imports become unreadable. Add aliases:

// vite.config.js
import path from 'path';

export default (config) => {
    if (!config.resolve) config.resolve = {};
    if (!config.resolve.alias) config.resolve.alias = {};

    config.resolve.alias['@my-plugin'] = path.resolve(__dirname, '../src');
    config.resolve.alias['@my-components'] = path.resolve(__dirname, '../src/components');

    return config;
};

Now you can import cleanly:

// Before
import ProductHelper from '../../../../service/product-helper';

// After
import ProductHelper from '@my-plugin/service/product-helper';

3. PostCSS Configuration

Need custom PostCSS plugins for autoprefixer config, CSS nesting, or custom media queries?

// vite.config.js
import postcssNesting from 'postcss-nesting';
import autoprefixer from 'autoprefixer';

export default (config) => {
    config.css = {
        ...config.css,
        postcss: {
            plugins: [
                postcssNesting(),
                autoprefixer({
                    overrideBrowserslist: ['last 2 versions', '> 1%'],
                }),
            ],
        },
    };

    return config;
};

Don't forget to add the PostCSS plugins to your plugin's package.json:

{
    "devDependencies": {
        "postcss-nesting": "^12.0.0",
        "autoprefixer": "^10.4.0"
    }
}

4. Chunk Splitting for Performance

If your storefront bundle is getting large, split vendor libraries into separate chunks:

// vite.config.js
export default (config) => {
    if (!config.build) config.build = {};

    config.build.rollupOptions = {
        ...config.build.rollupOptions,
        output: {
            ...config.build.rollupOptions?.output,
            manualChunks: (id) => {
                // Split large libraries into separate chunks
                if (id.includes('node_modules/swiper')) {
                    return 'vendor-swiper';
                }
                if (id.includes('node_modules/flatpickr')) {
                    return 'vendor-flatpickr';
                }
            },
        },
    };

    return config;
};

This produces separate files that can be cached independently - users who already have vendor-swiper cached don't re-download it when your main JS changes.

5. Dev Server Proxy

When developing against a remote API or microservice alongside Shopware:

// vite.config.js
export default (config) => {
    config.server = {
        ...config.server,
        proxy: {
            '/api/custom-erp': {
                target: 'https://erp-staging.your-company.com',
                changeOrigin: true,
                rewrite: (path) => path.replace(/^\/api\/custom-erp/, '/api/v2'),
                secure: false,
            },
            '/api/product-feed': {
                target: 'http://localhost:3001',
                changeOrigin: true,
            },
        },
    };

    return config;
};

This lets your storefront JS call /api/custom-erp/products during development and it gets proxied to your actual ERP API - no CORS issues.

Debugging Vite Builds

When something goes wrong:

# See the full resolved Vite config
npx vite -debug

# Analyze bundle size
npx vite build -mode analyze

# Check which modules are included
npx vite build -debug=resolve

Common Gotchas

  1. Config merge order - Shopware applies plugin configs in plugin load order. If two plugins modify the same config key, the last one wins
  2. Hot reload - Vite HMR works out of the box, but custom entry points may need manual HMR setup
  3. Production builds - always test bin/build-storefront.sh after config changes, dev mode can mask issues
  4. Import paths - Vite is strict about ESM imports. require() won't work - use import instead

Having trouble with your Shopware storefront build? We can help optimize it.