8 votes

What JavaScript framework should I use?

Little backstory. I'm the sole developer of delphitools, a collection of free and open source tools for artists, developers and just computer touchers in general. I'm using Next.JS and as such, React, but I don't think I like it anymore. DT is a completely offline exported application, and Next is meant for middleware-heavy apps with server layers, which I just don't have. I also just don't get on with React's endless use effect garbage and have little love for TypeScript, and if I'm honest, DT happens to be made like that because I wanted to try the shiny new thing. Now that I have around 60-ish individual micro-apps contained within, I think it's time for a rewrite.

I'm therefore looking for discussion and insights on what tooling is best for me, on the following grounds:

  1. delphitools is export only. There's no server component and it runs completely in the browser. Server capabilities or middleware are not a concern.
  2. I'm not married to JavaScript as the runtime. It's just what I know best, I've been in the industry for a long time, although I'm more familiar with classic JS, not necessarily the JSX react syntax. I'm confident I could learn something new though.
  3. I'm looking for fast build times, a smart-ish compiler that can ideally hot reload and give me insights into bad practices (Next.JS does this quite well)
  4. As close to bare metal as possible, I can't begin to enumerate the amount of times the NextJS Turbopack auto-caching thing has caused me significant headaches.

I'm a designer, not a developer, but I can manage my way around. I'm also not opposed to using Agents, but I would like to - if for my own sake more than anything - be able to work without them if need be. Suggesting Ruby that compiles to HTML or some other crazy new pipeline probably won't work.

Curious to hear your experiences and recommendations. Thanks!

