Vue.JS - micro frontend approach

2020-02-08 07:58发布

Our team is developing a large project and we want to build a big app with multiple forms and dashboards and features. One monolith SPA would get complicated. So we discuss the approach of „micro frontends architect“. The goal is to generate a parent SPA which contains several child SPAs. All SPA should be of same framework (vueJS).

The idea behind this approach (https://micro-frontends.org/)

  • a web app is a composition of features which are owned of independent teams
  • a team has a distinct area of business
  • the team is cross functional and developed its feature end-to-end from database to user-interface
  • its like Self contained systems

We have found some implementations of this approach

1) https://micro-frontends.org/

2) CanopyTax with single-spa -> https://github.com/CanopyTax/single-spa

What we want to use in our frontend:

  • vue

  • vue-router

  • vue-resource

  • vue-loader

  • webpack

Our Questions:

1) Is it possible to create a composite UI (micro front end) based on vue by using standard vue tools?

- we are not sure how doable is it with VueJS
- there may already be example projects?

2) We have more than one page, so we need a solution to navigate from one side to another. How can we realize page transitions?

3) Is it possible to established a Event-Bus between the VueJS components?

4) How can we implement a bidirectional communication between the components?

- Parent-Child Communication
- Child-Parent Communication

2条回答
smile是对你的礼貌
2楼-- · 2020-02-08 08:53

1) Is it possible to create a composite UI (micro front end) based on vue by using standard vue tools?

Yes, it is possible. Pretty much any independent component you see published around (https://github.com/sagalbot/vue-select, https://github.com/NightCatSama/vue-slider-component) and even full "sets" of components (such as vuetify, https://github.com/bootstrap-vue/bootstrap-vue, vue-material) are examples of reusable (composable) components developed using standard vue tools.

2) We have more than one page, so we need a solution to navigate from one side to another. How can we realize page transitions?

vue-router is the tool for this job. It is developed by the core team, so expect tight integration and great feature support.

3) Is it possible to established a Event-Bus between the VueJS components?

Every Vue instance implements an events interface. This means that to communicate between two Vue instances or components you can use Custom Events. You can also use Vuex (see below).

4) How can we implement a bidirectional communication between the components?

The best way to send data from parent component to child is using props. Steps: (1) Declare props (array or object) in the child; and (2) Pass it to the child via <child :name="variableOnParent">. See demo below.

Vue.component('child-comp', {
  props: ['message'], // declare the props
  template: '<p>At child-comp, using props in the template: {{ message }}</p>',
  mounted: function () {
    console.log('The props are also available in JS:', this.message);
  }
})

new Vue({
  el: '#app',
  data: {
    variableAtParent: 'DATA FROM PARENT!'
  }
})
<script src="https://unpkg.com/vue@2.5.13/dist/vue.min.js"></script>

<div id="app">
  <p>At Parent: {{ variableAtParent }}</p>
  <child-comp :message="variableAtParent"></child-comp>
</div>

You can also get references for Child Components (refs) and call methods on them.

Vue.component('my-comp', {
  template: "#my-comp-template",
  props: ['name'],
  methods: {
    saveMyComp() {
      console.log('Saved:', this.name);
    }
  }
})

new Vue({
  el: '#app',
  data: {
    people: [{name: 'Bob'}, {name: 'Nelson'}, {name: 'Zed'}]
  },
  methods: {
    saveChild(index) {
      this.$refs.myComps[index].saveMyComp();
    }
  }
});
<script src="https://unpkg.com/vue@2.5.13/dist/vue.min.js"></script>

<div id="app">
  <div v-for="(person, index) in people">
    <button @click="saveChild(index)">saveMyComp</button>
    <my-comp :name="person.name" ref="myComps"></my-comp>
  </div>
</div>

<template id="my-comp-template">
    <span> {{ name }} </span>
</template>

To communicate from child to parent, you'll use events. See demo below. There are also several modifiers that make this task easier.

var parent = {
  template: '<div><child :content.sync="localContent"></child><br>At parent: {{ localContent }}</div>',
  props: ['content'],
  data() {
    return {
      localContent: this.content
    }
  }
};

var child = {
  template: '<div>At child: {{ content.value }}<button @click="change">change me</button></div>',
  props: ['content'],
  methods: {
    change() {
      this.$emit('update:content', {value: "Value changed !"})
    }
  }
};

Vue.component('child', child);
Vue.component('parent', parent);

new Vue({
  el: '#app'
});
<script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>

<div id="app">
  <parent :content="{value:'hello parent'}"></parent>
</div>

Inevitably, though, as your application grows, you will have to use a more scalable approach. Vuex is the de facto solution in this case. Roughly, when using Vuex, you won't have to pass state around from parent to child: all of them will pick it up from the Vuex store (sort of a "global" reactive variable). This greatly simplifies the application management and is worth a post of its own.

Final note: As you can see, one great advantage of Vue is how easy you can prototype and test functionality. No build step, few abstractions over raw JS. Compared to other frameworks, I'd say this is an important bonus.

查看更多
干净又极端
3楼-- · 2020-02-08 09:01

I have been curious looking for a quick way to implement the Micro-frontend architecture. Some good resources I found are at: https://micro-frontends.org/ and https://single-spa.js.org/, however the problem I had with them is setup complexity... I like to see results pretty fast. https://piral.io is still pretty much in development and it's mainly targeted for react, but here are my findings.

I was able to come up with an approach and hope to write an medium article on that soon, however for the time being

  1. You can build each part of your application as an independent WebComponent, with Vue, this article is a great place to start.
  2. You can use vue-router, and with dynamic route matching (e.g /apps/:app_name) you can load sub-applications as appropriate. Within each sub-app, you can as well have a routing system in place
  3. In recent browsers, there's BroadcastChannel which can be used to send messages across sub-apps. This could be resourceful.
  4. BroadcastChannel can handle bi-directional communication.

This approach works best if you want to:

  1. Have separate team use whatever tool they're most comfortable with.
  2. Add new apps, even in production without downtime.
查看更多
登录 后发表回答