Isomorphic Layout Composer (ILC) - layout service that compose a web page from fragment services. It supports client/server based page composition.
It's key difference and advantage against other solutions lays in the fact that it does page composition isomorphically. It means that page will be assembled at server side using apps that support server side rendering (SSR) and after that it will be hydrated at client side so all further navigation will be handled by client side rendering.
This repository also contains an example of how you can create a front-end that is composed from multiple applications which work in concert and deliver unified experience.
Why do I need ILC?
Microservices get a lot of traction these days. They allow multiple teams to work independently from each other, choose their own technology stacks and establish their own release cycles. Unfortunately, frontend development hasn’t fully capitalized yet on the benefits that microservices offer. The common practice for building websites remains “the monolith”: a single frontend codebase that consumes multiple APIs.
What if we could have microservices on the frontend? This would allow frontend developers to work together with their backend counterparts on the same feature and independently deploy parts of the website — “fragments” such as Header, Product, and Footer. Bringing microservices to the frontend requires a layout service that composes a website out of fragments. ILC was developed to solve this need.
📦Based on single-spa & TailorX - battle tested solutions inside 📱Technology Agnostic - use it with React, Vue.js, Angular, etc... ⚙️Server Side Rendering support - key advantage over competitors 🗄Built-in registry - add new apps, pages or change configs and templates in few clicks. More info here. ⚡️Built for speed - server side part of the system adds just ~17ms of latency 👨💻Develop right at production - Doc 🌐Internationalization support - it is ready to serve your clients from any country. Doc, Demo with localized navbar 📡Other advanced features - Plugins, App Wrappers. 💲Baked by Namecheap - we use it internally and plan to evolve it together with community
🚀 Quick start
Check out demo website available online or go through the steps to spin it up locally:
- Clone this repository
docker-compose up -d
- During first launch or shutdown only. Run
docker-compose run registry npm run seed
More information about demo applications used in this quick start you can find here.
And don't miss the Step-By-Step lessons about apps development with ILC.
|– ilc: code of the Isomorphic Layout Composer |– registry: app that contains configuration used by ILC. Such as list of micro-fragments, routes, etc...
- Step-By-Step lessons about apps development with ILC
- Installation guide
- ILC to App interface
- ILC Registry
- Animation during reroute
- Global error handling
- Demo applications used in quick start
- SDK for ILC plugins development
- Compatibility with legacy UMD bundles
- Global API
- ILC transition hooks
To conveniently connect various frameworks to ILC we rely on the ecosystem of the single-spa provided adapters. However sometimes we need to extend original ones to deliver better integration with ILC. Here are the list of the adapters that were forked & modified:
We're using webpack (a static module bundler) to build each application for our micro-frontend approach. Webpack requires access to everything it needs to include in the bundle at build time. This means when an app that imports a service, for example planets importing the fetchWithCache service, webpack will try to bundle the service into the planets bundle. The built in way to avoid webpack doing this is webpack externals, using externals works really well but to avoid having to include a regex for each service I'm using the postfix to signal to webpack (and developers) that the import is another micro-app/service/front-end. The prefix isn't required if you would rather include a different postfix or none at all it should work, you'll just have to modify each webpack config for externals.
Code splitting is a complicated topic. I'm not going to dive into each facet of it within Webpack, see Webpacks docs for that.
In our project code splitting is further complicated because webpack's module format expects to load more modules from the website root, which will always fail in this project unless webpack is told where to load additional modules. Right now there is a single example of this, done in the people application.