The benefits, I can see.
JS frameworks move really quickly, and when we're working on a large, long-term project, it sucks when big breaking changes are introduced after only a couple of years. Sticking to slow-moving web standards (which are quite mature by now) increases the longevity of a project.
And the stability also means that more time is spent on delivering features, rather than on fixing compatibility issues.
There is also the benefit of independence. The project's success is not tied to the framework's success. And it also makes the project more secure, from supply chain attacks and such.
Because there is no "abstraction layer" of a framework, you also have greater control over your project, and can make performance optimizations at a lower level.
I feel not using a framework can even make us a better developer. Because we know more of what's going on.
There are benefits to using frameworks too, I'm not here to challenge that.But this alternative of using none... it seems rarely talked about. I want to learn more about building large (preferably web-based) software projects with few dependencies.
Do you have any suggestions on how to learn more about it? Are there any open source projects you know which are built this way? It needs to be large, complex, app-like, and browser based. I'm more interested in the frontend side.
Thank you!
React is a lot more stable than I think you're giving it credit for.
> And the stability also means that more time is spent on delivering features
Frameworks/libs also exist to save you time, thus letting you spend more time on delivering features. And fwiw, the obsidian team seems to agree in principle. Your link goes to a forum post of some kind, in which one may find a link to obsidian's third party deps: https://help.obsidian.md/credits#Third+party+acknowledgement...
These do not include React, but do include:
- i18next - lezer - moment.js
Plus a bunch of others. Why didn't obsidian write their own date lib and chose to use moment.js? Because it saved them time, despite the fact that moment.js does make changes, and many people are moving on from it in any case.
The idea that not using a frontend framework will let you focus on delivering features seems reductive, and the obsidian anecdote doesn't support the idea anyway.
Whatever you're building, it's never a bad idea to deeply understand the tradeoffs that using a library will bring. Obsidian probably couldn't accept the downsides of React due to them needing a bunch of custom renderers for content, which React makes harder. But that is likely a rare constraint for apps in general.
Generally speaking, libs like react exist to save you time and help you focus on delivering features.
That's until you have to use it in a real project, for a long time the go to solution was the facebook maintained CRA which is now deprecated. I have spent a lot more time than I'd like to admit migrating webpack versions when it was considered best practises to use class component with decorator but decorator never was standardised in the browser and was never able to get a clean project where running npm install would not give scary warning our project had high vulnerability that was dependencies of dependencies in CRA to the point that it got me wondered that even if the creator of react facebook can't get their shit together, the whole ecosystem is doomed. I have been outside the ecosystem for a year and looking at the shit show that is nextjs it seems things are even worse than before.
I think the only shaky moving part for us right now is styled components being left behind due to the RSC changes, but there's both mostly source compatible rewrites as well as perhaps even better alternatives (vanilla-extract).
> running npm install would not give you a dozen high vulnerability package
Yes, this is a serious problem, but mostly an npm messaging problem: https://overreacted.io/npm-audit-broken-by-design/
Not only did they deprecate it, they refused to acknowledge it's existence in the new docs which is wild to me.
It may have changed in the last year, but if you searched for "CRA", it would get 0 results. Again, mind-blowing considering it was the recommended way to build apps with React.
Instead, it was replaced with a section driving you towards adopting Next. Which then had to be whittled away at and updated to include other options all the while the React team acted hostile to any criticism of it. You either used Next or you were shit out of luck.
> I have been outside the ecosystem for a year and looking at the shit show that is nextjs it seems things are even worse than before.
My thoughts about CRA aside, you don't have to use the frameworks (I still don't). And if you remove Next from the equation, things are actually pretty cool. Suspense is cool, and you'll have to rip React Query from my cold, dead hands.
A lot of the HN zeitgegist would have you believe React is the opposite, sadly.
But React core APIs remain relatively stable, I've been using React the same way for many years at this point, and you can ignore the parts you don't like, like I'm ignoring hooks and haven't found a single use case where I needed them.
Turning it around, what exactly are you unable to do without useState/useEffects?
Usually that array is mapped elsewhere and those child components might also re render if the array is recalculated.
useEffects are when I need to call something outside of react, or when the page gets mounted or I need to call a function when something changes.
I'm still fairly new to this, the above examples may scream bad architecture to those more experienced, all criticisms welcome :)
Edit: for a more practical example, you don't need to go down the web components rabbithole just for native reactive components, MutationObserver can watch for your template fragments entering and exiting the DOM and run your init/destruct routines on them. Now you can just push HTML back from the server with fetch or xmlhttprequest or whatever, and as soon as your component's HTML enters the DOM it will be "hydrated" by your init routine via MutationObserver. Honestly, add some event signaling and XHR and you're further along to a smooth SPA-like experience than you might think.
https://developer.mozilla.org/en-US/docs/Web/API
The frameworky code is under 100 lines of code, heavily inspired by what I think is a good idea from React: "components are pure function", the simplest example of the about page beeing visible here: https://github.com/mickael-kerjean/filestash/blob/master/pub...
Since the whole project was migrated over from React, I was able to improve performance to a degree that would have been impossible using React, it's a breadth of fresh air to open the performance and memory tab and to be able to optimise things from there to get 60FPS no matter what whilst preventing massive ram usage because those frameworks runs all sort of code that is out of your control. Also because there is no build system, I was able to introduce plugins to be able to patch frontend code via patch applied dynamically by the server to create features like the recall button to recall data stored on glacier when using S3, dynamic patching of the icons to apply branding and many other things that I would have had to fork entirely before
Anyway, I hope our industry would go more often the vanilla route, es6 is ready for prime time and solve all the pain point we had while internet explorer was still a thing
I wouldn't use JQuery for a new project, as you can do almost everything it does with straight DOM manipulation. But there are still some strategic vanilla JS/TS packages that come in handy, e.g. clipboard, mousetrap, file-saver, split.js.
Web Components with Lit is kinda fun, though you'll have to deal with DOM shadow roots or disable them.
I would challenge that using a framework leads to less security. In vanilla JS you've got to use something like dompurify religiously to avoid XSS bugs, and you're tempted by the shiny candy-like innerHTML attribute.
Could need some js library and that is a maybe.
In general:
If is like a eCommerce site, blog, wikipedia, forum? Not need
If is like a Game, Paint app, form builder? Need.
And how you learn it? Not use a framework, and try to stay with things more minimal, like tailwindcss.
> I had a mind-blown-moment when I learnt that Obsidian was built without any frontend JS framework.
The comment you’ve linked to is wrong. Obsidian uses the Electron framework for its “front-end” framework.
In fact, it was even affected by the recent “Tahoe” Electron bug.
https://en.wikipedia.org/wiki/Obsidian_(software)#Availabili...
I'm working with JS for already 25 years. Tried all of the frameworks, and continue on doing it. And every time I try something new, the refactoring flow turns most of them into NextJS (if it's very UI rich or customer facing or something very web-oriented), or Vite+React+Tailwind (client) and Hono (backend) if it's more of a tinker toy needing more custom solutions.
The boilerplate with NextJS is cleanest (compared to all the other frameworks) and API is the most straightforward one, and you can safely ignore the vendor lock in. Its just a pretext to hate on NextJS. They all have some kind of a "vendor" lock in. Be it a vendor-or-a-specific-approach-or-whatever-lock-in.
And Vite+React+Hono — simplest to set up for quick experiments, and very powerful with minimal boilerplate. Will probably create a starter for this one, as I have been using this stack quite a lot lately.
EDIT:
You can pretend vanilla JS is all you need, but then your app grows, then you suddenly need types, and state, and more events and their handlers, and SSR or something else. Thus React has been the most stable bet for quite a while for me now.
But for me Lit is too OOP. It feels like Angular. And that all in turn feels like Java. It's just so heavy and constrained (not saying it's a bad thing though). Too much boilerplate for me.
The whole paradigm is different and does not match my preferences. And while subjective, I do believe React with TS, Tailwind, zod, react-query and zustand is the best stack delivering the best balance of boilerplate and code-delivery and easy of use and entry level and dx.
And, when a new developer comes in who knows React, they can ramp up fast and even if they don’t, there are plenty of resources instead of asking Bob how something works - if Bob is even still working there.
2. router https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern...
The rest should be code organization, not even a build tool.
Can check this example https://github.com/radio4000/components
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid...
You basically have the same capability you have in python or other ecosystems if you can be bothered to attempt what the OP suggests. Determining an appropriate way to organize your code is actually a really hard problem to solve if you've been leaning on 3rd parties to solve it for you. It's definitely a skill worth developing. Once you have it you will begin to dislike the organizational suggestions of others because they'll never fit your problem as well as a hand tuned strategy.
With the framework, you have structure. It might not be the best structure to use, but you have one. React lasted really long and is still works today.
Going without framework works if:
- you have a really small project
- you are so advanced developer or have specific use-case that using a framework creates more burden than time saving
- you are creating something so valuable that reimplementing it yourself is worth it
I think that regular website will bleed via maintenance costs in the long-run if you don't use a framework. Instead of paved road with framework migration you would be fixing and debugging bugs in your framework/codebase.
So yeah, JavaScript is nicer nowadays, and browser apis are more consistent than they were then.
In the past we used http://microjs.com/ and similar to find small libs to work with when we threw together marketing websites, not sure how maintained that list is nowadays but the idea is that you can make websites like lego, sometimes you don't need a whole box of Eiffel tower to make a little tree.
If your functionality is well thought out and not super complicated, don't have 10s or 100s of devs on the same project then working without a well known framework could make sense, otherwise there can be steeper learning curve when onboarding new devs, scope creep / bloat, etc that will likely cause issues down the road.
To learn about this you could try to replicate for example the mentioned Obsidian by yourself and research solutions for all the issues you run into, e.g. minimal routing, custom view renders, reactivity, performance, etc.
From there one big question is if everything needs to be dynamic or not. You often have menus and navigation that you don't need a framework for and that even something like jQuery is well suited for. On the other hand a framework would probably slow things down for the writing experience in Obsidian, which is the main draw for me to use Obsidian. Once the writing module is written from scratch, it won't seem like such a big lift to also do all the navigation and controls by hand.
That doesn't mean this is the right way for everyone. A lot of times the speed to releasing new features is more important, while the handicraft of the UI/UX is less important and in those cases using a framework is absolutely the right choice.
My priority is code clarity … so while it is not yet tested at scale, https://harcstack.org is aimed to do this on the server side (disclosure - I am the author)
Another determinant is the server side language / approach to templating you choose. With HTMX Python, Rust, Go are all fair game. I’m leading with Raku due to its web framework and ORM.
As you can see most functionality can be implemented in around 100 lines of code. The advantage is that you can build up functions just for your needs. These functions are super easy to understand because they don't have any dependencies and the whole implementation fits on one or two screens. There is very little indirection.
Another advantage is that most code is actually doing something concrete. With frameworks you often have a lot of code that is just pointing to other code, or is boiler plate code to set something up. Not having any boilerplate code also makes stepping through the debugger a lot easier.
The project has no build step in development which also makes debugging easier. It does have a build step in production.
Most people use frameworks to give the code structure. When writing vanillajs you need to bring the structure of the code yourself. This does take some getting used to but I think it is an essential skill for good programmers to have. On top of that many frameworks push you into structure that does not make much sense in my mind (for example seperating the view and the controller if those are always gonna change together).
So to conclude: My advice for building without frameworks is, just start building. Problems will come up and you can tackle those as you go. Do you think you need to use events in your application? A simple implementation is 10 lines of code and can be written in 10 minutes. If it takes me 1 hour to not use a library I will spend that 1 hour. Most frameworks will not bring that much value. Easy things become short and hard things will become impossible. I think most value is actually brought by the language and the basic api's (DOM, CSS, etc)
Going without a premade framework means it's a fight between you and the pile of complexity. Code will tend to become ugly and slow and hard to change the more you add, so you'll have to go into a cycle that's more like add-refactor-add-refactor. Forward then sideways, forwards then sideways. Do this long enough and you'll will end up with your own libraries and frameworks to manage the complexity.
If that's not enough, Lit enhances it a bit such that either LitElement and/or litHtml can accommodate whichever style you want: https://lit.dev/
There is no reason you cannot implement MVVC/MVC or whatever else on JS for reactivity, it’s just that react et al just abstracts that away for you.
You are effectively choosing some method of implementing and abstracting the observer pattern and handling cleanup since you can easily get into a situation where you have dangling references to objects that are never cleaned up (memory leaks) or pretty nasty GC hangs which can make the UI feel bad to use.
However, you'll inevitably end up with your own after some time. Even if you try your best to stay away from it, you'll need abstractions for:
But you can have minimal layers for that.- Routing
- State
- Rendering
A lot of frameworks try to cover all three of these, and that's where you tend to see a lot of feature churn. I would recommend picking a rendering library (like react) and writing your own routing and state library, even if it's just a light abstraction on top of an existing library. This will make it way easier to upgrade or move in the future, as you will control the API.
Even pre-web. I remember, how quickly I could create Delphi desktop app with drag & drop UI builder more than 2 decades ago. If we speak about generic ERP, you could make dozens of screens in a day.
You just split your app to layers.
That might be for example:
1. Just UI;
2. UI logic (validations, preloading selects...);
3. Transformation of data between data model and UI model
All of the things above lived on users' computers.
All of the things below were on servers.
1. API gateway (terrible things like SOAP, XML-RPC or completely proprietary formats);
2. Business logic;
3. Database
* greater flexibility
* faster execution, My current application produces a large single page application that fully renders visually and executes state restoration in about 105ms localhost or under 200ms across a network
* faster maintenance, I can do massive refactors that touch most files in the application in about 2 hours thanks to thorough use of TypeScript interface definitions
---
Here is how I do it:
1. Just start building your application. Realize that for any significant application the front end UI is probably only about 20% of the application code, or less.
2. Start the UI by writing static HTML. Reserve JavaScript, in the browser, only for handling events and state restoration and execute state restoration only on page load.
3. I prefer to use WebSockets over HTTP as much as possible for absolutely everything I can get away with. WebSockets are full-duplex, where HTTP is not, and have far less overhead. That will substantially reduce the complexity around messaging in and out of the web browser.
4. Everything after that is just execution, planning, refactoring, and feature addition.
5. You can do absolutely all of it in TypeScript now without any compile step. Node.js now executes TypeScript directly, but the browser does not. To solve for the web browser just include the browser code into your Node application using ES6 module import. If the imported code is a function you can convert it directly into a string for transport, and otherwise use JSON.stringify for objects/arrays.
You don't do framework nonsense. That is all there is to it.
For most people writing JavaScript for employment it is absolutely impossible to imagine any universe where a couple of lines of code could be written without something that looks like a framework. That is not a limitation of the language, but rather a limitation of the given developer's imagination. The problem is thus a person problem and not a technology problem.
I do not use innerHTML because that is string parsing, and one of my critical performance steps is to avoid parsing from strings, except JSON.parse when needed.
If you want to ship an MVP next week and you spend 6 days setting up your env, you've already failed. If you can get a framework with at least 80% of the features you need, suddenly you have 6.5 days left to build the product
JQuery was never considered "necessary". It's just a much prettier wrapper around the native dom apis. Arguing against adopting a more readable api (and codebase), is gonna be a tough sell.
Huh? Are you implying the code will never get read by another developer or possibly modified? Are you arguing there is no reason to make your code more readable?
> These things are clear when an outside party can observe your developer habits and inform you where your priorities are as opposed to what you state they are.
What?
This is what I used for fontofweb.com's snipper chrome extension.
I’ve switched to web components with lit/html driven by AI.
Could not be happier.
When I write vanilla js I don't have a seperate file called framework.js. There is very little code needed to manage state. Almost all functions in my codebase are doing concrete things.
For platforms, just go native - it's easier than ever with LLM assistance.
My advice is to go and learn a proper architecture (MVVM is a great fit in my opinion for MOST things) and then figure out how to implement that with something you enjoy using. My only bit of advice here is that the closer you stick to the underlying web platform the better off you’re going to be so if you want a concrete recommendation something like Lit here gives you all the primitives you need along with great performance, documentation and developer experience.
JSX encourages sloppy HTML. Props are are overly verbose. Hooks are a nightmare. Contexts are gross. Portals are a stupid hack for the very, very stupid reason of making it nearly impossible for parent elements to read anything about their children. The whole "props down, events up" paradigm is woefully naive and half of React exists to get around it because of that.
So yeah, if all you know is react, you've already been on the hard path.
Incidentally, many of the issues people have with React are attributable to this mistake: knowing what a framework is supposed to be, one might expect React to take care of everything, and when it turns out you’re on your own and using React in a complex project means (whether consciously or not) coming up with a homegrown React-based framework of your own, or using a collection of disparate extras that fill in the blanks (like CRA), by then it’s already a hairy mess of a codebase in a desperate need of refactoring.
React lacks most of framework traits. The library does reactive rendering and contains a somewhat restricted set of low-level primitives around it. Even its DOM integration is handled by a separate, optional library (ReactDOM).
Someone could complain it feels like with Vercel the direction for React is to become closer to a framework (now with RSC and JSX runtime being part of React), but still it is nowhere near a state where the phrase “a framework like React” rings true—and, in fact, Vercel’s interests are aligned with keeping React more of a library than a framework so that more people use Next and are upsold Vercel’s hosting, and Next is in fact a framework in the full sense of the word, comparable to Django or Rails.
Similarly, Vue, Angular, Marko, Astro, Qwik, etc. are frameworks. They provide you with project structure, scaffolding, and a lot of batteries. The fact that many of them are, in fact, using React under the hood speaks volumes.
On the first page "Quickstart" all code blocks contain code that contain JSX and call you. They do not even show the part where you need to call render. Copying this code into your codebase will not do anything.
On that same page they also introduce state management with hooks.
On the installation page npm installing react is not mentioned. They suggest using create react app.
Sure you can theoratically use react as a library but I've never seen it and from the website it seems like usage as a library is not the inteded way to use react.
The first sentence "The library for web and native user interfaces" is the only thing pointing to react being able to be used as a library. The rest of it looks like a framework to me.