ThoughtWorks Live - What Does Technical Excellence Look Like?
"An architectural style where independently deliverable frontend applications are composed into a greater whole"
<body>
<h1>Feed me</h1>
<!--# include file="$PAGE.html" -->
</body>
server {
listen 8080;
...
location /browse {
set $PAGE 'browse';
}
location /order {
set $PAGE 'order';
}
}
{
"name": "@feed-me/container",
"version": "1.0.0",
"description": "A food delivery web app",
"dependencies": {
"@feed-me/browse-restaurants": "^1.2.3",
"@feed-me/order-food": "^4.5.6",
"@feed-me/user-profile": "^7.8.9"
}
}
<body>
<h1>Welcome to Feed me!</h1>
<iframe id="micro-frontend-container"></iframe>
<script type="text/javascript">
const microFrontendsByRoute = {
'/': 'https://browse.example.com/index.html',
'/order-food': 'https://order.example.com/index.html',
'/user-profile': 'https://profile.example.com/index.html',
};
const iframe = document.getElementById('micro-frontend-container');
iframe.src = microFrontendsByRoute[window.location.pathname];
</script>
</body>
<body>
<h1>Welcome to Feed me!</h1>
<!-- These scripts don't render anything immediately -->
<!-- Instead they attach entry-point functions to `window` -->
<script src="https://browse.example.com/bundle.js"></script>
<script src="https://order.example.com/bundle.js"></script>
<script src="https://profile.example.com/bundle.js"></script>
<div id="micro-frontend-root"></div>
<script type="text/javascript">
// These global functions are attached to window by the above scripts
const microFrontendsByRoute = {
'/': window.renderBrowseRestaurants,
'/order-food': window.renderOrderFood,
'/user-profile': window.renderUserProfile,
};
const renderFunction = microFrontendsByRoute[window.location.pathname];
// Having determined the entry-point function, we now call it,
// giving it the ID of the element where it should render itself
renderFunction('micro-frontend-root');
</script>
</body>
<body>
<h1>Welcome to Feed me!</h1>
<!-- These scripts don't render anything immediately -->
<!-- Instead they each define a custom element type -->
<script src="https://browse.example.com/bundle.js"></script>
<script src="https://order.example.com/bundle.js"></script>
<script src="https://profile.example.com/bundle.js"></script>
<div id="micro-frontend-root"></div>
<script type="text/javascript">
// These element types are defined by the above scripts
const webComponentsByRoute = {
'/': 'micro-frontend-browse-restaurants',
'/order-food': 'micro-frontend-order-food',
'/user-profile': 'micro-frontend-user-profile',
};
const webComponentType = webComponentsByRoute[window.location.pathname];
// Having determined the right web component custom element type,
// we now create an instance of it and attach it to the document
const root = document.getElementById('micro-frontend-root');
const webComponent = document.createElement(webComponentType);
root.appendChild(webComponent);
</script>
</body>
Avoid too many communicate
There are no free lunches when it comes to software architecture - everything comes with a cost.
We need to be able to draw clear boundaries that establish the right levels of coupling and cohesion between technical and domain entities.
We should be able to scale software delivery across independent, autonomous teams.