Skip to content

nicklepickle/fe-compare

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

77 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Front-End Javascipt Library Comparison

About

This project is a comparison of front end javascript libraries. Libraries will be compared using a small test project with requirements detailed in requirements.html. The purpose of this project is to evaluate common front end challanges including cross component data binding, form validation, coalescing data from API calls, client side calculations and css theme support.

Supporting Libraries

This project is not evaluating back end technology. It will use express to implement a REST API and simple json files for storage. Vite is used to build and develop. Vite-express is used as glue. Implementations were all created by running npm create vite@latest and following the prompts.

Comparison Candidates

  • ES6 (no dependencies)
  • HTMX
  • React
  • Solid
  • Svelte
  • Vue

Key Differences

  • Vue and React use a virtual DOM while Svelte and Solid do not use a virtual DOM.
  • Svelte and Vue use HTML-first templating.
  • JSX used by React and Solid is a JavaScript-first templating language.
  • Svelte and Vue can scope css to a component while css included by JSX components is global.
  • HTMX relies on server side templating (i.e. express hbs) and is mostly a pure HTML solution.
  • ES6 uses no templating or framework and is a pure javascript solution provided as a baseline.

Comparison Criteria

The various libraries will be avaulated on the following criteria:

  • Market share
  • Amount of dependencies
  • Developer experience
  • Build size
  • Run time performance

Market Share (June 2025)

NPM Weekly Downloads

GitHub Stars

  • HTMX 609
  • React 481,128
  • Solid 324
  • Svelte 6359
  • Vue 108,683
  • HTMX 9.3% Desired / 72.9% Admired
  • React 33.4% Desired / 62.2% Admired
  • Solid 3.6% Desired / 67% Admired
  • Svelte 11.5% Desired / 72.8% Admired
  • Vue 16.3% Desired / 60.2% Admired
  • HTMX 7%
  • React 82%
  • Solid 9%
  • Svelte 26%
  • Vue 51%

Release Year

  • HTMX 2020
  • React 2013
  • Solid 2021
  • Svelte 2016
  • Vue 2014

Dependencies

ES6

"dependencies": {
    "express": "^5.1.0"
},
"devDependencies": {
    "vite": "^6.3.5",
    "vite-express": "^0.21.1"
}

node_modules size: 22.1 MB

HTMX

"dependencies": {
    "express": "^5.1.0",
    "hbs": "^4.2.0",
    "htmx.org": "^1.9.12"
},
"devDependencies": {
    "vite": "^6.3.5",
    "vite-express": "^0.21.1"
}

node_modules size: 22.4 MB

React

"dependencies": {
    "express": "^5.1.0",
    "react": "^19.1.0",
    "react-dom": "^19.1.0",
    "react-error-boundary": "^6.0.0"
},
"devDependencies": {
    "@eslint/js": "^9.25.0",
    "@types/react": "^19.1.2",
    "@types/react-dom": "^19.1.2",
    "@vitejs/plugin-react": "^4.4.1",
    "globals": "^16.0.0",
    "vite": "^6.3.5",
    "vite-express": "^0.21.1"
}

node_modules size: 44.8 MB

Solid

"dependencies": {
    "express": "^5.1.0",
    "solid-js": "^1.9.5"
},
"devDependencies": {
    "vite": "^6.3.5",
    "vite-express": "^0.21.1",
    "vite-plugin-solid": "^2.11.6"
}

node_modules size: 38.7 MB

Svelte

"dependencies": {
    "svelte": "^5.28.1",
    "express": "^5.1.0"
},
"devDependencies": {
    "@sveltejs/vite-plugin-svelte": "^5.0.3",
    "vite-express": "^0.21.1",
    "vite": "^6.3.5"
}

node_modules size: 27.7 MB

Vue

"dependencies": {
    "express": "^5.1.0",
    "vue": "^3.5.13"
},
"devDependencies": {
    "@vitejs/plugin-vue": "^5.2.3",
    "vite-express": "^0.21.1",
    "vite": "^6.3.5"
}

node_modules size: 38.5 MB

Build

ES6

> es6-test@1.0.0 build
> vite build

vite v6.3.5 building for production...
✓ 7 modules transformed.
dist/index.html                 2.61 kB │ gzip: 0.75 kB
dist/assets/index-J-7tryoT.css  1.75 kB │ gzip: 0.68 kB
dist/assets/index-qzgQcJRy.js   5.07 kB │ gzip: 1.87 kB
✓ built in 184ms

Total Uncompressed: 9.43 kB

HTMX

> htmx-test@1.0.0 build
> vite build

