DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • The Best Javascript Frameworks for 2022
  • Containerize Gradle Apps and Deploy to Kubernetes With JKube Kubernetes Gradle Plugin
  • Deploy an ASP.NET Core Application in the IBM Cloud Code Engine
  • Deploy a Hyperledger Fabric v2 Web App Using the Node.js SDK

Trending

  • The End of “Good Enough Agile”
  • SaaS in an Enterprise - An Implementation Roadmap
  • How to Merge HTML Documents in Java
  • Intro to RAG: Foundations of Retrieval Augmented Generation, Part 2
  1. DZone
  2. Coding
  3. JavaScript
  4. Building Micro-Frontends With Single-spa, React, and Vue

Building Micro-Frontends With Single-spa, React, and Vue

By 
Mayur Ingle user avatar
Mayur Ingle
·
Apr. 16, 20 · Tutorial
Likes (9)
Comment
Save
Tweet
Share
21.9K Views

Join the DZone community and get the full member experience.

Join For Free

When I see something new and controversial like this, I always want to try it out myself to see what all of the hype is about and also so I can form my own opinions about the subject.

This led me down the path to creating a micro-frontend application that rendered two separate React applications, along with a single Vue application.

In this tutorial, I'll share what I've learned and show you how to build a micro-frontend app consisting of a React and a Vue application. 

To view the final code for this application, click here.

Single SPA

The tool we will be using to create our project is Single SPA — a JavaScript framework for frontend microservices.

Single SPA enables you to use multiple frameworks in a single-page application, allowing you to split code by functionality and have Angular, React, Vue.js, etc. apps all living together.

You may be used to the days of the Create React APP CLI and the Vue CLI. With these tools, you can quickly spin up an entire project, complete with Webpack configurations, dependencies, and boilerplate ready to go for you.

If you're used to this ease of setup, then this first part may be somewhat jarring. That is because we will be creating everything from scratch, including installing all of the dependencies we need as well as creating the Webpack and Babel configuration from scratch.

Getting Started

The first thing you'll need to do is create a new folder to hold the application and change into the directory:

Shell
xxxxxxxxxx
1
 
1
mkdir single-spa-app
2
 
3
cd single-spa-app


Next, we'll initialize a new package.json file: 

Shell
xxxxxxxxxx
1
 
1
npm init -y


Now, this is the fun part. We will install all of the dependencies that we will need for this project. I will split these up into separate steps.

 Installing Regular Dependencies 

Shell
xxxxxxxxxx
1
 
1
npm install react react-dom single-spa single-spa-react single-spa-vue vue


Installing Babel Dependencies

Shell
xxxxxxxxxx
1
 
1
npm install @babel/core @babel/plugin-proposal-object-rest-spread @babel/plugin-syntax-dynamic-import


Installing Webpack Dependencies

Shell
xxxxxxxxxx
1
 
1
npm install webpack webpack-cli webpack-dev-server clean-webpack-plugin css-loader html-loader style


Now, all of the dependencies have been installed, and we can create our folder structure.

The main code of our app will live in an src directory. This src directory will hold subfolders for each of our applications. Let's go ahead and create the React and Vue application folders within the src folder:

Shell
xxxxxxxxxx
1
 
1
mkdir src src/vue src/react


Now, we can create the configuration for both Webpack and Babel.

Creating Webpack Configuration

In the root of the main application, create a webpack.config.js file with the following code:

JavaScript
xxxxxxxxxx
1
50
 
1
const path = require('path');
2
const webpack = require('webpack');
3
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
4
const VueLoaderPlugin = require('vue-loader/lib/plugin')
5
 
6
module.exports = {
7
  mode: 'development',
8
  entry: {
9
    'single-spa.config': './single-spa.config.js',
10
  },
11
  output: {
12
    publicPath: '/dist/',
13
    filename: '[name].js',
14
    path: path.resolve(__dirname, 'dist'),
15
  },
16
  module: {
17
    rules: [
18
      {
19
        test: /\.css$/,
20
        use: ['style-loader', 'css-loader']
21
      }, {
22
        test: /\.js$/,
23
        exclude: [path.resolve(__dirname, 'node_modules')],
24
        loader: 'babel-loader',
25
      },
26
      {
27
        test: /\.vue$/,
28
        loader: 'vue-loader'
29
      }
30
    ],
31
  },
32
  node: {
33
    fs: 'empty'
34
  },
35
  resolve: {
36
    alias: {
37
      vue: 'vue/dist/vue.js'
38
    },
39
    modules: [path.resolve(__dirname, 'node_modules')],
40
  },
41
  plugins: [
42
    new CleanWebpackPlugin(),
43
    new VueLoaderPlugin()
44
  ],
45
  devtool: 'source-map',
46
  externals: [],
47
  devServer: {
48
    historyApiFallback: true
49
  }
50
};


Creating Babel Configuration

In the root of the main application, create a .babelrc file with the following code:

JSON
xxxxxxxxxx
1
14
 
