An Interest In:
Web News this Week
- April 14, 2024
- April 13, 2024
- April 12, 2024
- April 11, 2024
- April 10, 2024
- April 9, 2024
- April 8, 2024
Micro-Frontends: The Next Gen Way to build Web Apps
In enterprise-level applications, working on an application from a single code base turns out to be a massive head-ache. For this purpose, Micro-Frontend architecture was born. Let's dive into the world of Micro-Frontend and discuss some of the nitty-gritty of following this approach.
What is Micro-Frontend?
Let's check the definition a google search spits out:
Micro-frontend architecture is a design approach in which a front-end app is decomposed into individual, independent micro-apps working loosely together.
There are two major parts of a Micro-frontend application:
- Container
- Sub-Applications
The container determines when each of the sub-application should be displayed on the screen. All the business logic is handled by each of the sub-applications.
Why use Micro-Frontend?
There are numerous benefits of using Micro-Frontend architecture:
- You can use any framework in each sub-application
- Modification or even bugs in one sub-application has no effect on the other sub-applications
- You can run A/B Tests easily to maximize customer conversions
- Makes it easier for teams to collaborate on a project (can be hosted as separate repository for each sub-app or a mono-repo)
- and many more
Key Principles of Micro-Frontend
There are two strict requirements for this architecture:
- The micro apps should work absolutely independently of each other, for example, the auth sub-app should not in any way rely on data from the product sub-app
- The micro apps can communicate with the container, but the communication should be kept as minimal as possible and should be done in as generic means as possible. So, even if both the container and a sub-app uses the same framework, let's say React, they should not pass React components between them, but some generic functions and objects. This ensures that during a major refactor of either the micro apps or the container, we don't have to work on the other.
Basic Micro-Frontend app
Ok, enough talk! Now it's time to get our hands dirty making a basic Micro-frontend app.
Let's make three folders for:
- container
- cart
- products
We would use faker
to generate fake data for the cart and products. To install the library, open the folder in the command prompt, initialize a node project using npm init
and use npm install faker
.
Implementing Micro-Frontend would be a nightmare for pretty much everyone, but luckily we have Module Federation plugin available with webpack which makes it a piece of cake. To install all webpack associated packages, use (in each folder):
npm install -D webpack webpack-cli html-webpack-plugin webpack-dev-server
Add public/index.html
in all three folders
<!-- cart --><div id="dev-cart"></div>
<!-- products--><div id="dev-products"></div>
<!-- container--><div id="product-list"></div><hr /><div id="cart-items"></div>
Now setting up our webpack.config.js
:
const path = require('path');const HTMLWebpackPlugin = require('html-webpack-plugin');module.exports = { mode: 'development', devServer: { port: 3000, }, plugins: [ new HTMLWebpackPlugin({ template: path.resolve(__dirname, 'public', 'index.html'), }) ],};
Copy the webpack.config.js
at the root of each folder, but make sure you have different port numbers for the dev server.
Now let's set up the Module Federation
:
// cart/webpack.config.js// ...const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');const packageJson = require('./package.json')module.exports = { // ... plugins: [ new ModuleFederationPlugin({ name: 'cart', // name of the item being exposed (required in container) filename: 'remoteEntry.js', // name of the file exposes: { './Cart': './src/bootstrap' // actual file being exposed }, shared: packageJson.dependencies, // to remove duplicate external modules loading in the container }), // ... ]};
// products/webpack.config.js// ...const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');const packageJson = require('./package.json')module.exports = { // ... plugins: [ new ModuleFederationPlugin({ name: 'products', // name of the item being exposed (required in container) filename: 'remoteEntry.js', // name of the file exposes: { './ProductIndex': './src/bootstrap' // actual file being exposed }, shared: packageJson.dependencies, // to remove duplicate external modules loading in the container }), // ... ]};
// container/webpack.config.js// ...const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');const packageJson = require('./package.json')module.exports = { // ... plugins: [ new ModuleFederationPlugin({ name: 'container', remotes: { products: 'products@http://localhost:8000/remoteEntry.js', // importing products file from port 8000 cart: 'cart@http://localhost:8001/remoteEntry.js', // importing cart file from port 8001 }, }), // ... ]};
With webpack now setup, we need to add our cart, products and container:
// cart/src/bootstrap.jsimport faker from 'faker'const mount = (element) => { // generating fake data element.innerHTML = ` <p>You have ${faker.datatype.number(10)} items in your cart</p>`}const mountPt = document.querySelector('#dev-cart')if (process.env.NODE_ENV === 'development' && mountPt) { mount(document.querySelector('#dev-cart'))}export { mount } // sharing generic mount function
// products/src/bootstrap.jsimport faker from 'faker'const PRODUCTS_COUNT = 5const mount = (element) => { // generating fake data let productsArr = [] for (let i = 0; i < PRODUCTS_COUNT; i++) { const product = faker.commerce.productName(); productsArr.push(`<div>${product}</div>
`) } const products = productsArr.join('') element.innerHTML = products}const mountPt = document.querySelector('#dev-products')if (process.env.NODE_ENV === 'development' && mountPt) { mount(mountPt)}export { mount } // sharing generic mount function
// container/src/bootstrap.jsimport { mount as mountProducts } from 'products/ProductIndex'import { mount as mountCart } from 'cart/Cart'mountProducts(document.querySelector('#product-list'))mountCart(document.querySelector('#cart-items'))
Now finally create an index.js
file in the src
folder of each sub-app & container
import('./bootstrap')
Creating this file with dynamic import is absolutely crucial as webpack fails to import the external packages without it (since the packages are shared, so they behave differently).
Now if your app is ready. You can add the following script in the scripts
section of package.json
:
"scripts": { "dev": "webpack serve"}
and call npm run dev
to start up the webpack server
Products (port 8000)
Cart (port 8001)
Container & the entire app (port 3000)
Wrapping Up
In this article, we went through the basics of Micro-frontend architecture. Hope it helps you in your development journey :)
I am currently working on a project utilizing Micro-frontend architecture, feel free to check it out:
ruppysuppy / Crypto-Crowdfund
Platform backed by Ethereum Blockchain to bring your creative projects to life
Thanks for reading
Looking for ways to boost your productivity? Check out my Bi-Weekly Productivity Blogs on Medium
Need a Top Rated Front-End Development Freelancer? Contact me on Upwork
Want to see what I am working on? Check out my GitHub
I am a freelancer who will start off as a Digital Nomad in mid-2022. Want to catch the journey? Follow me on Instagram
Follow my blogs for Weekly new Tidbits on Dev
FAQ
These are a few commonly asked questions I get. So, I hope this FAQ section solves your issues.
I am a beginner, how should I learn Front-End Web Dev?
Look into the following articles:Would you mentor me?
Sorry, I am already under a lot of workload and would not have the time to mentor anyone.Would you like to collaborate on our site?
As mentioned in the previous question, I am in a time crunch, so I would have to pass on such opportunities.
Connect to me on
Original Link: https://dev.to/ruppysuppy/micro-frontends-the-next-gen-way-to-build-web-apps-16da
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To