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