1
{
2
  "presets": [
3
    ["@babel/preset-env", {
4
      "targets": {
5
        "browsers": ["last 2 versions"]
6
      }
7
    }],
8
    ["@babel/preset-react"]
9
  ],
10
  "plugins": [
11
    "@babel/plugin-syntax-dynamic-import",
12
    "@babel/plugin-proposal-object-rest-spread"
13
  ]
14
}

Initializing Single-spa

Registering applications is how we tell single-spa when and how to bootstrap, mount, and unmount an application.

In the webpack.config.js file, we set the entry point to be single-spa.config.js.

Let's go ahead and create that file in the root of the project and configure it.

Single-spa.config.js

JavaScript
xxxxxxxxxx
1
15
 
1
import { registerApplication, start } from 'single-spa'
2
 
3
registerApplication(
4
  'vue', 
5
  () => import('./src/vue/vue.app.js'),
6
  () => location.pathname === "/react" ? false : true
7
);
8
 
9
registerApplication(
10
  'react',
11
  () => import('./src/react/main.app.js'),
12
  () => location.pathname === "/vue"  ? false : true
13
);
14
 
15
start();


This file is where you register all of the applications that will be part of the main Single Page App. Each call to registerApplication registers a new application and takes three arguments:

  1. App name.
  2. Loading function (what entry point to load).
  3. Activity function (logic to tell whether to load the app).

Next, we need to create the code for each of our apps.

React App

In src/react, create the following two files:

Shell
xxxxxxxxxx
1
 
1
touch main.app.js root.component.js


src/react/main.app.js

JavaScript
xxxxxxxxxx
1
27
 
1
import React from 'react';
2
import ReactDOM from 'react-dom';
3
import singleSpaReact from 'single-spa-react';
4
import Home from './root.component.js';
5
 
6
function domElementGetter() {
7
  return document.getElementById("react")
8
}
9
 
10
const reactLifecycles = singleSpaReact({
11
  React,
12
  ReactDOM,
13
  rootComponent: Home,
14
  domElementGetter,
15
})
16
 
17
export const bootstrap = [
18
  reactLifecycles.bootstrap,
19
];
20
 
21
export const mount = [
22
  reactLifecycles.mount,
23
];
24
 
25
export const unmount = [
26
  reactLifecycles.unmount,
27
];

src/react/root.component.js

JavaScript
xxxxxxxxxx
1
 
1
import React from "react"
2
 
3
const App = () => <h1>Hello from React</h1>
4
5
export default App


Vue app

In src/vue, create the following two files:

Shell
xxxxxxxxxx
1
 
1
touch vue.app.js main.vue


src/vue/vue.app.js

JavaScript
xxxxxxxxxx
1
23
 
1
import Vue from 'vue';
2
import singleSpaVue from 'single-spa-vue';
3
import Hello from './main.vue'
4
 
5
const vueLifecycles = singleSpaVue({
6
  Vue,
7
  appOptions: {
8
    el: '#vue',
9
    render: r => r(Hello)
10
  } 
11
});
12
 
13
export const bootstrap = [
14
  vueLifecycles.bootstrap,
15
];
16
 
17
export const mount = [
18
  vueLifecycles.mount,
19
];
20
 
21
export const unmount = [
22
  vueLifecycles.unmount,
23
];


src/vue/main.vue

HTML
xxxxxxxxxx
1
 
1
<template>
2
  <div>
3
      <h1>Hello from Vue</h1>
4
  </div>
5
</template>


Next, create the index.html file in the root of the app:

Shell
xxxxxxxxxx
1
 
1
touch index.html


Index.html

HTML
xxxxxxxxxx
1
 
1
<html>
2
  <body>
3
    <div id="react"></div>
4
    <div id="vue"></div>
5
    
6
  </body>
7
</html>


Updating Package.json With Scripts

To run the app, let's add the start script as well as a build script in package.json:

JSON
xxxxxxxxxx
1
 
1
"scripts": {
2
  "start": "webpack-dev-server --open",
3
  "build": "webpack --config webpack.config.js -p"
4
}


Running the app

To run the app, run the start script:

Shell
xxxxxxxxxx
1
 
1
npm start


Now, you can visit the following URLs:

Plain Text
xxxxxxxxxx
1
 
1
# renders both apps
2
 http://localhost:8080/
3
 
4
# renders only react
5
 http://localhost:8080/react
6
 
7
# renders only vue
8
 http://localhost:8080/vue


Conclusion

Overall, setting up this project was fairly painless with the exception of all of the initial boilerplate setup.

I think in the future, it would be nice to have some sort of CLI that handles much of the boilerplate and initial project setup.

If you have the need for this type of architecture, Single-spa definitely seems like the most mature way to do it as of today and was really nice to work with.

React (JavaScript library) application app shell JavaScript framework

Opinions expressed by DZone contributors are their own.

Related

  • The Best Javascript Frameworks for 2022
  • Containerize Gradle Apps and Deploy to Kubernetes With JKube Kubernetes Gradle Plugin
  • Deploy an ASP.NET Core Application in the IBM Cloud Code Engine
  • Deploy a Hyperledger Fabric v2 Web App Using the Node.js SDK

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!