Simplified Micro-Frontends in Vue
Tags: modulefederation, vue3, microfrontends
Published: 2021-01-20 21:39:29

---
title: Simplified Micro-Frontends in Vue
published: true
date: 2021-01-20 14:19:49 UTC
tags: modulefederation,vue3,microfrontends
canonical_url: 
---

Vue 3 is a fantastic platform for creating Micro-Frontend components. And there are great frameworks out there to help with that, such as [SingleSPA](https://single-spa.js.org/) and [OpenComponents](https://opencomponents.github.io/).

Unless you plan on integrating your Vue components into applications that use a different framework you simplify your architecture dramatically by [Webpack 5’s Module Federation](https://webpack.js.org/concepts/module-federation/) to share and consume Micro-FE components.

### Scenario

Let’s say that you and I work for a tap list service. That’s a service that bars and restaurants use to list their available beverages online. The bars enter the data into our service, and then use an iframe embedded on their site to show customers what’s on tap today. This is a real service by the way, with multiple vendors. Here is the tap list for my local [Happy Valley Growlers](http://valleygrowlers.com/tap-list/).

An iframe, while easy to implement, doesn’t integrate well onto the page. We can do better using Micro-Frontends!

### The Growlers App

Our starting repo has a single Vue 3 application (on Webpack 5 and using Typescript) called growlers. And when we start it up we see three Micro-FE components.

![](https://cdn-images-1.medium.com/max/800/1*0O7QhV_0Dyq_rq_wMIOfnA.gif)<figcaption>Growlers Micro-FE components</figcaption>

There are three Micro-Frontend components:

- **Search**  — Has controls that allow the customer to refine the list of taps to their liking.
- **Taps**  — Shows the current list of available beverages that match the Search filter.
- **Cart**  — Shows a list of beverages the customer has added to their cart.

Each of these components is implement in its own .vue file. And they “talk” through a shared data store, implemented in store.ts, that uses the Vue 3 reactive feature to share data between the components. The advantage of this approach in a Micro-Frontend context is that the application that consumes these components do not need to implement the shared data store. You just drop the components on the page and they connect automatically through the store.

Turning these components into Micro-Frontend components is as easy as editing the `ModuleFederationPlugin` in the `webpack.config.js`. It starts off looking like this:

```js
new ModuleFederationPlugin({
  name: "starter",
  filename: "remoteEntry.js",
  remotes: {},
  exposes: {},
  shared: require("./package.json").dependencies,
}),
```

From there we can change the name from `starter` to `growlers` and then expose the components as well as the store:

```js
new ModuleFederationPlugin({
  name: "growlers",
  filename: "remoteEntry.js",
  remotes: {},
  exposes: {
    "./store": "./src/store",
    "./Cart": "./src/components/Cart",
    "./Search": "./src/components/Search",
    "./Taps": "./src/components/Taps",
  },
  shared: require("./package.json").dependencies,
}),
```

This is telling Webpack 5 to expose these files for external consumption by other applications. We are exposing the store because it is used to load the customer data. Even if we didn’t expose the store code it would still be packaged up with the components because Module Federation is smart enough to package up all the code required to run any exposed module.

### Setting Up The Consumer Application

Our next step in trying this out is to create a new Vue 3 project to consume these components. The simplest way to do that is to use `degit` to clone the starter project:

```sh
npx degit https://github.com/jherr/wp5-starter-vue-3 hv-growlers
```

This will create a directory called `hv-growlers` that has a Vue 3 application that uses Tailwind for CSS and supports Typescript.

The next thing to configure is the `webpack.config.js` file to change the port number to 8081 (so that it doesn’t conflict with the growlers application). Then changing the `ModuleFederationPlugin` configuration to:

```js
new ModuleFederationPlugin({
  name: "hvGrowlers",
  filename: "remoteEntry.js",
  remotes: {
    growlers: "growlers@http://localhost:8080/remoteEntry.js",
  },
  exposes: {},
  shared: require("./package.json").dependencies,
}),
```

This connects our new application with the growlers application and allows us to import the components using simple `import` statements in the code.

With this configured we can add this code to `bootloader.ts`:

```js
import { load } from "growlers/store";

load("hv-taplist");
```

This will load the tap list for the client into the store.

### Adding Micro-Frontends To The Page

Our next step is to change `App.vue` to have a template for the new page with spots in it to host the Micro-Frontend components. There is a template in a [gist associated with this demo](https://gist.github.com/jherr/ee77cb8d7315e5149b7ffd4f81288bcb). When we replace the template in `App.vue` with this HTML we see this layout:

![](https://cdn-images-1.medium.com/max/1024/1*8yXPWv8lrc0QHhGVCRRSug@2x.png)<figcaption>Consumer application template with callouts for Micro-FEs</figcaption>

We can then replace the `App.vue` code with this code:

```js
import { Component } from "Vue";
import Taps from 'growlers/Taps';
import Search from 'growlers/Search';
import Cart from 'growlers/Cart';

export default {
  components: {
    Search,
    Taps,
    Cart,
  },
}
```

Now the Micro-FE components from growlers are available to the template and we can replace the `search`, `taps`, and `cart` divs with `<Search />`, `<Taps />`, and `<Cart />` tags. The result looks like this:

![](https://cdn-images-1.medium.com/max/800/1*4SIefpJPV3Ez03h5YjJslw.gif)<figcaption>Micro-Frontend components integrated seamlessly into the other application</figcaption>

How easy is that? And this is a live runtime connection. The moment that a new version of `growlers` is pushed with a new implementation the consuming applications will update immediately.

### Where To Go From Here

In the complete version of this example, which is shown in the YouTube video connected below, we continue on to:

- Show the Vue consumer application integrating with the store to show an additional level of integration.
- The growlers application upgraded to expose Vanilla Javascript wrappers around the Micro-Frontend components.
- Another consumer application, this time using Vanilla Javascript and consuming the components using the Vanilla Javascript wrappers

There is a YouTube version of this article if you want a video walkthrough of the process:

{% youtube YQvQwTAqXE8 %}

### Conclusions

Vue is a great way to make reusable components. When you combine that that Module Federation you now have reusable components you can easily runtime share between applications Micro-Frontend style. Even better, because you have access to them as full fledged Vue components you have a much deeper level of integration that we’ve seen in other Micro-Frontend frameworks.

* * *