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-muimport Vue from 'vue'; // replace vue
import VueMu from 'vue-mu'; // with vue-muDo 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