Reputation: 39280
I have several menu types and want to configure the type of menu to be used in .env.local for example: VUE_APP_MENU_TYPE=2
In my javascript file I have the following:
let menu = false;
if (process.env.VUE_APP_MENU_TYPE === "2") {
menu = require("./type2/Type2.vue");
}
if (menu === false) {//default menu if env is missing
menu = require("./default/Default.vue");
}
export default menu;
This will result in an error Failed to mount component: template or render function not defined.
I can do the following:
import Default from "./default/Default.vue";
import Type2 from "./type2/Type2.vue";
let menu = Default;
if (process.env.VUE_APP_MENU_TYPE === "2") {
menu = Type2;
}
export default menu;
This will work but all menus are compiled in the code, including menus that will never be used since VUE_APP_MENU_TYPE is known at compile time and will never change until you recompile.
Is it possible to import a component dynamically at compile time?
Upvotes: 0
Views: 802
Reputation: 37813
Try menu = require("./type2/Type2.vue").default;
Explanation taken from this answer
when dealing with ES6 imports (
export default MyComponent
), the exported module is of the format{"default" : MyComponent}
. Theimport
statement correctly handles this assignment for you, however, you have to do therequire("./mycomponent").default
conversion yourself. If you want to avoid that, usemodule.exports
instead ofexport default
Fort second part of question...
Is it possible to import a component dynamically at compile time?
Really never tried but I have my doubts. Webpack is not executing the code when building. It just scans it for some patterns.
require()
so it know what modules should be included in the bundleprocess.env.VUE_APP_MENU_TYPE
with values from env
files so it make code look like if ("3" === "2") {
if ("3" === "2") {
is never true
and eliminate "the death code"Real question if what happens first - if require
scanning happens before death code elimination, you will end up with all possible menu components in the bundle. But unfortunately I don't know - You'l have to try
On the other hand using dynamic async components (as mentioned in other answers) is sure bet. Yes, Webpack will build all possible menu components but each with it's own js chunk (js file in dist
folder). If the app loads just one of them, it's seems fine to me (note that the loading will be async - at runtime - so it means one more server request)
Upvotes: 2
Reputation: 1730
I think that loading the component dynamically is the best option you have. https://v2.vuejs.org/v2/guide/components-dynamic-async.html
Upvotes: 1
Reputation: 39280
I could have solved this with a webpack setting.
In vue.config.js
const path = require("path");
module.exports = {
configureWebpack: {
resolve: {
alias: {
MENU: path.resolve(
__dirname,
(() => {
if (process.env.VUE_APP_MENU_TYPE === "2") {
return "src/components/header/CategoriesMenu/Type2/Type2.vue";
}
return "src/components/header/CategoriesMenu/Default/Default.vue";
})()
),
},
},
},
};
In src/components/header/CategoriesMenu/index.js
import menu from "MENU";
export default menu;
But to be honest, I like the require
better.
Upvotes: 0