Home > Enterprise >  Adding *.vue files support to the Shopware 6 Storefront (Module not found: Error: Can't resolve
Adding *.vue files support to the Shopware 6 Storefront (Module not found: Error: Can't resolve

Time:12-29

I want to create mini Vue app embedded in the Shopware 6 storefront (inside TWIG ecosystem). So far I have this:

MyPluginTheme\src\Resources\app\storefront\build\webpack.config.js

const { join, resolve } = require('path');
const { VueLoaderPlugin } = require("vue-loader");

console.log('VueLoaderPlugin', VueLoaderPlugin);

module.exports = (env) => {
    return {
        module: {
            rules: [
                {
                    test: /\.vue$/,
                    loader: 'vue-loader'
                }
            ]
        },
        plugins: [
            new VueLoaderPlugin()
        ],
        resolve: {
            alias: {
                '@hello-world-npm': resolve(join(__dirname, '..', 'node_modules', 'hello-world-npm')),
                "@vue/compiler-core": resolve(join(__dirname, '..', 'node_modules', '@vue/compiler-core')),
                "@vue/reactivity": resolve(join(__dirname, '..', 'node_modules', '@vue/reactivity')),
                "@vue/compiler-sfc": resolve(join(__dirname, '..', 'node_modules', '@vue/compiler-sfc')),
                "@vue/server-renderer": resolve(join(__dirname, '..', 'node_modules', '@vue/server-renderer')),
                "@vue/compiler-dom": resolve(join(__dirname, '..', 'node_modules', '@vue/compiler-dom')),
                "@vue/shared": resolve(join(__dirname, '..', 'node_modules', '@vue/shared')),
                "@vue/runtime-dom": resolve(join(__dirname, '..', 'node_modules', '@vue/runtime-dom')),
                "@vue/runtime-core": resolve(join(__dirname, '..', 'node_modules', '@vue/runtime-core')),
                // 'vue-loader': resolve(join(__dirname, '..', 'node_modules', 'vue-loader')),
                '@vue': resolve(join(__dirname, '..', 'node_modules', 'vue/dist/vue.esm-bundler.js')),
            }
        }
    };
}

MyPluginTheme\src\Resources\app\storefront\src\main.js

import { createApp, ref } from '@vue';

createApp({
    setup() {
        const count = ref(0);

        const increment = () => {
            console.log('increment from main.js', count.value);
            count.value  ;
        }

        return { count, increment }
    }
}).mount('#app');

Some *.twig file in my shop

<div id="app" style="background-color: yellow; padding: 8px;">
    {% verbatim %}
        <h1>-{{ count }}-</h1>
        <button @click="increment">Increment</button>
    {% endverbatim %}
</div>

Until this point everything works fine and my mini app works:

enter image description here

The issue is when I want to move my code to *.vue file. For this purpose I used vue-loader but I cannot make it working:

MyPluginTheme\src\Resources\app\storefront\src\main.js

// ...
import HelloWorld from './HelloWorld.vue';

console.log('HelloWorld', HelloWorld);
// ...

Output of the build:

> NODE_ENV=production webpack --config webpack.config.js

VueLoaderPlugin [class VueLoaderPlugin] { NS: 'vue-loader' }
ℹ Compiling Shopware 6 Storefront
✔ Shopware 6 Storefront: Compiled with some errors in 6.40s
   202 modules

ERROR in /var/www/html/custom/static-plugins/MyPluginTheme/src/Resources/app/storefront/src/main.js
Module not found: Error: Can't resolve 'vue-loader' in '/var/www/html/custom/static-plugins/MyPluginTheme/src/Resources/app/storefront/src'

I tried to create aliases for vue-loader in webpack.config.js but nothing works


UPDATE: 2022.12.28 09:28

@dneustadt found the solution! Alias for loaders should go to dedicated resolveLoader field in the confing not just resolve. Here is my working final webpack.config.js for copy pasting.

NOTE Pinia is transpiling but still not fully working, I have some error on defining the store but everything else works like a harm!

const { join, resolve } = require('path');
const { VueLoaderPlugin } = require("vue-loader");

module.exports = () => {
    return {
        module: {
            rules: [
                {
                    test: /\.vue$/,
                    use: ['vue-loader'],
                },
                {
                    // https://github.com/vuejs/pinia/issues/675
                    test: /\.mjs$/,
                    include: /node_modules/,
                    type: "javascript/auto"
                }
            ],
        },
        plugins: [
            new VueLoaderPlugin()
        ],
        resolveLoader: {
            // https://stackoverflow.com/questions/74889165/adding-vue-files-support-to-the-shopware-6-storefront-module-not-found-error
            alias: {
                'vue-loader': resolve(join(__dirname, '..', 'node_modules', 'vue-loader')),
            },
        },
        resolve: {
            alias: {
                "@vue/compiler-dom": resolve(join(__dirname, '..', 'node_modules', '@vue/compiler-dom')),
                "@vue/compiler-core": resolve(join(__dirname, '..', 'node_modules', '@vue/compiler-core')),
                "@vue/runtime-dom": resolve(join(__dirname, '..', 'node_modules', '@vue/runtime-dom')),
                "@vue/runtime-core": resolve(join(__dirname, '..', 'node_modules', '@vue/runtime-core')),
                "@vue/shared": resolve(join(__dirname, '..', 'node_modules', '@vue/shared')),
                "@vue/reactivity": resolve(join(__dirname, '..', 'node_modules', '@vue/reactivity')),
                '@vue/devtools-api': resolve(join(__dirname, '..', 'node_modules', '@vue/devtools-api')),
                'vue-demi': resolve(join(__dirname, '..', 'node_modules', 'vue-demi')),
                'pinia': resolve(join(__dirname, '..', 'node_modules', 'pinia')),
                'vue': resolve(join(__dirname, '..', 'node_modules', 'vue/dist/vue.esm-bundler.js')),
            }
        }
    }
}

CodePudding user response:

If memory serves me right this is an issue where the loader cannot be resolved, as it is expected to be a regular dependency, not outside of the main node_modules directory. This doesn't change even if an alias of the same name is resolved.

In that case loaders have to be resolved separately.

module.exports = {
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: ['vue-loader'],
      },
    ],
  },
  resolveLoader: {
    alias: {
      'vue-loader': resolve(join(__dirname, '..', 'node_modules', 'vue-loader')),
    },
  },
}

If that still fails you could try to change the root for loaders.

resolveLoader: {
    root: resolve(join(__dirname, '..', 'node_modules')),
}
  • Related