vite v6.3.5 building for production...
htmx.min.js can't be bundled without type="module" attribute (48.1 kB)
✓ 2 modules transformed.
dist/index.html                 5.28 kB │ gzip: 1.91 kB
dist/assets/index-J-7tryoT.css  1.75 kB │ gzip: 0.68 kB
✓ built in 157ms

Total Uncompressed: 55.13 kB

React

> react-test@0.0.0 build
> vite build

vite v6.3.5 building for production...
✓ 36 modules transformed.
dist/index.html                   0.37 kB │ gzip:  0.26 kB
dist/assets/index-x91orODR.css    1.75 kB │ gzip:  0.68 kB
dist/assets/index-D1Xc-jUN.js   194.72 kB │ gzip: 61.28 kB
✓ built in 441ms

Total Uncompressed: 196.84 kB

Solid

> solid-test@0.0.0 build
> vite build

vite v6.3.5 building for production...
✓ 13 modules transformed.
dist/index.html                  0.46 kB │ gzip: 0.29 kB
dist/assets/index-x91orODR.css   1.75 kB │ gzip: 0.68 kB
dist/assets/index-DXVV_tn8.js   16.75 kB │ gzip: 6.66 kB
✓ built in 190ms

Total Uncompressed: 18.96 kB

Svelte

> svelte-test@0.0.0 build
> vite build

vite v6.3.5 building for production...
✓ 101 modules transformed.
dist/index.html                  0.40 kB │ gzip:  0.27 kB
dist/assets/index-N8SxIneX.css   2.19 kB │ gzip:  0.74 kB
dist/assets/index-DQ5tZtIL.js   26.66 kB │ gzip: 10.53 kB
✓ built in 289ms

Total Uncompressed: 29.25 kB

Vue

> vue-test@0.0.0 build
> vite build

vite v6.3.5 building for production...
✓ 18 modules transformed.
dist/index.html                  0.39 kB │ gzip:  0.27 kB
dist/assets/index-CtDfmxcm.css   2.20 kB │ gzip:  0.75 kB
dist/assets/index-DxMo-c_l.js   67.36 kB │ gzip: 26.61 kB
✓ built in 359ms

Total Uncompressed: 69.95 kB

Run time performance (Mac OS + Safari 18.3.1)

ES6

  • 100 Records: Total payload: 41.1 KB | Load time: 40.6 MS
  • 1000 Records: Total payload: 99.5 KB | Load time: 63.1 MS
  • 2000 Records: Total payload: 165.1 KB | Load time: 68.1 MS

HTMX

  • 100 Records: Total payload: 101.1 KB | Load time: 66.2 MS
  • 1000 Records: Total payload: 323.2 KB | Load time: 51.6 MS
  • 2000 Records: Total payload: 573.1 KB | Load time: 79.9 MS

React

  • 100 Records: Total payload: 228.6 KB | Load time: 54.3 MS
  • 1000 Records: Total payload: 286.9 KB | Load time: 44.3 MS
  • 2000 Records: Total payload: 352.5 KB | Load time: 63.9 MS

Solid

  • 100 Records: Total payload: 50.7 KB | Load time: 58.2 MS
  • 1000 Records: Total payload: 109.9 KB | Load time: 66.2 MS
  • 2000 Records: Total payload: 174.9 KB | Load time: 52.3 MS

Svelte

  • 100 Records: Total payload: 61.0 KB | Load time: 48.8 MS
  • 1000 Records: Total payload: 119.3 KB | Load time: 66.1 MS
  • 2000 Records: Total payload: 184.9 KB | Load time: 56.0 MS

Vue

  • 100 Records: Total payload: 101.7 KB | Load time: 55.0 MS
  • 1000 Records: Total payload: 160.0 KB | Load time: 75.4 MS
  • 2000 Records: Total payload: 225.6 KB | Load time: 90.6 MS

Run time performance (Windows 11 + Chrome 138.0.7204.97)

ES6

  • 100 Records: Memory: 9.0 MB | Resources: 41.4 KB | Load: 285 MS
  • 1000 Records: Memory: 50.1 MB | Resources: 99.7 KB | Load: 576 MS
  • 2000 Records: Memory: 88.5 MB | Resources: 165 KB | Load: 2130 MS

HTMX

  • 100 Records: Memory: 13.5 MB | Resources: 102 KB | Load: 1530 MS
  • 1000 Records: Memory: 77.6 MB | Resources: 329 KB | Load: 2290 MS
  • 2000 Records: Memory: 63.2 MB | Resources: 583 KB | Load: 1830 MS

