This document outlines the technical plan for migrating six Angular applications to React + Next.js using a micro-frontends architecture with Module Federation. The plan allows for gradual migration while maintaining a functioning overall system.
Create a new Next.js project:
npx create-next-app@latest shell-app
cd shell-app
Install necessary dependencies:
npm install @module-federation/nextjs-mf
Configure Next.js for Module Federation (next.config.js):
const NextFederationPlugin = require('@module-federation/nextjs-mf');
module.exports = {
webpack(config, options) {
config.plugins.push(
new NextFederationPlugin({
name: 'shell',
remotes: {
app1: 'app1@http://localhost:3001/remoteEntry.js',
app2: 'app2@http://localhost:3002/remoteEntry.js',
app3: 'app3@http://localhost:3003/remoteEntry.js',
app4: 'app4@http://localhost:3004/remoteEntry.js',
app5: 'app5@http://localhost:3005/remoteEntry.js',
app6: 'app6@http://localhost:3006/remoteEntry.js',
},
shared: {
react: {
singleton: true,
requiredVersion: false,
},
},
})
);
return config;
},
};
Create a layout component (components/Layout.tsx):
import React from 'react'
import Link from 'next/link'
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div className="min-h-screen flex flex-col">
<header className="bg-blue-600 text-white p-4">
<nav>
<ul className="flex space-x-4">
<li><Link href="/">Home</Link></li>
<li><Link href="/app1">App 1</Link></li>
<li><Link href="/app2">App 2</Link></li>
<li><Link href="/app3">App 3</Link></li>
<li><Link href="/app4">App 4</Link></li>
<li><Link href="/app5">App 5</Link></li>
<li><Link href="/app6">App 6</Link></li>
</ul>
</nav>
</header>
<main className="flex-grow container mx-auto p-4">
{children}
</main>
<footer className="bg-gray-200 p-4 text-center">
© 2023 Your Company Name
</footer>
</div>
)
}
Update pages/_app.tsx:
import type { AppProps } from 'next/app'
import Layout from '../components/Layout'
import '../styles/globals.css'
export default function App({ Component, pageProps }: AppProps) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
For each Angular application, create a corresponding Next.js application:
Create a new Next.js project:
npx create-next-app@latest app1
cd app1
Install dependencies:
npm install @module-federation/nextjs-mf
Configure for Module Federation (next.config.js):
const NextFederationPlugin = require('@module-federation/nextjs-mf');
module.exports = {
webpack(config, options) {
config.plugins.push(
new NextFederationPlugin({
name: 'app1',
filename: 'static/chunks/remoteEntry.js',
exposes: {
'./App': './pages/index.tsx',
},
shared: {
react: {
singleton: true,
requiredVersion: false,
},
},
})
);
return config;
},
};
Create the main component (pages/index.tsx):
import React from 'react'
export default function App1() {
return (
<div className="bg-green-100 p-4 rounded-lg">
<h1 className="text-2xl font-bold mb-4">Welcome to App 1</h1>
<p>This is the content of App 1, now migrated to React and Next.js!</p>
</div>
)
}
Repeat steps 1-4 for each remaining application (app2 through app6).
Create pages for each micro-frontend in the shell app (pages/app1.tsx):
import dynamic from 'next/dynamic'
const App1 = dynamic(() => import('app1/App'), { ssr: false })
export default function App1Page() {
return <App1 />
}
Repeat for app2 through app6.
Update the home page (pages/index.tsx):
import Link from 'next/link'
export default function Home() {
return (
<div className="space-y-4">
<h1 className="text-3xl font-bold">Welcome to Our Micro-Frontend App</h1>
<p>Click on the links below to navigate to different apps:</p>
<ul className="list-disc list-inside">
<li><Link href="/app1" className="text-blue-600 hover:underline">App 1</Link></li>
<li><Link href="/app2" className="text-blue-600 hover:underline">App 2</Link></li>
<li><Link href="/app3" className="text-blue-600 hover:underline">App 3</Link></li>
<li><Link href="/app4" className="text-blue-600 hover:underline">App 4</Link></li>
<li><Link href="/app5" className="text-blue-600 hover:underline">App 5</Link></li>
<li><Link href="/app6" className="text-blue-600 hover:underline">App 6</Link></li>
</ul>
</div>
)
}
Install Redux:
npm install redux react-redux @reduxjs/toolkit
Create a shared store (store/index.ts):
import { configureStore } from '@reduxjs/toolkit'
const store = configureStore({
reducer: {
// Add your reducers here
},
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
export default store
Wrap the shell with Redux Provider (pages/_app.tsx):
import type { AppProps } from 'next/app'
import { Provider } from 'react-redux'
import store from '../store'
import Layout from '../components/Layout'
import '../styles/globals.css'
export default function App({ Component, pageProps }: AppProps) {
return (
<Provider store={store}>
<Layout>
<Component {...pageProps} />
</Layout>
</Provider>
)
}
This plan provides a structured approach to migrating Angular applications to React + Next.js using Module Federation. It allows for gradual migration while maintaining a functioning system. Adjust as needed based on specific requirements and application complexity.