23 comments

  1. [6]
    bkimmel
    Link
    Don't use one. There's nothing React / whatever really gets you anymore that you can't get from native Web Components and all the effect and suspense garbage it comes with serves literally no...

    Don't use one. There's nothing React / whatever really gets you anymore that you can't get from native Web Components and all the effect and suspense garbage it comes with serves literally no point anymore. It's time has officially come and gone.

    As far as Typescript goes, if there's no one else contributing to your project and you don't like it - don't use it. It is useful to bind contracts into things you provide, but contracts are for two or more people.

    For good builds, etc I'd recommend using Bun if you just want a standard kit you don't want to think about too much or Vite.

    9 votes
    1. skybrian
      Link Parent
      Maybe it’s because it’s what I’m familiar with, but to me, Web Components seem really complicated with their slots and shadow dom, etc, while JSX seems more like simple HTML templates, directly in...

      Maybe it’s because it’s what I’m familiar with, but to me, Web Components seem really complicated with their slots and shadow dom, etc, while JSX seems more like simple HTML templates, directly in JavaScript. If React seems too complicated, there are simpler ways to get JSX syntax.

      I would rather pass parameters to templates as JavaScript values than mess with html attributes.

      5 votes
    2. Johz
      Link Parent
      I strongly disagree with this statement. To be clear, I think not using a framework at all can be a fine option, and I also think React has a lot of issues that make it a poor framework. My own...
      • Exemplary

      There's nothing React / whatever really gets you anymore that you can't get from native Web Components and all the effect and suspense garbage it comes with serves literally no point anymore. It's time has officially come and gone.

      I strongly disagree with this statement.

      To be clear, I think not using a framework at all can be a fine option, and I also think React has a lot of issues that make it a poor framework. My own personal preference would be for SolidJS, that's what I usually go for if I'm using a framework, otherwise I'll sort of hand-roll things if they aren't too complicated. Either way, I am not trying to denigrate web components or claim that React is some brilliant tool that solves all your problems. However:

      Web components are not a replacement for React. Web components are mostly orthogonal to React, they should be used for different things.

      React provides, roughly, three major things: reactive state (i.e. when I change some application state, trigger the appropriate side effects including updating the UI); templating (i.e. a declarative syntax for describing how the UI should look depending on the state); and state management (i.e. how do I stay in control of a complex state tree). It isn't necessarily great at all three (templating is great, reactive state is overly complicated by the UI = f(state) paradigm, and state management exists but is mostly supplemented by third-party libraries), but all three are present.

      Web components provide two things: a set of APIs for isolating parts of the DOM in different way, and a declarative syntax for executing these APIs from HTML. It's also worth keeping in mind that the APIs aren't necessarily even tied to web components - you can use the shadow DOM without ever creating a custom component - but the two parts are mostly connected for historical reasons.

      Many people use web components via Lit, but Lit is a fairly standard web framework, much like React, that just happens to use web components internally. When you use Lit, you get all the reactive state, templating, state management goodies that you get from React and other frameworks, but only because Lit is providing them, and not because they have anything to do with web components themselves.

      You should reach for web components if:

      • You are writing code that will be embedded into a variety of different contexts and frameworks, and you want consumers to be able to use a consistent syntax to pass data into your code
      • You are writing a widget that is entirely self-contained with very clearly defined inputs and outputs, essentially something like a date picker or a chart widget that can be dropped into any page.

      That's probably not the case in this instance, in which case web components aren't really adding much.

      I also don't agree with your comment about the "effect and suspense garbage". In fairness, React makes effects more complicated than they need to be, but both tools are incredibly useful. Effects are how you interact with things outside of the React world, and suspense is how you cope with asynchronous data. If you don't have these things, you need to either load all data upfront (impractical for anything that's actually reactive where that data can change) or you manually manage that asynchronicity everywhere that it's needed, essentially building your own less-good version of suspense. All frameworks have something like suspense, although different frameworks have different APIs and names for it. Svelte and SolidJS in particular are actively exploring this space in detail because of how useful it turns out suspense can be.

      1 vote
    3. [2]
      hobbes64
      Link Parent
      I agree that web components are a good choice. If nothing else it will help you organize a library and think about reusability of widgets. Then if you decide to use react or angular or anything...

      I agree that web components are a good choice. If nothing else it will help you organize a library and think about reusability of widgets. Then if you decide to use react or angular or anything else you can make wrappers for the web components and continue to use them. Also you can share them with the community if you want.

      1 vote
      1. tanglisha
        Link Parent
        This is my first time really looking at Web components. It looks like react used to look.

        This is my first time really looking at Web components. It looks like react used to look.

        1 vote
    4. teaearlgraycold
      Link Parent
      Contracts are helpful for one person as well. They are used to define and inforce certain types of invariants. Without a build step you can even do this across the front-end/back-end. My preferred...

      Contracts are helpful for one person as well. They are used to define and inforce certain types of invariants. Without a build step you can even do this across the front-end/back-end. My preferred setup these days is a JSDoc annotated tree of .mjs files on the front-end and TypeScript on the back-end, both in the same repo.

      1 vote
  2. teaearlgraycold
    Link
    You've lost me

    and have little love for TypeScript

    You've lost me

    3 votes
  3. [2]
    nullbuilt
    Link
    Disclaimer: not a frontend developer, take this with a grain of salt. I’ve had brief experiences with Svelte (not SvelteKit - that’s the server one) and I have to say it was pleasant enough for a...

    Disclaimer: not a frontend developer, take this with a grain of salt.

    I’ve had brief experiences with Svelte (not SvelteKit - that’s the server one) and I have to say it was pleasant enough for a person like me, with strong BE background and definitely not a JS enjoyer.
    It checks a lot of your boxes: strong compiler, hot reloads, good ecosystem.
    I don’t really understand what you mean by “close to bare metal as possible”, cause to me that means C lol.

    By the way, I’ll use the occasion to say that I’m a big fan of delphitools! Thanks for working on it.

    2 votes
    1. delphi
      Link Parent
      Ah, that was my bad - I mean, little abstractions. I write JavaScript or HTML, the next time I reload that should be what's loaded, and not go through endless levels of minification, obfuscation...

      Ah, that was my bad - I mean, little abstractions. I write JavaScript or HTML, the next time I reload that should be what's loaded, and not go through endless levels of minification, obfuscation and caching, at least for development environments. Bad wording on my part, and glad you're enjoying DT!

      I hear good things about Svelte, it's currently in the running along with Ember and my personal front runner Vue, but I've had personal bad experiences with a messy Svelte codebase before, so I guess we'll see?

  4. [2]
    Moogles
    Link
    Vue or Svelte. I just do design now but I found Vue and Svelte to be easier to pick up then React or Angular.

    Vue or Svelte. I just do design now but I found Vue and Svelte to be easier to pick up then React or Angular.

    1 vote
    1. delphi
      Link Parent
      Yeah, that's what it's gonna come down to, realistically. I'm between Vue, Svelte and Ember right now, with Ember coming from a personal recommendation of a close personal senior designer friend....

      Yeah, that's what it's gonna come down to, realistically. I'm between Vue, Svelte and Ember right now, with Ember coming from a personal recommendation of a close personal senior designer friend. Going through the tutorial right now and I quite like it so far.

  5. redwall_hp
    Link
    I haven't had a chance to use it in a project, because I work for a company that's been doing a lot of React lately (and I want nothing to do with front end stuff, anyway) but...HTMX. It's an...

    I haven't had a chance to use it in a project, because I work for a company that's been doing a lot of React lately (and I want nothing to do with front end stuff, anyway) but...HTMX. It's an anti-JavaScript framework that focuses on giving you things that might actually need to be dynamic in a markup-driven interface and otherwise avoids JavaScript. You just write and return HTML.

    1 vote
  6. [5]
    creesch
    Link
    Typescript is pretty the de-facto default in JavaScript world these days. Out of curiosity, is it Typescript or the fact that strongly typed languages are something you aren't too familiar with?...

    have little love for TypeScript

    Typescript is pretty the de-facto default in JavaScript world these days. Out of curiosity, is it Typescript or the fact that strongly typed languages are something you aren't too familiar with? There is some valid reasons to stick to stronger typing, but Typescript also often gets made overly complex by some folks.

    I'm not married to JavaScript as the runtime.

    If it needs to run in the browser JavaScript or a superset are basically your options. Technically speaking you could do stuff with WebAssembly but I am not sure what the benefit would be for the tools available on the UI side. I mention UI specifically since you seem to be looking for a framework to do the front-end, which WebAssembly is bad at. But, for a lot of the image manipulation, encoding, hashing, etc it could be a valid choice. Just seems out of scope for what you are asking.

    I'm looking for fast build times, a smart-ish compiler that can ideally hot reload and give me insights into bad practices (Next.JS does this quite well)

    How about basically no build times? If it is mostly the UI you are concerned with you could explore Web Components . You write them in vanilla JS and HTML without the need to build them. Web Components are not without their issues though, dealing with shadow DOM styling can be a pain for example. And you still would need to build all reactivity yourself.

    As far as bad practices goes, I would throw a linter against it (eslint) and for good measure also prettier so you have consistent markup as well.

    If you want something like hot reloading you can include something like browser-sync or I guess vite.

    As close to bare metal as possible, I can't begin to enumerate the amount of times the NextJS Turbopack auto-caching thing has caused me significant headaches.

    Web components is the closest you will get while still have somewhat of a "framework". The alternative is doing much of it basically just in vanilla HTML, JavaScript and CSS. Which is possible, though does require more planning and thought in some areas. Something you might not want to deal with but it would check a lot of boxes you mentioned.

    As far as other actual frameworks go, Svelte is often fairly popular with the crowd who don't like a lot of the React paradigms. No JSX, components that are basically HTML and as far as I know no useEffect as a crutch react does. No practical experience here myself, but it is what I encounter most.

    Having said all that, completely switching everything around can be quite the undertaking. Not just doing the work of converting all tools but also learning all new paradigms and ways of working. Next.js in itself might be you biggest headache and is for many people. I'd first look at switching to just React if I am being honest, simplify the tech stack you have now and then reorient.

    1. [4]
      delphi
      Link Parent
      I don't mind a strongly typed language, but you know, I'm not building missiles here. I don't need my compiler to yell at me because i forgot a "type: whatever" in a context where only one type...

      I don't mind a strongly typed language, but you know, I'm not building missiles here. I don't need my compiler to yell at me because i forgot a "type: whatever" in a context where only one type would ever be passed anyways. It just kind of cramps my style. I'm familiar with strongly typed languages. Hell, I started with C# back in the late 2000s. It just feels shoddy in TS, but I'm also not an engineer, so this might be a personal hangup.

      1. skybrian
        Link Parent
        I think that might be a matter of tweaking your linter or TypeScript settings to turn off warnings you don't care about? It's the sort of thing I'd ask a coding agent how to tweak. Regarding not...

        I think that might be a matter of tweaking your linter or TypeScript settings to turn off warnings you don't care about? It's the sort of thing I'd ask a coding agent how to tweak.

        Regarding not letting the agent do too much, I put something like this in my AGENTS.md:

        If the user asks a question in a prompt, answer the question and do not edit any files, to give the user a chance to adjust their request.

        Then I can ask all the questions I want without the agent being too much of an eager beaver, but I can also tell it to fix something specific.

        2 votes
      2. creesch
        Link Parent
        Fair enough. Well, the rest of my advice still applies. Basically what others also said, if you really want a framework Svelte is good choice. Web Components bring down the amount of building even...

        Fair enough. Well, the rest of my advice still applies. Basically what others also said, if you really want a framework Svelte is good choice. Web Components bring down the amount of building even further and doing it all vanilla is technically also possible.

        1 vote
      3. Eji1700
        (edited )
        Link Parent
        Okay so, speaking from experience, I will fight tooth and nail to only use strongly typed languages moving forward, and I say that as someone who held similar opinions. The main reason i'm going...

        I don't need my compiler to yell at me because i forgot a "type: whatever" in a context where only one type would ever be passed anyways.

        ....and give me insights into bad practices

        Okay so, speaking from experience, I will fight tooth and nail to only use strongly typed languages moving forward, and I say that as someone who held similar opinions.

        The main reason i'm going to double down on this for you especially is because you're supporting a tool that you intend for use by others. Maybe you're very good at ensuring things don't change, but chasing down a 'oops this typo meant this function threw out a string instead of an int which caused a bug 29 functions later' is something I will heavily desire to never do again.

        It's why I proselytize F# because it both has strong typing, but type inference where I don't have to bother to declare so long as the compiler can figure it out. It'll yell at me the moment it's unsure of a type (Hey asshole this could be int or string, tell me so i can tell what else you've done wrong), but doesn't waste my time with me declaring every single one.

        THAT SAID, I recognize that code that's written is often more important than code that could be. If you just can't gel with it, don't, and use whatever you like.

        I do strongly recommend keeping in the back of your mind if you do find yourself chasing down runtime bugs, that tools like typescript help you eliminate the majority of that problem. It all comes down to "i'd rather the compiler yell at me than spend an hour chasing runtime bugs", but oddly I get it from the other angle where "well typescript is better but its still not good enough, so why bother".

  7. skybrian
    (edited )
    Link
    Lately I’ve been using Hono libraries a fair bit for web stuff. They are pretty lightweight and they are portable across JavaScript environments, so if you want to build a web app using Deno or...

    Lately I’ve been using Hono libraries a fair bit for web stuff. They are pretty lightweight and they are portable across JavaScript environments, so if you want to build a web app using Deno or Cloudflare Workers instead of Node.js, you can. (I use them with Deno.)

    Hono itself is just a router: given an http request to a URL that matches a pattern, call the function you choose. I also like Hono JSX for generating html using functions in a .tsx file instead of insecurely concatenating html strings like a caveman. It takes the place of HTML templates and works both on the server and in a browser.

    Other libraries I inevitably end up using are Valibot for validating any JSON coming in from the outside (either config files or web requests) and Dax for running OS commands, so I can write all my scripts in TypeScript instead of bash and have them be fairly readable.

    For bundling client-side JavaScript, I was running the esbuild command directly from a build script, but now I invoke it using an npm package. This lets me write client-side code in TypeScript. I also use htmx to swap in parts of html pages and keep client-side JavaScript to a minimum.

  8. Kremor
    (edited )
    Link
    Mithril is a very close to metal, but still powerful framework. It's so close to metal that the only things you need to write an application is the bundle and regular JS. Or you could use JSX with...

    Mithril is a very close to metal, but still powerful framework. It's so close to metal that the only things you need to write an application is the bundle and regular JS. Or you could use JSX with the help of Webpack.

    I like to use it for small projects . IMO it only a more robust router that can handle nested components.

    However, your third point suggest you really don't want something like this.

    Edit: The way to get the best practices suggestions is with a linter like ESLint, but that involves messing more with the tooling.

  9. [2]
    post_below
    Link
    Why do you need a framework? HTML/CSS/JS can do all the things, but it sounds like you probably know that, so I'm just curious.

    Why do you need a framework? HTML/CSS/JS can do all the things, but it sounds like you probably know that, so I'm just curious.

    1. creesch
      Link Parent
      Not OP, but I think I can answer this a little bit. You can do everything in vanilla HTML/CSS/JS, but if you need to make a lot of UI and want to be able to reuse it you will end up writing some...

      Not OP, but I think I can answer this a little bit. You can do everything in vanilla HTML/CSS/JS, but if you need to make a lot of UI and want to be able to reuse it you will end up writing some sort of framework yourself either.
      For some use cases that works perfectly cromulent, in other cases it becomes complex to maintain fast. Ready made frameworks do help there and can be a valid choice.

      React is overused for sure and as it is the only tool many devs know they tend to try and nail everything down with it. But, there are plenty of other valid choices who, for certain use cases, make parts of web development a bunch easier than it would be without them.

  10. adutchman
    Link
    If you want native, there are now a few native directly GPU rendered Webassembly solutions you can use. Most native languages have one, I have hear most about Rust based ones, like egui. I have no...

    If you want native, there are now a few native directly GPU rendered Webassembly solutions you can use. Most native languages have one, I have hear most about Rust based ones, like egui. I have no personal experience with them but it is an option. Probably overkill and slower to load then a webframework, but hey, why not.

  11. secret_online
    Link
    This isn't a complete answer to everything, just another data point to add alongside the other discussions here. I was going to come in here to also suggest Svelte, but you'll almost certainly...

    This isn't a complete answer to everything, just another data point to add alongside the other discussions here.

    I also just don't get on with React's endless use effect garbage

    I was going to come in here to also suggest Svelte, but you'll almost certainly need some level of $effect given what some of the tools doing. Svelte's runes are a similar enough model, so if you're not enjoying (as stated elsewhere in this thread) that way of thinking then drop it.

    Otherwise, if you think you can get away with plain HTML and JS then why not try that for a couple of the tools and see how you go? I see some people have also suggested Web Components; they aren't my favourite so I personally would be starting without them and then add them in later on for things that need a more component-y model.

    and have little love for TypeScript

    I will admit it took me a lot of time and pain to understand how the Typescript compiler wanted to be fought against. It's now ingrained in my head, to the point that I now find its type system to be incredibly expressive. It was a long journey.

    If you find yourself still wanting a semi-typed experience with plain JS, most editors allow you to run the Typescript language server over JS files, and will pick up JSDoc comments like /** @type {number} */ as a way of selectively adding types to otherwise untyped code.

    I'm looking for fast build times, a smart-ish compiler that can ideally hot reload and give me insights into bad practices

    Vite is the compiler behind pretty much everything except Next.js at this point (well, and anything still using webpack). It'll give you your hot reload. It will, however, still minify and bundle everything, which I saw you comment on in other comments.

    As for insights into bad practices, this is usually covered off by a combination of compiler plugins (if you're using a framework) or ESLint plugins. I suppose it depends on what you mean by "bad practices" and what you want them to prevent you from doing.