Manage multiple instances of a Vue.js app with individual configuration.
vue-mu
is a Vue.js plugin that helps you to manage Vue.js apps in environments, which serve multiple instances of the same Vue.js app with different configuration settings.
By default Vue.js does not provide a handsome way to configure instances of the same app independently.
Imagine a server side served dashboard page. This dashboard contains multiple same-looking widgets which display different table based contents provided by an API, each widget is a Vue.js app. The base for these widgets could easily be one single Vue.js app. But how do we configure these app instances independently? You could do some inline-scripting... Or you can use vue-mu
and provide individual configuration properties via the html data
attribute to each app instance.
Add vue-mu
after vue
:
<!-- latest development version, includes helpful console warnings by default -->
<script src="https://cdn.jsdelivr.net/npm/vue-mu/dist/vue-mu.umd.js"></script>
<script src="https://unpkg.com/vue-mu/dist/vue-mu.umd.js"></script>
<!-- latest production version, minified and silent by default -->
<script src="https://cdn.jsdelivr.net/npm/vue-mu"></script>
<script src="https://unpkg.com/vue-mu"></script>
npm install --save vue-mu
import Vue from 'vue'; // replace vue
import VueMu from 'vue-mu'; // with vue-mu
Do not remove vue
from your package.json
and node_modules
, it is used internally by vue-mu
.
vue-mu
needs a new identifier, to load your app. Switch into the HTML code where your <div id="app" />
entry container resides and make one modification:
<div id="app"></div> <!-- replace this -->
<div data-vue-mu-el="myapp"></div> <!-- with this -->
Now you will notice, that your app won't mount anymore. Fix it by replacing the Vue.js initialization in your JavaScript code with vue-mu
:
// replace vue
new Vue({ /* vue configuration options */ }).$mount('#app');
// with vue-mu
new VueMu(
{ /* vue configuration options */ },
{ el: 'myapp', /* ...more vue-mu configuration options */ }
);
Add configuration options via data
attributes:
<div
data-vue-mu-el="myapp"
data-vue-mu-config-hello="Hello from instance configuration"
data-vue-mu-config-is-admin="true"
data-vue-mu-config-price="90.99"
></div>
Use the new configuration properties inside your Vue.js app:
{
// some vue data, computed properties, methods...
created() {
console.log(this.$mu.config);
}
}
If you've done everything right, this will print your new configuration properties to the console of your browser:
// console.log() output inside devtools
{
hello: 'Hello from instance configuration',
isAdmin: true,
price: 90.99
}
Does it? Congrats, you are now a successful user of vue-mu
.
This is the hot stuff where vue-mu
reveals its power. Duplicate the HTML entry element and make some changes inside the data-vue-mu-config-*
attribute values of the new element. Reload the page. Now you should get two Vue.js app instances with different configuration.
this.$mu.config
is globally available in your app and contains all the configuation options you hand over via data-vue-mu-config-*
attributes to the instance.
Access single configuration properties by typing this.$mu.config.isAdmin
, this.$mu.config.price
...
Use vue-mu
configuration inside your Vue.js templates:
<template>
<div>{{ $mu.config.hello }}</div>
</template>
All data-vue-mu-config-*
attributes should be written in kebab-case format. Inside the Vue.js app instance these config properties are available in camelCase format:
HTML data attribute |
Access inside Vue.js |
---|---|
data-vue-mu-config-foobar |
this.$mu.config.foobar |
data-vue-mu-config-foo-bar |
this.$mu.config.fooBar |
As you may have already noticed, vue-mu
automatically converts the values of the data
config attributes into their natural format via auto-parse. Some examples:
HTML data attribute value |
Value format inside Vue.js |
---|---|
data-vue-mu-config-foo="Test" |
String |
data-vue-mu-config-foo="90.99" |
Number |
data-vue-mu-config-foo="true" |
Boolean |
You can use data-vue-mu-config='{ "some": "json", "config": "data" }'
directly to pass all configuration properties at once. This can be combined with additive data-vue-mu-config-*
attributes, which will in turn override duplicate properties defined in data-vue-mu-config
.
<div
data-vue-mu-el="myapp"
data-vue-mu-config='{
"hello": "Hello from instance configuration",
"isAdmin": true,
"price": 90.99
}'
data-vue-mu-config-hello="Hello world!"
></div>
Results in:
// console.log(this.$mu.config)
{
hello: 'Hello world!',
isAdmin: true,
price: 90.99
}
Format | Required | Property | Default value | Description |
---|---|---|---|---|
String | true |
el |
undefined |
Identifier for the Vue.js app instances |
String | false |
ident |
'vue-mu' |
Data attribute identifier data-vue-mu-* . Change this eg. to app if you want to access vue-mu by data-app-* . |
Boolean / Selector | false |
observe |
false |
Observe DOM changes and initialize app instances dynamically. true observes the whole document <body> , document.querySelector('.foo') or document.querySelectorAll('.bar') observes only changes in these elements. Selector elements must be present before vue-mu gets loaded. |
Boolean | false |
silent |
false * |
If set to false vue-mu throws errors on misconfiguration (*: defaults true in minified browser/umd version) |
Boolean | false |
strict |
false |
Only accept data-vue-mu-config-* properties defined in config option |
Object | false |
config |
{} |
Use this to define a default configuration for instances, overwritable by data properties. |
Example configuration:
new VueMu(
{
// some vue data, computed properties, methods...
created() {
console.log(this.$mu.config);
}
},
{
el: 'myapp',
ident: 'vue-mu',
silent: false,
strict: true,
config: {
hello: '',
isAdmin: false,
}
}
);
Access vue-mu
configuration inside Vuex the same way you are using it inside your Vue.js app:
new Vuex.Store({
// state, getters, mutations
actions: {
someAction() {
console.log(this.$mu.config.hello);
// more action specific code
}
}
});
If you have multiple instances of the same app running Vuex, you may want to scope the store to each instance individually.
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
// change this
export default new Vuex.Store({ /* store config */});
// to this
export default () => new Vuex.Store({ /* store config */});
If multiple different apps use vue-mu
you should think about loading vue-mu
and vue
globally (for example via CDN) to save bandwith and bundle size.
<!-- entry elements go here -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-mu/dist/vue-mu.umd.js"></script>
<!-- import vue-app scripts here -->
If you are using vue-cli
you should mark vue
and vue-mu
as external dependencies inside vue.config.js
in each app:
module.exports = {
chainWebpack: (config) => {
config.externals({
vue: 'Vue',
'vue-mu': 'VueMu',
});
},
};
Set some global defaults, used by every app. Apps can overwrite these defaults via their instance settings:
<!-- entry elements go here -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-mu/dist/vue-mu.umd.js"></script>
<script>
VueMu.defaults = {
strict: true,
silent: false,
// ...
};
</script>
<!-- import vue-app scripts here -->
License
vue-mu is licensed under the MIT license.
Copyright (C) 2019 Leonard Hertel