Skip to content

Instantly share code, notes, and snippets.

@PsyGik
Created April 4, 2021 09:52
Show Gist options
  • Save PsyGik/95954ee99cbebf66011ff78296cb144f to your computer and use it in GitHub Desktop.
Save PsyGik/95954ee99cbebf66011ff78296cb144f to your computer and use it in GitHub Desktop.
Code snippets for the blog post: Microfrontends are awesome!
import React from 'react';
import ScriptCache from './script-cache';
class MicroFrontend extends React.Component {
scriptCache;
abortController;
constructor(props) {
super(props);
this.state = {
containerId: ''
};
this.scriptCache = new ScriptCache();
}
componentDidMount() {
this.loadScripts();
}
loadScripts() {
const {match, host, containerId} = this.props;
// TODO: export this.
this.abortController = new AbortController();
fetch(`${host}/asset-manifest.json`, {
signal: this.abortController.signal
})
.then(res => res.json())
.then(manifest => {
const entryPoints = manifest['entrypoints'];
let styles = [];
let scripts = [];
entryPoints.forEach(path => {
path.includes('.css') ? styles.push(`${host}/${path}`) : scripts.push(`${host}/${path}`);
});
styles.forEach(style => {
this.loadStyles(style)
});
this.scriptCache
.setScripts(scripts)
.setContainerId(containerId)
.load(scripts).then((event) => {
if(this.props.host === host)
this.renderMicroFrontend();
});
});
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (prevProps.containerId !== this.props.containerId) {
// we are trying to unmount previous app
const {name} = prevProps;
const {window, containerId} = this.props;
this.unmountMicroFrontend(name, window, containerId);
this.loadScripts();
}
}
loadStyles = (style, containerId, index) => {
const styleId = `style-${containerId}${index}`;
if (!document.getElementById(styleId)) {
const styleRef = document.createElement('link');
styleRef.setAttribute('rel', 'stylesheet');
styleRef.setAttribute('type', 'text/css');
styleRef.setAttribute('href', style);
document.head.appendChild(styleRef);
}
};
componentWillUnmount() {
const {containerId, window, name} = this.props;
this.unmountMicroFrontend(name, window, containerId)
}
unmountMicroFrontend = (name, window, containerId) => {
if(this.abortController){
this.abortController.abort();
}
if(window[`unmount${name}`]){
window[`unmount${name}`](containerId);
}
};
renderMicroFrontend = () => {
const {name, window, containerId} = this.props;
if(window[`render${name}`]){
window[`render${name}`](containerId);
}
};
render() {
const {containerId} = this.props;
return <main id={containerId}/>;
}
}
MicroFrontend.defaultProps = {
document,
window,
};
export default MicroFrontend;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment