In my 7 years of front-end development experience, I have witnessed the evolution of web technologies. I began during the PHP and jQuery era, navigating the browser wars. In 2017, I embraced node.js and React, finding its simplicity appealing. However, as I delved deeper, I realized React had its complexities, including routing, state management, and performance optimization.
To address these challenges, Next.js emerged, gaining industry recognition. Still, React had its lingering issues. That is when I explored Svelte and its contender, SvelteKit. In this article, I assess whether Svelte is a genuine alternative to the React/Next.js ecosystem or just hype.
In the red corner we have Next.js, a battle-tested popular React framework for building server-rendered React applications. It provides features that enhance React development, such as server-side rendering, static site generation, and routing.
In the blue corner we have SvelteKit, a new and modern front-end framework that builds on the concepts of Svelte, which aims to simplify the development of web applications by providing a streamlined approach to building reactive user interfaces.
The challenge that sets these two frameworks against each other revolves around building a simple blog powered by a Headless CMS (Content Management System).
I wanted a fair competition, so I aimed to introduce minimal extra dependencies into the project, ones that would hold up in a real-world scenario and have a framework-independent or highly similar counterpart in the other framework. This is how technologies like Tailwind CSS, TypeScript, Portable Text, and the CMS's own supplementary libraries found their way in, which facilitated my work and led to cleaner code.
Backend development is not my forte, but I value simplicity. Curiosity led me to explore how a widely acclaimed Headless CMS would complement our two contenders. That is why I opted for Sanity.io, a cloud-based headless CMS engine with comprehensive integration guides for both frameworks in its documentation.
As I mentioned, the project itself involved creating a blog, with a focus on frontend development(what a surprise 😳). One day, I will even launch the finished version as my own blog.
Primarily, I created a Sanity.io account, where I learned that I needed to install a node.js-based Sanity Studio. This platform allowed me to easily create my own data types, documents, and of course, content, all of which would be synchronized with the Sanity cloud.
This process went incredibly smoothly, and I created the three main entities: post, author, category. With these, I could describe everything necessary for the project. I even generated a few posts to have some data to work with. Since the focus of the article is not on Sanity, I will not delve deeply into this part. However, there are two key things worth highlighting here:
The usage of Sanity's own query language GROQ, and the format of the Rich Text fields generated by Sanity, known as Portable Text.
The initial one is a unique query language that bears a resemblance to GraphQL. Unlike making REST API calls, it empowers developers to ask for data in a specific manner. This language is divided into two primary segments: a filter section, which assists in selecting data, and a projection segment, which outlines the desired data structure. I will not conceal that the syntax might pose a slight challenge, particularly when dealing with nested components. Nevertheless, after becoming familiar with it, one can smoothly and effectively navigate through it.
The latter, as I mentioned, is a JSON descriptive language that defines the format of rich text fields. This was also developed by Sanity. It is particularly handy when dealing with frameworks that build components from useful parts. With this approach, we do not inject statically generated HTML code into components, but rather, we gain control over the component's implementation.
I chose to initiate the creation of both frontend projects using the CLI recommended by their respective developers. The development environments for both frameworks are easily installable, and incorporating TypeScript, Tailwind, and code quality/testing tools is a straightforward process.
With the debut of version 13 in Next.js this year, React Server Components were introduced. This feature allows us to create server-side React components without sending a single byte of JavaScript code to the client side. To maintain usability of the existing structure, Vercel organized this functionality into an app directory, where layouts and pages can be easily created. As this is a competition, I aimed for a highly performance-oriented page, and I built the Next.js version of the blog using this approach.
SvelteKit inherently follows a remarkably similar project structure. However, it might seem more complex that there are so many files associated with a single page. The brief answer is that this separation allows for better distinction between server-side and client-side code, making it easier to prevent sensitive data leakage to the client.
Since I was more experienced with Next.js projects, I thought it would be a bigger challenge to start development with SvelteKit and eventually port the finished code to React/Next.In hindsight, this proved to be rewarding, as I managed to rewrite the code from SvelteKit to Next.js in just one evening. The work with Svelte took about a week in total, during which the actual development was much less time-consuming. However, this phase involved implementing the design and layout, the queries, and all the logic. Likely, even if I had taken the reverse approach, the workload would not have been significantly different.
As I emphasized earlier, there is a fantastic CLI that liberates developers from a lot of boilerplates writing and configuration hassles. Personally, I enjoy working with Next.js; its new routing structure takes the simplicity of creating pages to a whole new level. There is a wealth of tutorials and completed projects available on the internet, which can assist in solving emerging issues. Both Next and React are backed by large communities, and associates with enterprises like Sitecore. At ALLWIN, we have successfully executed a joint project involving Sitecore and Next.js, significantly reducing development time compared to a traditional project. The well-structured ecosystem around React contributes to enhanced productivity, as you can find well-written libraries for every problem domain. One downside that stems from React is the challenge of code refactoring as the project grows. Especially when optimizations are involved, it becomes increasingly difficult to refactor the code. Moving the state back and forth can disrupt functionality in multiple places, and these optimizations can be non-trivial for novice developers. The abundance of wrappers and higher-order functions makes certain parts of the code less transparent and harder to maintain.
It also offers fantastic developer experience, beginning with its robust CLI, fast bundling, and efficient routing. Unlike React, Svelte deals less with the challenges of state management. It boasts a well-designed subscription-based store system, leading to simpler and more maintainable code. Additionally, variables adopted at the component level are reactive by nature; no imports are needed. Svelte conducts granular UI updates, meaning only the necessary parts are re-rendered when values need updating. This approach avoids re-rendering the entire component tree due to a change in state. Its straightforward state management results in rapid component/page development.
At present, Svelte's downside is its relative newness; while its enthusiastic community exists, it has not yet reached the magnitude of React's community. Consequently, there are fewer usable libraries available, and among them, many are still in the experimental stage. For instance, finding robust component libraries or form handling libraries for enterprise applications can be challenging. It is worth noting that SvelteKit, even though it has been around for less than a year, is already supported by numerous libraries, which is a rarity.
Next provides developers with many tools for enhancing performance. For instance, it supports a wide array of rendering patterns, such as Server-Side Rendering (SSR), Static Site Generation (SSG), Incremental Static Regeneration (ISR), Client-Side Rendering (CSR), as well as Streaming SSR facilitated by Server Components. These cover all market demands. However, that is not all; Next.js features built-in image optimization, which recently received a facelift due to its usability concerns. Code splitting works effectively, and for more extreme cases, it can offer component lazy loading. For the sake of comparison, I used SSR, which might be the slowest strategy after CSR due to continuous page rebuilding. However, utilizing CSR for a blog, especially one that heavily relies on SEO (Search Engine Optimization), is not advisable.
The use of the Portable Text component for rich text parsing significantly increased the bundle size on the post page. The build process took around 7-8 seconds in general using the webpack build. Vercel's own tool, Turbopack, is currently in beta and promises much faster build times in the future.
Web Vitals are a set of metrics introduced by Google to measure and quantify the user experience on websites. These metrics aim to provide developers with insights into how well their websites perform in terms of loading speed, interactivity, and visual stability, all of which contribute to the overall user experience.
With Next.js, we can observe that despite the larger bundle size, the page loading performance is quite satisfactory. This is due to the usage of Server Components and the well-structured framework, even when utilizing SSR. Of course, these times could have been further reduced, but my goal was to explore how easy it is to create well-optimized pages with minimal effort, and Next.js did not disappoint us.
At present, SvelteKit supports fewer rendering patterns than Next.js. We can choose from SSR, SSG, or CSR. Image optimization is not built-in, and component lazy loading is also lacking. However, out-of-the-box, it excels in code splitting compared to Next.js, resulting in smaller bundle sizes.
While it is more challenging to determine the actual bundle size, looking at the pages reveals that none of the pages come close to Next.js's maximum of 400kb. For the build process, Svelte utilizes a tool called Vite, resulting in a general build time of around 2-3 seconds, which is twice as fast.
Surprise, isn't it? Despite SvelteKit not being as mature a framework as Next, its advantages shine through. Thanks to its lack of a virtual DOM, smaller bundle size, and closer alignment with native web solutions, it emerges as a winner in performance.
While not the most exciting aspect for developers, it is worth mentioning that through SSR, search engines index our site more easily and effectively. Both SvelteKit and Next provide options to place meta tags anywhere within our pages. However, Next recently took a step forward in this realm, offering tools for dynamic open graph image generation and even providing its own sitemap generator. These features are still missing from SvelteKit.
Of course, these challenges can be addressed using other tools, but it is evident that Vercel is paying keen attention to these aspects during Next's development.
Creating the project on either platform did not pose any significant challenges, but when it comes to SvelteKit, finding libraries was tougher compared to the well-established React ecosystem. For simpler projects, SvelteKit can compete with Next, but due to its current ecosystem size and the absence of foundational features like middleware and i18n support, I am not inclined to recommend it for enterprise applications just yet.
However, in terms of speed and developer experience, it already surpasses what the React/Next duo offers. Transitioning from React is also quite seamless, with a shallower learning curve. In my view, teaching a junior developer to write well-optimized code with Svelte is easier and faster than with React.
Oh, and I almost forgot, who is the winner? Well... me! Because I have gained a wealth of new experiences in the past few weeks while working on this project and article in my spare time. Both frameworks are doing well, and I have learned a lot. React is here to stay for a long time, no need to write it off, while Svelte is a fantastic alternative with many future possibilities. The two frameworks have their own place and time when they are worth using. The React ecosystem is vibrant, and Svelte offers a great alternative with plenty of potential. So, both have their merits, and I am glad to have had the chance to explore them.
If SvelteKit continues its current trajectory and pace, it could quickly catch up to, and even surpass, Next.js. We eagerly anticipate developments in this space!
PS: I have deployed the (kind of) finished version of the blog to UIndefined, which totally will not be another neglected pet project of me.