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:
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')),
}
}
}
}

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_modulesdirectory. This doesn't change even if an alias of the same name is resolved.In that case loaders have to be resolved separately.
If that still fails you could try to change the root for loaders.