bootstrap-vue vuejs dynamic async component import - vue.js

I would like to import a single bootstrap component dynamically only when I need it.
Bellow syntax actually can do it but it does import all components.
So final module bundle after tree-shaking is 1.4MB (entire bootstrap library).
BNavbar: () => import('bootstrap-vue').then(module => module.BNavbar),
How can I change it to import only navbar to be equivalent of
import { BNavbarPlugin } from 'bootstrap-vue'
Vue.use(BNavbarPlugin)

I think the solution is to wrap it in another component like AppNavbar which imports the BNavbarPlugin the basic way import { BNavbarPlugin } from 'bootstrap-vue' Then import your wrapper component dynamically
AppNavbar: () => import('#/components/AppNavbar')

Related

register dynamic components for vue app in seperate module file

I would like to make a js module file that imports vue component and register there.
and then inherit this component and use it for the app's main component.
I've found similar cases but the thing is, I don't use vue cli.
custom.js
import customMain from '/custom/components/main/main.js';
window.Vue.defineComponent('custom-main', customMain);
and in the app.js
import Main from '/global/components/main/main.js';
var App = createApp({
...
components: {
'global-main': Main,
},
template: `<component :is='mainComponent'></component>`,
computed: {
mainComponent() {
if(this.settings.customComponent){
return 'custom-main';
}else{
return 'global-main';
}
}
is this doable? what should I do to make this work?
is there other alternative way to load components dynamically?
The best approach for this case is defining a plugin named registerComponents in the plugins folder : plugins/registerComponents.js
import customMain from '/custom/components/main/main.js';
export default {
install: (app, options) => {
app.component('custom-main', customMain);
}
}
in App.js use the plugin:
import registerComponents from './plugins/registerComponents'
var App = createApp({....})
App.use(registerComponents)

Transition from gobal Vue instance to app breaks import dependency

I'm looking at migrating a Vue 2 app to Vue 3 and ran into a problem. The Vue 2 app used to start with importing a whole lot of components and directives:
// these components register to the global Vue instance
import {ComponentA} from './componenta';
import {directiveA} from './directivea';
// create app (after the components are registered)
new Vue({...})
This worked fine, but when changing this code to Vue3, the app instance is now created instead. This instance isn't actually available when the global directives and components are imported.
What's the recommended way for dealing with this? I can't reorder the imports to the bottom of the file as webpack bundles them always at the top...
The order of imports does not matter in your case - what matters is the order of the JavaScript statements that follow the import section.
You should first create the app instance and only then register your global components to this instance - as explained in https://learnvue.co/2020/08/how-to-register-a-vue3-global-component/
import { createApp } from 'vue'
import PopupWindow from './components/PopupWindow'
import App from "./App.vue"
const app = createApp(App)
app.component('PopupWindow', PopupWindow) // global registration - can be used anywhere
app.mount('#app')
I settled with a solution that imports the app instance before component registration/definition (which occur within the component file) in an attempt to keep the current structure.
import {app} from './instance';
import './components/popupwindow';
import App from './app.vue';
const app = createApp(App)
app.mount('#app')
// instance.js
import {createApp} from 'vue';
const app = createApp();
export {app};
// popupwindow.vue
import {app} from '../instance';
// component registration+definition here (for global components only)
app.component('popup', {
...
}

How to use Axios in main.js

I am learning Vue.js.
I have this code which runs fine :
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
const app = createApp(App).use(store).use(router)
app.mount('#app')
Now I would like to add some import, for example 'axios'. This code does not run :
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
const app = createApp(App).use(store).use(router).use(axios)
app.mount('#app')
The error is:
Uncaught RangeError: Maximum call stack size exceeded
at merge (utils.js?c532:276)
at assignValue (utils.js?c532:282)
at forEach (utils.js?c532:253)
at merge (utils.js?c532:291)
at assignValue (utils.js?c532:282)
at forEach (utils.js?c532:253)
at merge (utils.js?c532:291)
at assignValue (utils.js?c532:282)
at forEach (utils.js?c532:253)
at merge (utils.js?c532:291)
So how to add some other "use" in the main.js file ? It is certainly very basic but I am a beginner.
You're using vue 3 and axios is not a plugin (we cannot register it like app.use()) it's a javascript module that could be add to the app instance like :
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
const app = createApp(App).use(store).use(router)
app.config.globalProperties.axios=axios
app.mount('#app')
and in child component reference it like :
this.axios
Note: the code below is valid for Vue 2.x. Since version 3, some stuff has changed regarding initialization (createApp function is now required).
What I usually do in my code is the following:
import Vue from 'vue';
import axios from 'axios';
// Add it to Vue prototype (use any variable you like, preferrably prefixed with a $).
Vue.prototype.$http = axios;
// Instantiate the main vue app.
let app = new Vue({
//
});
This means that the $http object is now available in all your components using this.$http. Since it is assigned as a prototype variable, it is considered a singleton (it is re-used everywhere), so you can add any options you need to the axios variable before assigning it to Vue.prototype.$http.
Additionally:
Vue.use() is made specifically for enabling Vue plugins. That means the given parameter must use the exact syntax as described here https://v2.vuejs.org/v2/guide/plugins.html . Since axios is not a Vue plugin but just a regular JavaScript library, you cannot use it with this function.
If you want to make it especially nice (or convoluted), you can use the following syntax:
Vue.use({
install(v) {
v.prototype.$http = axios;
// Do other stuff like adding mixins etc.
}
})
This may clear up your code if you move this code to another file, so it could end up like this:
import myCustomAxiosLoader from './bootstrap/axios';
Vue.use(myCustomAxiosLoader);

Use multiple plugins with parameters in VueJS

Let say I have 2 plugins I want to use:
Bootstrap-Vue & Vue Analytics
I would import like so
import BootstrapVue from 'bootstrap-vue'
import VueAnalytics from 'vue-analytics'
How would I use them if one has parameters?
Is this correct?
Vue.use(BootstrapVue, VueAnalytics, {
id: 'UA-12345678-9'
});
Don't overthink it. Just call Vue.use twice.
Vue.use(BootstrapVue);
Vue.use(VueAnalytics, {
id: 'UA-12345678-9'
});
import BootstrapVue from 'bootstrap-vue'
import VueAnalytics from 'vue-analytics'
[BootstrapVue, VueAnalytics].forEach((x) => Vue.use(x));
This is what I usually use.
I will use:
const useArray = [Bootstrap-Vue, Vue Analytics];
useArray.forEach((item)=>{
Vue.use(item)
})

Creating and invoking my own javascript library in react-native

I just wanted to encompass some JavaScript functions in a helper class. For example, running some fetch or async operations, etc. I do not want to create a Component class, instead it's just pure JavaScript. I don't think I can just create a js file, plop the code in and invoke it from within a Component. Do I need to register it, etc?
Yes you can through module imports. React native comes packed with babel compiler. You can reference all the enabled Syntax transformer at https://facebook.github.io/react-native/docs/javascript-environment.html.
Babel also has very good explanation on modules at https://babeljs.io/learn-es2015/#ecmascript-2015-features-modules.
For example:
File helper.js
export function doSomething(){
console.log("I am calling module helper through exported function")
}
File App.js
import {doSomething} from "./helper"; //simply imports function from another file.
import React, { Component } from "react";
import { AppRegistry, Text, View} from "react-native";
export default class ExampleComponent extends Component {
componentDidMount(){
doSomething(); //invoke your function here for example.
}
render() {
return (
<View>
<Text>I'm a text</Text>
</View>
)
}
}
AppRegistry.registerComponent("Example", () => ExampleComponent);