Show HN: Microfronts – Front-end solution for running multiple frameworks as one
github.com
github.com
I worked at a major travel company (you know the brand) that ignored its legacy web+backend for almost 10 years until our parent company basically gave us away to our biggest competitor (the tech was all abandoned as unusable) who made us just a marketing brand (also 100% of people laid off in the process). We couldn't keep up with our competitors as everything was impossible to fix any more. On the other hand the mobile team I worked with replaced everything and we were extremely agile in competing (other than being limited by the crappy back end).
It's not always a good idea to replace everything, but it's also not a good idea to live with shit either.
I agree leaving your house in this "junkyard sculpture" state indefinitely (love that analogy) will eventually kill your business.
The bigger question might be how much more painful was it than continuing to try to be competitive (react with new functionality, deliver ongoing value, etc) in the previous codebase, and how much more painful over trying to plan out small incremental refactoring changes during the same time? And... after a certain time period of going through that pain, was the end result quantifiably more useful (testable, fewer bugs, faster, easier to grok/extend/etc - choose your metrics) than if that big change wasn't undertaken?
I’m starting to fear that the right response, especially considering the Big Picture, is to let it die. Let some other competitor with fresh ideas eat your lunch. I suspect these problems are symptoms of a deeper, terminal illness and palliative care is the best you can do.
But the number of people who want to hear this is depressingly low. It’s more common in younger people, but they have no clout, so I get mentees easily enough, but they take a long time to become allies.
The places I look back on fondly, I had a boss who agreed, but often their skip level boss was having none of it, so the work was still... well, work.
No team(s) wants to maintain a SPA written in multiple frameworks. If you truly must, embed a component written in framework X into a component in framework Y.
The embedding of components is a good way to re-factor your way out of having multiple frameworks and migrating towards a single framework. We've been doing this successfully at work where we're incrementally migrating our AngularJS + React SPA to Vue one component at a time.
While I'm not sure this is the right solution, the problem absolutely does exist. There are loads of companies that have to deal with extremely shitty, brittle front ends that are confronted with a difficult "scrap the whole thing and rebuild it" vs. "incremental improvements" challenge.
If this tool is used appropriately as a way to piecemeal replace parts of your website, then I think it could be very useful. While I love deleting old crappy technology as much as any other developer, I've seen more than my fair share of "big bang" replacements fail miserably and result in huge team burnout and reduced trust between the business and technology sides of a company. On the other hand, I would only support this tool if the end game was indeed getting rid of all the crappy old stuff. Living in a world with umpteen different languages and ways of doing things on the front end is a recipe for extremely low productivity.
Thus, like most tools, something like this can easily be misused but there is certainly a place for it if used appropriately.
The iframe angle is probably the most universal, and easiest way to include legacy apps / sites. It does present challenges with authentication, as cookies cannot be persisted by a framed context. Local storage still works, but that requires some changes in the legacy apps.
As far as the "orchestrator" goes, I don't see the point of using a nearly-legacy framework (yes, a jab at Angular) when this can be done in plain vanilla JS with postMessage. Some balk at using events, but in this context messaging between clients could be a light, elegant solution to the communication / synchronization problem.
Finally -- this is bound to fail in actual real-world applications, because legacy apps are very likely to include everything and the kitchen sink, and simply wrapping them in frames doesn't solve the problem of a bloated do-everything spaghetti monster.
As an architectural approach for developing new, modular front-end solutions, this is promising. Multiple small teams responsible for small, single-purpose apps, stack-agnostic in aggregate -- this way of handling scale could reduce the overall complexity, making development and maintenance a little easier.
I'm glad to see two solutions out there, because there's a lot of variety in how this problem can be solved. For example, single-spa recommends (but does not mandate) using import maps [0] using SystemJS (to get better cross-browser support) The idea is, each application says they want 'react-dom' or '@angular/core', and it is resolved to a URL.
However, if applications are built expecting, say, different versions of dependencies, a naive approach to import maps won't work (e.g., the import 'react-dom' is requested-- how do we know which version to serve?).
At my employer, we take each frontend application and transpile to ES Modules and then combine via webpack. It's not what's recommended in Single SPA, but it greatly simplifies the deployment architecture for us.
We don't have to worry about hosting a CDN that can resolve import maps, everything's just in the bundle.
Our solution is called Piral, https://github.com/smapiot/piral, however, we do not believe that mixing technologies should be a solution - it's rather a workaround (which we also support). The real deal from our point of view is in independent development, deployment, and modular, decoupled thinking.
We were using EmberJS, which is a framework that I liked a lot, but it was just almost impossible to hire frontend developers to work with Ember. It is such a niche framework that it is basically asking developers to compromise their future career prospects to work on it at this point.
We used Single SPA to make an organized and gradual transition from Ember to React.
So having a solution to run different frontend frameworks is a way to avoid lock-in on a single framework (which can go out of favor in the future for whatever reason).
1. Some abstraction. 2. Replacing the existing "thing" with a new one that had more functionality.
Building layers of abstraction is typically safer and easier, but the abstractions aren't free. There's a really performance and completely tax to using the additive approach. Just take a look at the Win32 API. So many calls are slow AF and just reading a file off the disk in Windows requires 1000s of syscalls and confext switches- because of too much "safe" abstractions built over the years.
Compare this to Apple's engineering strategy, where they often deprecate and replace an APIs. This is obviously more abusive to the developers, and the users, but arguably better for the long term stability and performance of the system.
Windows, like any big system, has problems, but not this one. Its FS is slow, but not for this reason.
And searching the whole disk for a partial filename? tens of minutes.
I can do both in a database on the same machine in seconds...
Another problem is that the Windows Api is designed differently from the Linux Api. Windows is optimized for network drives, Linux more for local drives. Software designed for Linux often hits access patterns that don't perform well in Windows.
0: https://docs.microsoft.com/en-us/windows-hardware/drivers/if...
Disruptive has a distribution problem - how do you get people to use it
Vertical integration can be "10x better" and if you meet that threshold, maybe people adopt it, like iphones
Or maybe you have existing distribution networks or power to get people to act
On line 24 in this file an object is sealed, but it has a type assigned. What does sealing this object change? Is there a concern that other running code will try to assign or delete properties on this object?
https://github.com/eavichay/microfronts/blob/master/src/rout...
If an app is partially build with React, Angular and/or other lib/frameworks, that is in itself a red flag. You might be dealing with legacy code while moving to a newer stack. Using the same lib/framework brings you less mental overhead and quicker development speed, developer onboard, etc. Unfortunately I worked in some places where this was a sad reality and it was never easy to fix simple bugs due to the lack of structure, architecture, code conventions, etc . A refactor is your best friend but good luck convincing the product owner that you need X amount of time to bring 0 new features to the business.
Downsides of Iframes:
1. For each iframe you use, you'll use more memory, more CPU, bandwidth, increased TTI, etc.
2. You'll have to deal with subdomains authentication
3. Data over fetching, each iframe fetch its own data without sharing with another iframe. Trying to cache this is a sure way to chaos.
3. Breaking an app into tiny packages might be overkill when compared to having a proper folder structure, specially for UI.
4. Now you have a Content Security Policy to maintain, it gets trickier over time.
5. You’ve N CI pipelines, some repos will be “forgotten“ -> older React/Angular versions, packages that never got updated because you don’t work in that repo/“microfront”.
6. More DevOps overhead
7. Forget about good UX and be welcome to the world of redirects -> a “microfront” that takes you to another “microfront”
In my experience, breaking the business logic into packages is great since the logic is self-contained with unit testing, etc but placing the UI components there will bring you the problem of not having atomic UI components. Now if you want to change a UI component in just 1 package, good luck trying to figure out which pages could be broken.
You’ve to be very careful on how you break your app into packages, it only takes 1 bad design decision to make the whole thing a nightmare to work on. Not to mention when you’ve packages that depend on other packages, you haven’t written anything about versioning which is critical.
It is much easier to look at page built with React/Angular where you can see the exact definition of the UI versus jumping between several packages to try to figure out where do things come from. Put the UI components and pages in a single folder/package. If you something like StoryBook and create your package for UI components, even that brings some work to get right and maintain, you split these components into more than 1 package and you’ll be running in hell for simple changes.
Reduced mental overhead is a precious luxury I strongly value.
edit: formatting