React

  • 100 Records: Memory: 25.7 MB | Resources: 229 KB | Load: 1730 MS
  • 1000 Records: Memory: 51.1 MB | Resources: 287 KB | Load: 1820 MS
  • 2000 Records: Memory: 75.4 MB | Resources: 353 KB | Load: 1320 MS

Solid

  • 100 Records: Memory: 17.8 MB | Resources: 50.8 KB | Load: 996 MS
  • 1000 Records: Memory: 52.3 MB | Resources: 109 KB | Load: 1200 MS
  • 2000 Records: Memory: 91.1 MB | Resources: 175 KB | Load: 1690 MS

Svelte

  • 100 Records: Memory: 13.5 MB | Resources: 61.1 KB | Load: 983 MS
  • 1000 Records: Memory: 53.7 MB | Resources: 119 KB | Load: 1090 MS
  • 2000 Records: Memory: 126 MB | Resources: 185 KB | Load: 1180 MS

Vue

  • 100 Records: Memory: 16.7 MB | Resources: 102 KB | Load: 983 MS
  • 1000 Records: Memory: 59.9 MB | Resources: 160 KB | Load: 1340 MS
  • 2000 Records: Memory: 158 MB | Resources: 226 KB | Load: 1930 MS

Takeaways

Market share

If market share and all the benefits that go with it (community, developers, compatible packages, tutorials and let’s be honest in 2025 GPT, Copilot, Cursor prompting) then React is the clear winner here. By any of the metrics considered and I am certain many that were not, React has more market share than all of the other candidates combined. React is the oldest of these technologies and will likely stick around far into the future. HTMX and Solid are about tied for the lowest market share and are the newest options. Solid has the benefit of using JSX which I would imagine makes it easier to adopt if you and your team are already familiar with React. This was certainly true for me.

Dependencies

While React is the clear winner when it comes to market share it is on the bottom wrung if your main concern is minimizing dependencies. React has an abundance of compatible packages and it all but forces you to use some of them. This is a clear trade off from my perspective. More compatible packages mean more functionality that you don't have to write yourself but also means a more complex dependency graph and a larger build size. In contrast Svelte (true to its name) has an impressively small node_modules directory and dependency list in general. Solid also gets a nod here. HTMX has deceptively minimal dependencies because it offloads all dynamic rendering to the server. If you are already using SSR with e.g. PHP, cshtml, jsp, etc. then this is a non-issue but if you need to evaluate SSR solutions then this could add a fairly significant dependency.

Developer experience

Previously on...

DX is obviously a very subjective topic and depends greatly on prior experience. To take a small bio detour, I've spent the majority of my career as a back-end dev. My experience with front-end was heavy during the jQuery and then Angular years. I did use an earlier version of React during the class component era so JSX was not a new concept. Most of the projects I maintain professionally have been migrating off of jQuery towards standard ES6 replacing jQuery with fetch and querySelector. Angular was abandoned when it moved to TypeScript. We have an appetite to use a more modern approach and here we are.

Developer methodology

My methodology during development of these test projects was to start each project using vite create, try to implement the requirements using the official docs, rely on tutorials when I had questions and then falling back on Copilot when all else failed. Once the projects were created, tested and working, I took a second pass to improve consistency. My goal was not perfection but rather an application that demonstrated more real world complexity than a counter or to-do list.

React vs. Solid

React's move from class components to hooks definitely makes it a lot more dev friendly. I am still unsure when to useEffect and when it is unnecessary. I wanted to stick with fetch for API calls for consistency but saw many suggestions to use react-query at the cost of yet another dependency. This is my main critique of React. It seems to force you into the React ecosystem making the standard JS API feel like a second class citizen. In contrast Solid allowed a more standard approach to writing JSX and components in general. I really appreciate that Solid does not complain about JS keywords in JSX. It makes migration much easier. I also appreciate the control flow elements which can be a bit more intuitive than using JS primitives in React JSX. I initially expected Solid would offer less features than React but was pleased to see it does support complex features beyond what I could demonstrate in these test projects e.g. suspense rendering and SSR.

Svelte

Prior to this project I had no direct experience with Svelte or Vue. They were both approachable by virtue of their HTML first design. State handling with runes in Svelte feels very similar to React hooks. The key difference is that $state does not return a setter. Instead, Svelte offers the $bindable rune for two way data flow. In some ways $bindable is simpler than passing setters around as props. Svelte seems to discourage it's use claiming "This isn’t something you should do often". My experience is this is something I do often and I could see the temptation to make everything bindable leading to a jQuery like situation where it is difficult to reason about who updates what.

Vue

