Over the past few years, the number of web frameworks available to us has exploded. In some ways, the breadth of choice is a clear win for our ecosystem. However, for many of us, it also comes with harsh drawbacks: - Have you ever used a popular open-sourced component built for framework A, and wished it existed in framework B? What about a design system library? - Does your company have frontends built in different frameworks, and your web teams are frustrated about the wasted hours needed to achieve a consistent design system? - Does your team build SDKs for web frameworks, and must manually re-write them for each framework? The solution to all 3 of these problems exists today. To fully understand it, we must first examine today’s web frameworks, re-think what a component should look like, and introduce a new Intermediate Representation of our components. This is what we have done at Builder.io when we created Mitosis, and we’re excited to share it with everyone.
It's Time to De-Fragment the Web
AI Generated Video Summary
Today's Talk introduces Mitosis, an open source project that solves the problem of building framework agnostic components. It supports JSX and Svelte syntax and outputs human-readable code for various web frameworks. Mitosis is already being used by enterprise customers and can be easily integrated with React, Svelte, and other frameworks. It saves time, allows for easy handling of framework version migrations, and enables efficient unit and integration testing.
1. Introduction to Framework Agnostic Components
Today, I will discuss the idea of framework agnostic components. Building these components can be tedious, and current solutions like writing them by hand or using web components have tradeoffs. That's why we've developed Mitosis, an open source project that solves this problem. I'll show you why building these components is tedious, why Mitosis is a good solution, and how it works better than expected.
Well, you guys have a lot of energy for a full day of talks. Thank you for sticking around for mine. Thank you to the React Day Berlin organizers for choosing my talk and for everyone else who's in the room today. I'm really, really excited about what I want to talk about, so let's just dive in.
What I'm going to be discussing today is the idea of framework agnostic components. Those to those who are unfamiliar with that idea is when you write a component that you want to render in different web frameworks. So a React app, a Quick app, a Svelte app, a Vue app. There are a lot of scenarios where you want to build such a component because of a business need or any other kind of need. Doing that today is really tedious. You effectively have one of two choices. You can either do it by hand, write that same component over and over by hand four, five, six times, which is obviously not great, or you can use web components, which is a standard that's been developed on top of web browsers. Both of those have tradeoffs that we at Builder we're unhappy with. This is why we've come up with a solution, which is Mitosis, an open source project that's already been available for a couple of years now, that solves this problem for us and hopefully for other people. So I'm going to try to convince you that building those components is tedious right now, and I'm going to try to convince you that Mitosis is a good solution for that. And towards the end, I'm going to try to really, really convince you that Mitosis works, because it is almost too crazy to work, but it does work better than you would expect.
2. Introduction to Sami Jaber and Buildr
I'm Sami Jaber, a software engineer at Buildr and the primary contributor and maintainer of the Buildr.io SDKs. Buildr is a headless visual CMS that allows non-web developers to build web pages by dragging and dropping components. I also build the SDKs using Mitosis. Previously, I worked on Splash as a web developer.
Now, before we get into all of that, I just want to introduce myself briefly. My name is Sami Jaber, I'm a software engineer at Buildr. I'm the primary contributor and maintainer of the Buildr.io SDKs. So Buildr is a headless visual CMS, which means you can drag and drop your own components in a way that lets non-web developers build web pages, and what powers all of that is the SDKs, which need to be different for each web framework. And so I'm the contributor to those SDKs and I build them using Mitosis, which I'm also the primary contributor to. Before my time at Buildr, I was one of the web developers on Splash.
3. Introducing Sisyphus and the Buildr SDK
I'm going to introduce a fictional coworker named Sisyphus, the Buildr.io SDK engineer. Sisyphus's task of building web components repeatedly can be monotonous. The Buildr SDK is a library of components that supports server-side rendering. Sisyphus, who only knows React, is assigned to build the View SDK. He decides to learn Vue by studying each component line by line, starting with RenderContent.
Now instead of talking about myself, I'm going to imagine a fictional coworker and I'm going to name him Sisyphus, the Buildr.io SDK engineer. Show of hands, who's familiar with Greek mythology? Oh wow, a lot. So to those who are not familiar with Greek mythology, Sisyphus is a man who received an eternal punishment from the Greek gods. That punishment was to roll this huge boulder up a hill forever. Every time he'd get to the top, the boulder would roll down. He'd have to go down and start rolling it back up again. I chose the name Sisyphus because as you'll find it clear, and I will try to make it as clear as possible, building those web components, those UI components, over and over can get very, very monotonous.
So I'm talking about how Sisyphus is the SDK engineer, so what is this Buildr SDK that he's building? To keep it simple, it's essentially a big library of components. You have stuff like the image component, column, text, button, video, et cetera, all of which have style and state management and all these sorts of things. And one important feature that you're going to want to keep in mind is that this SDK needs to support server-side rendering out of the box, and that's going to become very important later.
So Sisyphus gets onboarded about a year ago. He becomes a builder engineer, he gets the job there, he figures out how everything works, and he decides I want to work on the SDKs. So far, the only SDK that exists is the React SDK. So his boss comes in and tells him, Sisyphus, I want you to build the View SDK. We have a lot of clients, and they want to use View, so they want to use Builder, but we only have a React SDK. Sisyphus has never written a line of View before in his life. Like many people in this room today, he only knows React. But he's excited to learn, and ambitious, and full of good spirits at this point. So he decides he's going to go over every component line by line and learn how to write that line of code in View.
Let's look at this hypothetical component called RenderContent. It's a React component. It has a name, it runs some code once in a UseEffect hook. There's some code it wants to rerun every time something changes. That's UseEffect with a dependency array. You want to create a context, so use.provider and add the value. You want to apply some styles, using the style property. You want to track a click, so you use onClick and you write your code. And last, you want to render another component and give it some properties. This is all very basic, very standard stuff that we do every day in React. So how do we do each one of these five or six things in Vue? Let's find out.
4. Vue Component Creation and Web Components
Well, what about server-side rendering, which is what I mentioned earlier. To those of you who may not know what server-side rendering is, it's when you want to render your web application on the server and then send the HTML output to the browser. Now why would you want to do that? For really good reasons. It will make your web app load faster, and it will give you a really good boost for SEO. It is pretty much a standard technique that everyone does today in every web framework. And so when we try to have web components rendered on the server, we realize that doesn't quite work today. Web components are built on top of the browsers, and servers don't know how to render them. There are a lot of workarounds that you'll find, but they're going to be specific to each web framework that you're trying to import the web component into.
5. Building SDKs for Different Frameworks
And what that means is if you're a builder and you want to build SDKs, you're going to have to tell every different person, oh, hey, you're using Svelte. Make sure to do this. You're using Next.js. Make sure to do that. You're using Vue, et cetera, et cetera. There's always different instructions. And that's just not a reasonable thing to do when you're a business. You want to have the ultimate user experience to your customers, which if they're software developers, you want them to be able to install and not have to worry about anything.
And so when I say here that web components are harder to use than native components, what I mean by native is that if you're in a React app, the best component is a React component, et cetera, et cetera, et cetera. There's no way around it. That's just the reality. React knows how to render React components better than it knows how to render web components.
So Sisyphe is getting a bit upset, a little frustrated, a little bored. He's done this twice already. So you can imagine his frustration when he has to do it a third time. And I'm going to spare you the implementation details, but he had to import something with a different name, use some slightly different syntax, and then he got the Solid JS SDK. And then he had to do it again with QUIC.
6. Sisyphus and the Box
7. Storing Code in JSON and Using JSX
All of those onMount calls are now being written by him one time and then being fed into generators that generate the right code for each web framework. So before he moves any further, he wants to store this somewhere. The best candidate is to use JSON. Everything that I just showed you can just be written in JSON. It's just strings. But no one here would want to write all of their UI components, all of their logic in JSON. The obvious candidate here is JSX, which doesn't have a logo. JSX is great for all of the reasons I just listed. You can parse JSX into the JSON schema that Sisyphus came up with. JSX Lite allows you to do anything you want in that JSX code, unlike if you were writing React.
He didn't quite get that yet but all of those onMount calls are now being written by him one time and then being fed into generators that generate the right code for each web framework. Pretty good, right? We're getting somewhere.
So before he moves any further he wants to store this somewhere. And obviously the best candidate is to use JSON. JSON's logo is a black hole which I never knew until I looked that up for this slide. And so he uses a JSON object, hooks, key, inside of it there's an onMount object and then he puts the code as a string like you see here. How far can we dig this? How many things can we put in that JSON and how many things can we just inject into strings and manipulate out of everything that I showed you earlier? Really really far.
And I know you're not going to believe me, so this is where I escape and show you my interactive demo. So you see on the top the JSON object that I'm talking about, and at the bottom you have the four outputs that I've been showing you in slides. And here you have the onMount code and what's neat is you can actually go here and add like another function call and as you can see it's being generated correctly in every place. I'm going to skip right to the end where we actually have the entire object. So you have an import statement, you have an onMount hook, onUpdate hook with the dependency, you can have the context, you can have a children array with the div, and then we have the styles. Everything that I just showed you can just be written in JSON. It's just strings. And then if I hide this so you can see the output better, you actually get the output that I've been talking about the whole time. So it's human readable output, it looks like something that anyone would write, because it's just a string interpolation. We have it working and these are actually valid files for each web framework. So this can be saved into a view file, a Svelte file, et cetera, et cetera.
So let's go back for a second and look at where we landed. So Sisyphus went from having just the onMount code to having everything, he wrote a bunch of generators for each thing, and now he's writing one JSON that generates the same component in every framework. Pretty cool. But I mean, no one here, I think, would want to write all of their UI components, all of their logic in JSON. It's really tedious, there's no type support, there's no syntax highlighting. So what else can we use? The obvious candidate here is JSX, which doesn't have a logo, so I took the liberty of combining the JSON black hole with the React logo. JSX is great for all of the reasons I just listed. Every code editor supports it, ESLint knows how to parse it, TypeScript supports it. It has a very rich ecosystem of tools, right? So there wouldn't be a need to build anything extra. You can just tap into JSX, and a lot of people are familiar with it already. You can also use Babel because it's able to parse JSX, so you can parse that JSX into the JSON schema that Sisyphus came up with. And finally when I say JSX Lite, I'm talking about the fact that you can do anything you want in that JSX code, unlike if you were writing React, because the more complex use cases you write, the more you have to make a smarter parser that can handle all of your edge cases.
8. Dynamic Code in CSS and JSX Syntax
Having dynamic code inside CSS can be problematic when using Svelte and Vue. Guardrails are necessary to handle this. The JSX syntax provides a familiar structure, similar to React, making it easy to write and run components anywhere.
So having crazy dynamic code running inside of your CSS is going to get hairy, because that CSS gets moved into a style tag in Svelte and Vue. So you have to have some kind of guardrails. And let me show you what that looks like. So if I were to go back here, show the input again, and so now we have the top input is not the JSON anymore, but it's this JSX syntax that I've talked about. And if I were to comment out everything, you'll see that we are getting that same component code that we were getting from the JSON, but now we're getting it from a JSX file. So at the top you can see it looks almost exactly like React, right? There's nothing unfamiliar about it. Just imports have maybe different names than what we're used to, on update instead of use effect. Everything looks familiar here, and then if I hide that, it's the exact same code. These are valid components that you can save and then run anywhere.
9. Introduction to Mitosis
Mitosis is an open source project that lets you write a component once and run it everywhere. It supports JSX and Svelte syntax and outputs human-readable code for various web frameworks. There are no weird dependencies or lock-in, as Mitosis simply generates the component into a React or Vue file.
Back here. So to go back to our graph that's been growing and growing and growing. We now have this scenario where Sisyphus is writing one JSX file and that gets converted into a JSON, which then gets generated into four different components that get saved as strings or as files. I mean he did it. That's what he wanted. That's what he wants to achieve and now there's a single source of truth. And in a nutshell, that's what Mitosis is. Mitosis is an open source project that we've come up with at Builder. It lets you write a component once and run it everywhere. You can write components in a JSX syntax or actually a Svelte syntax, which a contributor has added about two weeks ago. And it outputs this human readable code and this huge list of web frameworks and many, many more. And so just to be clear, there's actually nothing surprising about it. I showed you the code. It's what a normal developer would have written almost if they were to write that code over and over again. There's no weird dependencies being imported. There's no lock-in because at the end of the day, all Mitosis does is generate that component into a file that's a React file or a Vue file. So if at any point someone gets tired of using Mitosis or doesn't need different outputs, you can just take that output and use that instead as a source of truth.
10. Benefits of Mitosis and Building on Top
Most generators are in beta or alpha, but Mitosis is already being used by enterprise customers without any issues. Experian is one company that uses Mitosis for their UI design system. In demos, Mitosis components can be easily integrated with React, Svelte, and other frameworks. It allows for dynamic functionality, type generation, and component arguments. Mitosis saves human capital by avoiding redundant rebuilding of complex design systems like Material UI. Building on top of Mitosis allows for instant benefits from optimizations and bug fixes, creating a more efficient web.
The status today is I would say, most generators are in beta. Some of them are very early, so they're still in alpha. The foundation is all there, the parsers, and the generators, and the JSON schema, but there's bugs that need to be sorted out. But builders enterprise customers, a lot of them are running on those new SDKs that are built with Mitosis, and they can't even tell the difference. To them this is just a Svelte library, a Quik library, a Solid Jest library, they just don't even know, and it's powering their ecommerce site, their enterprise sites, and they have zero hiccups.
And there's also one example of Experian which is a company in the US who has actually been using Mitosis to generate some of their UI design system. And there are a bunch of other companies actually that are starting to consider using it. If you're still not convinced, I'm going to quickly dive into my last demo that I can show you because I feel that's the best way to convince people that this thing actually works. So on the left side you have this Mitosis component written in JSX, and I have here a React server and a Svelte server and you can see at the bottom that I'm actually importing this talk app in each case, and you import it normally, you render it normally, and over here it's like a fully dynamic to-do list app, so you can do whatever you want, you can delete, and the experience of building those components is not unfamiliar or unconventional. You just go here, if you want to make a change to the style here, all that happens is that Mitosis in the background is rerunning, updating the changes, which takes a second, but you see that the colour here gets darker almost instantly, so you're not suffering in terms of developer experience that much. As long as you wire everything together, it works.
Another example is an autocomplete example. You can have anything here, fetching data, promises, all of that. None of that is something that wouldn't work in Mitosis, because as I showed you, it's just strings being generated. So, you can do whatever you want, really, because you have those building blocks that can be generated properly. Anything else is possible. You can even have types generated. If you look here, in this SvelteKit example, SvelteKit is running after Mitosis and is generating types. There's full type support and all that, so you can know what you're providing. You can even provide components as arguments. So, these are, again, normal components. By now, hopefully, whoever has been watching and listening is convinced that maybe Mitosis is something that can work, and the question becomes, why should we use it? I think there's a good argument to be made that there's a lot of human capital and human resources being wasted today. One example is Material UI, which is a complex design system that you have four or five different teams rebuilding from scratch for every web framework. I don't think there's a lot of, like, recode reuse that's possible, so everyone's just doing the same thing over and over again, which I think is a real shame. It's a real shame that people are wasting a lot of hours doing what other people have already done in a slightly different flavor. I think that the world could benefit a lot if we were to do what, I guess, I titled this talk, which is to defragment the web. What I mean by that is that if we were to all build on top of something like Mitosis, And every time somebody optimizes a generator, finds something that can be done better, everyone benefits instantly. They just upgrade to the latest version. If somebody finds a bug, or if somebody writes a brand new generator that does something in a cooler or different way that handles a certain use case, everyone can tap into that instantly. And so to kind of recap who could benefit from this, I would say that people who are building systems like Material UI would be great candidates.
Benefits of Mitosis and Q&A
People building design systems in big tech companies with different web frameworks can benefit from Mitosis. Buildr SDKs also benefit from Mitosis, saving time and expanding the market. Try Mitosis, contribute, and see the results. Thank you! Now, let's move on to the Q&A session.
And lastly, people like us at Buildr. We have SDKs that actually need to export components for the web, and so in that case, using Mitosis is a huge time-saver and unlocks a bigger market right away.
So that's it. If you've watched this talk, you've actually understood every piece of Mitosis and how it works. So give it a shot, build some components, see if you find any issues, raise them, and contribute. Because again, you're just as capable as anyone who's already contributed because that's effectively how Mitosis works. It's not that much more complicated.
Thank you very much. Yay! Please. Step right here. Right here. This one, this one, this one. You're the star. You're the star. Alrighty. We'll do a couple questions and then the rest. Sammy will be at the speaker Q&A room out by reception. Or I think maybe online for the remote folks.
Okay. Let's see what we have from our Slido. Thank you for that talk. My pleasure. Love the vibe. Interesting. There's actually a few questions that are along the lines of, do you think that AI, for large language models, LLMs, could be a good solution to Sisyphus's problems? Translating between framework syntaxes automatically, and then there's another one that says, do you think AI could do a similar thing? I mean, I use GitHub Copilot a lot, so I like how much ease it gives me in terms of doing a lot of the work for me. I'd be surprised if anyone can trust an LLM or machine learning to just spit out the components that they're going to push to production just like that. Yeah, I would leave it up to something more deterministic like mitosis than something that just, like, you can't actually be 100% sure it will do what you want it to do. Would you trust GitHub Copilot to write all of your code and just, like, push it to production? I don't think so. Maybe one day.
Unit Testing and Integration Testing in Mitosis
Mitosis supports integration testing for all outputs, but unit testing is not possible for the mitosis component itself. Instead, a suite of unit tests can be run on the generated output to ensure framework agnosticity.
Okay, well that leads actually nicely into what is the thought around unit testing for mitosis or in mitosis? Oh, yeah. So, actually the nice thing is we've set this up for our SDKs and in the mitosis codebase you can just have these different servers running everything and run integration tests at least, so you can have integration testing set up for all of the outputs. You can't do unit testing for the mitosis component because it's not actually something that you can render, so you would want to have a suite of unit tests that would then run on the generated output and make sure that that suite is framework agnostic. But I would say integration testing is kind of the thing that mitosis can handle very easily right now.
Handling Framework Version Migrations
Mitosis allows for easy handling of framework version migrations, such as going from view-2 to view-3. By upgrading the generator and adding a config option, Mitosis can generate both view-2 and view-3 versions side by side. This flexibility extends to other frameworks like React, where multiple versions with different styling options can coexist. Users can choose the version that best suits their needs.
Cool! There is a couple about handling framework version migrations, like going from view-2 to view-3 and how you handle that. That's actually something we had to do. We had view-2 support, we had to have view-3 support, we upgraded the generator to have an option, the view generator in mitosis, to allow you to generate view-2 and view-3. And just by adding that as a config option we are now spitting out view-2 and view-3 side by side. And we just tell the view-3 users to import the view-3 version. So the nice thing about mitosis is that because you're not writing it by hand, you can just instantly generate like ten different versions for the same framework, each one with a slightly different use case. You can even do it for React, you can have like a React version that uses style.jsx, and one that uses emotion and one that uses style components and they'll all live side by side and you can tell people, take your pick, use whichever one you prefer.