Reputation: 110
I have a VueJS 2 application in which I'm trying to load specific components depending on different flags in a config JSON file.
My file structure is as follows:
root
config.json
> src
>> client
>>> components
>>>> dashboard
>>>>> MenuBarBrand.vue
> product
>> product01
>>> client
>>>> components
>>>>> branding
>>>>>> MenuBrand.vue
>> product02
>>> client
>>>> components
>>>>> branding
>>>>>> MenuBrand.vue
At the moment I've tried 2 different methods:
Using the webpack import syntax in my MenuBarBrand component:
<template>
<b-navbar-brand href="/dashboard">
<MenuBrand />
</b-navbar-brand>
</template>
<script>
import config from '../../../../config.json';
const MenuBrand = import(`../../../../product/${config.product}/components/branding/MenuBrand`);
export default {
name: 'MenuBarBrand',
components: {
'MenuBrand',
},
}
</script>
which results in the following error:
or the Vue Async Components local registration syntax:
<template>
<b-navbar-brand href="/dashboard">
<MenuBrand />
</b-navbar-brand>
</template>
<script>
import config from '../../../../config.json';
export default {
name: 'MenuBarBrand',
components: {
'MenuBrand': () => import(`../../../../product/${config.product}/components/branding/MenuBrand`)
},
}
</script>
which results in the following error:
Are there any clear errors that I'm making or are there any specific babel/webpack plugins needed to enable this functionality?
Edit: Adding my loader configuration based on a comment I received:
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: [
'vue-style-loader',
'css-loader',
'sass-loader',
],
sass: [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax',
],
},
},
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]',
},
},
{
test: /\.css$/,
loader: 'style-loader!css-loader',
},
{
test: /\.(ttf|otf|eot|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader?name=fonts/[name].[ext]',
},
],
},
Upvotes: 0
Views: 2232
Reputation: 644
You need to use the vue-loader
webpack plugin to process the .vue-files in your webpack setup. That enables the () => import(...)
syntax.
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
(other loaders....)
]
},
Or, using require
instead in your original example:
<template>
<b-navbar-brand href="/dashboard">
<MenuBrand />
</b-navbar-brand>
</template>
<script>
import config from '../../../../config.json';
const MenuBrand = require(`../../../../product/${config.product}/components/branding/MenuBrand`);
export default {
name: 'MenuBarBrand',
components: {
'MenuBrand',
},
}
</script>
Upvotes: 0
Reputation: 110
I solved this through an alternate method.
In the webpack config I pull in my product flag and create a path:
const config = require('./config.json');
const fs = require('fs');
const path = require('path');
const productPath = path.resolve(__dirname, 'product', config.product);
Then I set up an alias in the webpack config using this path:
resolve: {
alias: {
menuBrandingPath: productPath,
},
extensions: ['*', '.js', '.vue', '.json'],
},
This path is then used in my Vue component to import the proper component:
<template>
<MenuBrand />
</template>
<script>
import MenuBrand from 'menuBrandingPath/client/components/branding/MenuBrand'; // menuBrandingPath is an alias in the webpack config
export default {
name: 'MenuBar',
components: {
MenuBrand,
},
}
</script>
I've intentionally left out error checking with fs and the fallback path I used to make this example easier to understand. Hopefully it helps someone! :)
Upvotes: 1