I did struggle with Vue state more than state in the other projects. This was largely a skill issue and turned out to be much simpler than I initially thought. Some of this had to do with the fact that there are multiple ways to handle state in Vue (data vs. ref vs. Vuex). At one point I fed most of my Vue files to Copilot to figure it out and it produced a completely broken solution. My main critique of Vue is that it seems there has been a lot of churn in the API. After my successful implementation, I learned I probably should have been using Pinia for state all along. This isn't uncommon in any library that has been around for a while and Vue is over ten years old. React suffers from some of the same issues but I do appreciate backwards compatibility so c'est la vie.

HTMX

HTMX is definitely the odd man out. In some ways it is comparing apples to bicycles when set along side the other libraries. HTMX relies entirely on server-side rendering so there is no templating here. I was surprised how much milage I got out of the hx- attributes. Form validation and cookie access were the only features which required writing javascript and even there I was able to take advantage of the htmx JS functions to do a lot of useful things. State is entirely managed on the server due to SSR which isn't necessarily a bad thing and certianly better than having a large SQL data set that must be synced with a mirror of that data on the client. I do believe that a large and complex enough application would eventually devolve into a jQuery like mess using only HTMX. My largest HTMX critique though is the lack of support for loading as an ES6 modules. In 2025 modules should be the default and I want to import htmx from 'htmx.min.js' which as far as I can tell is not possible.

CSS

The style requirements for the test projects were fairly simple. The only dynamic css was toggling the display of the add item modal and toggling a dark mode theme. I was a little disappointed that in almost all of the solutions the main app had to know to remove the .hidden class to show the modal. If that css class is defined in the component I need to know more about its implementation than it seems I should as a parent.
Toggling dark mode was largely trivial due to the fairly new color-scheme property. One key difference between how Svelte and Vue handle component css vs JSX is that css can be scoped entirely to the component e.g. h2 {color:purple} would only style h2's within the component. In JSX, css included in a component is global.

Vite

The unsung hero in this project as a whole is Vite. Vite provided a fantastic starting point for all of the libraries, user friendly dev and build tools and a simple integration with the purposefully basic express back end. I doubt I would have had the patience to complete this without it. Shout out to Vite!

Build size

As you would expect build size tracks with dependency count. More dependencies mean bigger build. The winners here are Solid and Svelte with Solid beating Svelte by 11 KB. The heaviest build was React coming in at over ten times the size of Solid. How much this matters depends heavily on the size and complexity of the application as well as the target audience. That said most public facing web apps will target mobile users pulling your app down over a cellular network where they could be running as slow as 300-400 kbps over 3G.

Run time performance

All of the performance benchmarks were measured with a production build using preview with only one browser tab open and some attempt to minimize other processes. With an application the size and complexity of the test project, all of the projects performed well enough that any discrepancies in load time or memory usage are likely due to the environment they were running in rather than the speed of the build even with records cranked to 2000. If there is any takeaway here it is that my Windows 11 work laptop running Chrome performed radically worse than my 2021 M1 iMac running Safari.

What about...

Angular?

Angular is now a TypeScript library which you can not use with pure JS. This is a JS library comparison. It is disqualified. I also have opinions from prior experience. But hey, try it out. Vite create an angular app and see for yourself. Not pretty.

TypeScript?

I have nothing against TypeScript and I do think strong types in general are a good thing. That said all of the front-end code I currently maintain is JS. Porting it to TS would be a huge time sink and I don't think it would solve the types of issues that show up. But yes, knowing that 1+1=2 and not 11 without Number() would be nice.

Server components?

This is a valid question because every library evaluated here has some sort of SSR companion. React has Next.js, Solid has solid-start, Svelte has SvelteKit, Vue has vue/server-renderer. All of these assume you want to run JavaScript on your back-end. Do you want to run a JS back-end? My professional opinion is unless it is a small project that is not public facing, no you mostly don't. JS eats memory like me at a BBQ. It is slower than compiled languages and it is hard to reason about what it's doing under the hood thus hard to optimize. My current job runs C# and SQL Server. If I was building a commercial web application in 2025 I would consider Go. The reason HTMX snuck in is because it is back-end agnostic but it isn't really doing components either.

Conclusion

There are no bad choices here. All the options evaluated here will absolutely do the job. If market share is what you want React is your answer full stop. If you are dealing with highly stylized components that rely heavily on hand rolled css, I would suggest Svelte or Vue. If speed and build size are your top criteria it's hard to beat Solid. If javascript just annoys you and you want to write less of it, HTMX is a good bet. If learning any of this sounds like a migraine, just adopting the principles of modern ES6 with modules, fetch, async, etc. will do wonders for your JS code. And finally, Vite makes all of it much more pleasant than it has literally ever been.

About

A comparison of front end js libraries

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •