DEV Community

Cover image for Unlocking the Power of Modern Web Architecture: Monorepos, Micro-Frontends, and Vite πŸš€βœ¨
Husnain Tariq
Husnain Tariq

Posted on

Unlocking the Power of Modern Web Architecture: Monorepos, Micro-Frontends, and Vite πŸš€βœ¨

✨ Introduction ✨:

Monorepo

A monorepo is a single repository that houses multiple interconnected yet independent projects. It simplifies development workflows by centralizing code management, enabling seamless code reuse, and streamlining dependency sharing. By fostering collaboration across teams and ensuring consistency in tools and practices, monorepos provide a more cohesive development environment compared to maintaining separate repositories.

Micro Frontend

A micro-frontend architecture decomposes a web application's frontend into smaller, independent units that can be developed, tested, and deployed individually. Each micro-frontend operates autonomously, enabling greater flexibility, scalability, and faster development cycles. This approach allows teams to work independently on specific features or modules, leveraging different technologies if needed while maintaining seamless integration within the larger application.

Module Federation and Vite

Module Federation is a powerful Webpack feature that enables the dynamic sharing and loading of code across remote locations. It allows multiple applications or modules to collaborate seamlessly by sharing dependencies and resources at runtime, without requiring a rebuild. This feature is particularly beneficial for implementing micro-frontend architectures, enabling independent teams to integrate their codebases efficiently while maintaining autonomy and scalability.

Vite It is a modern build tool for web development, focusing on speed and efficiency. Vite is designed to address performance issues associated with traditional build tools like Webpack and Parcel, especially in large-scale modern projects.


Challenges Addressed by These Tools 🀝

  • Scaling Teams: Facilitate collaboration across multiple teams by enabling parallel development with clear boundaries and shared resources.
  • Managing Dependencies: Simplify dependency sharing and versioning, ensuring consistency and reducing conflicts across projects.
  • Enhancing Development Speed: Accelerate development cycles with modular architectures, streamlined builds, and optimized workflows.

By leveraging these tools and patterns, developers can create scalable, maintainable, and high-performance front-end applications tailored to the demands of modern web development.


πŸ’‘Integrating Monorepos, Micro-Frontends, Module Federation, and Vite for Modern Web Development πŸ’‘

Impact

By combining these technologies, you create a powerful and flexible architecture for building large-scale, complex web applications. Here's a breakdown of the key impacts:

  • Enhanced Scalability: Independent deployment and updates of micro-frontends within a monorepo.
  • Improved Developer Experience: Faster development with Vite and streamlined workflows.
  • Optimized Performance: On-demand loading of code with Module Federation reduces initial load times.
  • Better Maintainability: Modular micro-frontends improve code organization and reduce coupling.

πŸ”₯πŸ”₯ Enough of this theory, let's see some action! πŸ”₯πŸ”₯

How to Do It?

1: Setup Monorepo

Choose a monorepo management tool like Lerna or Nx. (let's choose Nx for this demo project)

  • Let's create a folder and initialize Nx workspace there.

mkdir my-monorepo
cd my-monorepo

Enter fullscreen mode Exit fullscreen mode

2: Install Nx Cli:

  • Install Nx CLI globally into your system

npm add --global nx@latest 

Enter fullscreen mode Exit fullscreen mode
  • Initialize Nx workspace
npx create-nx-workspace@latest

Enter fullscreen mode Exit fullscreen mode
  • Use the Nx CLI to generate new applications and libraries within your workspace

nx g @nx/next:application host-app
.
.
.
nx g @nx/react:application my-remote-app
.
.
.
nx g @nx/react:library my-utils


Enter fullscreen mode Exit fullscreen mode

3: Configure Vite And Implement Module Federation:

  • Install the @originjs/vite-plugin-federation plugin in each micro-frontend's vite.config.js.

npm i @originjs/vite-plugin-federation -D

Enter fullscreen mode Exit fullscreen mode

Your Project structure should look like this

my-monorepo/
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ host-app/
β”‚   β”‚   β”œβ”€β”€ package.json
β”‚   β”‚   β”œβ”€β”€ vite.config.js
β”‚   β”‚   β”œβ”€β”€ src/
β”‚   β”‚   └── ...
β”‚   β”œβ”€β”€ my-utils/
β”‚   β”‚   β”œβ”€β”€ package.json
β”‚   β”‚   β”œβ”€β”€ src/
β”‚   β”‚   └── ...
β”‚   └── my-remote-app/
β”‚       β”œβ”€β”€ package.json
β”‚       β”œβ”€β”€ vite.config.js
β”‚       β”œβ”€β”€ src/
β”‚       └── ...
└── nx.json
Enter fullscreen mode Exit fullscreen mode
  • Create a vite.config.js (if not created by Nx) and configure it.
  • Implement module federation package.

Host-App Vite configuration:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [
     react(),
     federation({
      name: 'host-app',
      remoteApp: {},  // add Urls of your remote apps here
     shared: {
        react: {
          singleton: true,
          requiredVersion: '18.2.0',
        },
        'react-dom': {
          singleton: true,
          requiredVersion: '18.2.0',
        },
      },
    }),
  ],
});

Enter fullscreen mode Exit fullscreen mode

Remote-App Vite Configuration:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [
     react(),
     name: 'my-remote-app', // unique app name for your remote module
     filename: 'remoteEntry.js',
     exposes: {}, // add the path of any components you want to expose to the host app
     shared: {
       react: {
         singleton: true,
         requiredVersion: '18.2.0',
       },
       'react-dom': {
         singleton: true,
         requiredVersion: '18.2.0',
       },
     },
    }),
  ],
});

Enter fullscreen mode Exit fullscreen mode

πŸŽ‰ Congrats, your app is configured now. πŸŽ‰
Now, go ahead and create a component and expose it to the host app.

How to add a remote component to the host?

Let's assume you have exposed a component named as "AppComponent" and your remote name is "remoteApp"


const RemoteComponent = React.lazy(() => import('remoteApp/AppComponent'));

<Suspense fallback={<>Loading....</>}>
  <RemoteComponent />
</Suspense>

Enter fullscreen mode Exit fullscreen mode

*NOTE: * Make sure to add a remote URL to the host's vite.config.js file.

πŸŽ‰πŸŽ‰ Cool!! your app is ready, go ahead and create cool projects with it.

Real-World Scenarios 🌟

  • Large-Scale E-Commerce Platforms: Teams can independently develop and manage features like product pages, checkout flows, and user account management, enabling faster iterations and better scalability.
  • Enterprise Applications: Departments can own and manage specific features or modules, such as analytics dashboards, admin panels, or reporting tools, within a shared platform.
  • Widget and Dashboard Development: Different teams can build, maintain, and deploy individual widgets or dashboards, ensuring modularity and flexibility in large applications.

πŸ”— Check out my demo project code here πŸš€πŸš€: Monorepo project

Conclusion

Monorepos, Micro-frontends, Module Federation, and Vite, using the strengths of all the above technologies, can help organizations build scalable, maintainable, and high-performance web applications that meet the demands of modern development and business needs.

Additional Resources:

Nx Documentation
Vite Documentation
Webpack Module Federation
Micro-Frontend Architecture

Feel free to reach out if you have questions or need assistance in implementing this setup for your project. Let's build something amazing! πŸš€

Top comments (0)