Intro
It’s been 7 years since solidjs came out and Ryan Carniato wrote a blog post on it. And since i love it so much i thought i should talk about it. Since its inception in 2018 solid has been leading the performance benchmark but even today there’s not much solid out in the production (not nearly as much as react) except a few like Telegram web client and Nord Vpn; don’t believe me? you can easily dig through the sourcemap and find out. So allow me to advocate for solid and hopefully you’ll see the light by the end of the article.
The world of Frontend
About a year ago when i started transitioning from a backend framework (django) into js world, i wondered how hard it could be and boy it was rough. Javascript frameworks are overly complex and i’m not exaggerating. What do you need for a simple a website to work. A server which renders html page directly to the dom but you’re asking for more fancy thing right? so you have to pay for it by using modules.
oh what kind of modules then? common js? ES6?
who cares i just want things to work.
So.. better pick a bundler.
Fine, i’ll do it.
Now you can create site with fancy libraries like tailwind. But now you need routes. frontend routes are not as easy as you may think. it’s not something as easy as:
if( req.url.pathname == '/somepath'){
return <somecomponent/>
}
You’ll have to hack through Location API to get a basic a basic router working and even if you do there’s much more you’ll have to handroll yourself like catch all routes, path params, query params etc etc.
So.. better pick a router.
Fine, i’ll do it.
Now you need to fetch data from your backend what you’ll use. Hey we can use fetch api right? wrong! you need to use useEffect hook so you can have any kind of state other than data so you can deliver optimistic updates to your user. This is how a typical data fetching in react looks like:
function MyComponent() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch("https://api.example.com/stuff")
.then((res) => res.json())
.then((data) => {
setData(data);
setLoading(false);
})
.catch((err) => {
console.error("Error fetching data:", err);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
This ugly piece of code just to fetch a simple api, imagine nesting it with Promise.all to fetch multiple data from multiple sources. So if you want to fetch data with loading states?
better pick a data fetching library.
(shout out to tanstack query)Fine, i’ll do it.
You can keep going like this forever and you’ll find that you need a library for every single thing in this ecosystem. be it data fetching, be it state management or as simple as setting the title of the document in an ssr application (It’s real btw React helmet)
I’m not sh!tting on react because its cool now but simply because react just don’t seem to keep up with with the modern web application requirements. Even today they don’t mention in their docs about vite being the easiest way to get started with react now that they even deprecated “create-react-app”. Every single framework out there switching to signals but react refuses to change even though everybody know how inefficient virtual dom is (you can’t even use selectelement queries, what a shame).
What solid offers
What solid offers is a unified library which has all the things that you need to create a web
application. Ryan carnito has put together something so remarkable that it
made half the industry to move with his solution. i.e using proxies
instead of virtual doms and diffing. Fine grained reactivity with less overhead and cleaner code.
React had some noble ideas like JSX and Ryan has only taken it further by making primitives. Choosing jsx as templating language is clever and to me seems to make perfect sense because why would you want to create another templating language when it does the job and it is familiar to a lot of devs already. One more thing about jsx is the dev tools have already perfected it. You don’t need any additional lsp servers or plugins, which is a common occurance with new frameworks like svelte or vue. And even with extra plugins the lsp/syntax highlighters don’t seem to parse it correctly.
Data Fetching in solid is handled by the router itself and if you think about this it makes perfect sense. A Metaframework is nothing but a frontend library + router. What sort of resource you’d want to cache on which routes and which you want to keep refetching for it to be the most recent one should be handled by router.
const fetchUsers = async (id) => {
const response = await fetch(`https://api.example.com/users`);
return response.json();
}
//Inside the component
const [data, setdata] = createSignal();
const [dataset] = createResource(data, fetchUsers);
This small piece of code will give you loading state, error state and the data itself. This is all you need to fetch data in a solid app so even if you’re not using the router you can easily query data.
Ever needed to install a whole state management library for even a minimal number of reactive data? Behold Stores
const [state, setState] = createStore({
tasks: [],
numberOfTasks: 0,
})
const addTask = (text) => {
setState("tasks", state.tasks.length, {
id: state.tasks.length,
text,
completed: false,
})
state.numberOfTasks++;
}
Things that you need to work in a modern web app is at your fingertips and you don’t have to go through npm and pick a library for it.
Why Solid and not a React Meta Framework?
So naturally anyone would ask why should i use solid and not some meta framework like Next js or Remix which provide all the extra utility and helpers to do things, there’s plenty to choose from too. The ecosystem is huge and the performance is okay.
The reality is something different. Often the performance of these metaframework is not great. they try to vender lock you in their expensive subscription plans by making it harder to deploy anywhere except their own cloud infrastructure. And there was even a huge security issue in the Nextjs middleware not long ago.
Also if you have already deployed your app and its a huge codebase. i wouldn’t recommend moving to solid, that be dumb (unless its a specific reason). The best you could do is use preact signal to make it more readable and less cumbersome to manage.
The advantage you get from solid is less headaches from re-renders
Less stupid library hunt because solid already provides enough things that you can make your app work easily and move to a specific library in future only if your app is getting too large.
And last but not least easy deployments. SolidStart is built on nitro and vite. Vite provides all the bundling meanwhile nitro makes it super simple to deploy on almost any provider you want. Nitro presets provide 20+ configurations and some of them are zero config deployment, i.e. all you need to do is to tell app config which provider you want to deploy on and it’ll take care of rest.
I don’t see a reason for it not to be the industry standard. Check out Solid docs.