I'm trying to Implement Cam Jackson’s micro-frontend applications, so far I'm able to create 3 following react application:
- parent app
- child1 app
- child2 app
The problem that I'm facing is with the routing. parent app routes:
const Child1 = ({ history }) => (
<MicroFrontend history={history} host={childapp1} name="child1" />
);
const Child2 = ({ history }) => (
<MicroFrontend history={history} host={childapp2} name="child2" />
);
const App = () => (
<BrowserRouter>
<Account>
<React.Fragment>
<ReactNotifications />
<AppHeader />
<Routes>
<Route exact path="/" element={<Signin/>} />
<Route exact path="/about" element={<About/>} />
<Route exact path="/child1/*" element={<Child1/>} />
<Route exact path="/child2/*" element={<Child2/>} />
</Routes>
</React.Fragment>
</Account>
</BrowserRouter>
);
Child app1 routes:
<BrowserRouter>
<Account>
<React.Fragment>
<ReactNotifications />
<Routes>
<Route path='child1' element={<ProtectedRoute><Home/></ProtectedRoute>}/>
<Route
path="child1/dashboard"
element={
<ProtectedRoute>
<Dashboard/>
</ProtectedRoute>
}
/>
<Route path="child1/forbidden" element={<ForbiddenPage/>}
/>
</Routes>
</React.Fragment>
</Account>
</BrowserRouter>
So far all right, When i try to navigate from child1/any-route to '/' which is a signin route in parent. it tries to search for a component which is at '/' in the child app1 routes which seems to be a expected behaviour, what i want to understand is how can i navigate from childapp1's component to parent app's signin route.
i tried to navigate using useNavigate hook on token expiry by following code:
In child app1
const ProtectedRoute = ({ children }) => {
const { authData } = useAuth()
const navigate = useNavigate()
console.log(authData, 'authData');
if (authData.isAuthenticated && authData.expiryTime > Date.now()) {
return children
}
else{
navigate('/')
}
};
export default ProtectedRoute;
expected workflow is:
parent app's signin -> childapp1/home -> authToken expires -> navigate to parent app's signin
update: MicroFrontend.js
import React from 'react';
class MicroFrontend extends React.Component {
componentDidMount() {
const { name, host, document } = this.props;
const scriptId = `micro-frontend-script-${name}`;
if (document.getElementById(scriptId)) {
this.renderMicroFrontend();
return;
}
// if (document.getElementById(styleId)) {
// this.renderMicroFrontend();
// return;
// }
var parentUrl = `${window.location.protocol}//${window.location.href.split('/')[2]}`
if (name === 'child1'){
fetch(`${parentUrl}/child1/asset-manifest.json`,{
method: "GET",
})
.then(res =>res.json())
.then(manifest => {
console.log(manifest, 'manifest');
const script = document.createElement('script');
const linkforCSSfile = document.createElement("link")
linkforCSSfile.href = `${parentUrl}/child1${manifest['files']['main.css']}`
linkforCSSfile.type = 'text/css'
linkforCSSfile.rel = 'stylesheet'
script.id = scriptId;
script.crossOrigin = '';
script.src = `${parentUrl}/child1${manifest['files']['main.js']}`;
script.onload = this.renderMicroFrontend;
document.head.appendChild(script);
document.head.appendChild(linkforCSSfile)
})
}
else{
fetch(`${parentUrl}/child2/asset-manifest.json`,{
method: "GET",
})
.then(res =>res.json())
.then(manifest => {
console.log(manifest, 'manifest');
const script = document.createElement('script');
const linkforCSSfile = document.createElement("link")
linkforCSSfile.href = `${parentUrl}/child2${manifest['files']['main.css']}`
linkforCSSfile.type = 'text/css'
linkforCSSfile.rel = 'stylesheet'
script.id = scriptId;
script.crossOrigin = '';
script.src = `${parentUrl}/child2${manifest['files']['main.js']}`;
script.onload = this.renderMicroFrontend;
document.head.appendChild(script);
document.head.appendChild(linkforCSSfile)
})
}
}
componentWillUnmount() {
const { name, window } = this.props;
window[`unmount${name}`]?.(`${name}-container`);
}
renderMicroFrontend = () => {
const { name, window, history } = this.props;
console.log(history);
window[`render${name}`]?.(`${name}-container`, history);
};
render() {
return <main id={`${this.props.name}-container`} />;
}
}
MicroFrontend.defaultProps = {
document,
window,
};
export default MicroFrontend;
Thanks in Advance.