Anything that is supposed to replace web UI frameworks needs to be able to perform client side routing. You can argue that the different colors shouldn't represent a push to history, but that's a criticism of the implementation, not the library.
Demos should cover the happy path really well. This opens modals that don't have an x to close them. If you click outside the modal, a common alternative way to close modals, it just picks a different color. The background fades to black so you can't see what you are picking. Then the back-stack grows large so you can't even back out of the demo normally. I'm not going to look at the code, even if it looks great this isn't an experience I'd ever want. There just too much basic stuff missing.
Maybe it's just a poor demo, are there better examples?
The sample repo is at least well-commented. I've taken the liberty of pasting some of the sample code here, sans comments, so we can see what the code style is like. My editorial take: no thanks. This looks less declarative than jQuery. If this is the alternative, then yeah, you still probably need React (or Vue/Svelte/Astro/whatever)
...yuck.
The hilarious part to me is that every single thing this does could be done in one line of an angular template with massively less typing and opportunity for error. just a:
Like, I know you want to create an element and blah blah...but if it takes your dev 4x longer to write it, why are you doing it? Ultimately, in the real world, all of this is devs trying to make bragging rights for reasons with no real commercial viability intended. As much as we like the idea of less JS frameworks and all that, there is a reason why every major company uses them - they allow people to make business-impacting changes and features faster.
What is really funny to me though is that it is even an awful example - you should never use a div as a button, it is an accessibility nightmare. That is telling.
> you should never use a div as a button, it is an accessibility nightmare
Eh, that's easily fixable with role="button" and tabindex="0". Oh, and adding a keyup handler so space and enter both click it. After that though, you have a perfectly good button. Well, minus any visual feedback that it's being clicked, but presumably you're doing some custom effect to go with the custom element...
So never say "never", but yeah, use a damn <button> whenever you have the choice. The roles are there to give you an escape hatch when you don't. And sometimes buttons are actually just button-shaped links, in which case you _really_ want to use an <a> tag, because those are heinous to imitate properly.
I have to say this is a bit disingenuous. You pulled the segmented button component which in a real-world environment would just be a part of a library. You should show the part where it gets used. From my experience, how this ends up playing out in a real-world environment is that these things end up getting boxed into higher-level UI libraries that turn all this stuff into quick function calls.
The vast majority of devs aren't (and shouldn't be) writing their own custom components.
> The vast majority of devs aren't (and shouldn't be) writing their own custom components.
Component frameworks are for doing exactly that, and they generally make it pretty easy, with no manual DOM manipulation required when state changes.
Rather than continue with my salty commentary, I suggest to anyone still reading to look at any other file in the example project and draw their own conclusions: https://github.com/squaresapp/rawjs-sample
The live sample of that is not very impressive. And even worse:
> These are the limitations you need to accept with this project structure:
> You have to be disciplined to only use dependencies that are published on jsdelivr (npm install programmers need to clean up their act)
That with a package.json which has dependencies @squaresapp/rawjs and rawter, both of which have no info on npmjs. Talk about "do as I say, not as I do". The idea that you might be able to handle things like i18n and a18y without dependencies screams "not invented here" syndrome.
my reading on the "limitations you need to accept with this project structure" is that those limitations are about this particular project structure, not on rawjs itself; i.e. my understanding was that you can also write a project using rawjs using normal ES modules and plain JS (as mentioned briefly in the main rawjs github repo readme).
that said, I do agree that pointing to a highly opinionated example project is a bit confusing
My point is that, this being written by the authors of Rawjs, who unironically proselytize that "npm install programmers need to clean up their act" while providing a project which would require you to `npm install` dependencies is telling.
The problem with React is nobody actually learns how to code in React properly and formally. They just wing it by copying what else they see around them.
But the point of incremental code is that it completely changes how you think about data flow and changes. Which they never do.
TLDR: topologically sort your code by change frequency of the data.
That reminds me of volatility based composition presented in Righting Software[0].
I'm curious if you have anything to reference for what you are considering "proper and formal" react? Not sure if you're pointing toward the flux architecture with redux or something else...
honestly, I just never found a need to do react an even more counterintuitive way, than the counterintuitive way that I'm fine with
there were never performance problems just because we used a ton of useEffects
there were never bounced users because hooks were not the most optimal
we did static landing pages without dynamic data that passed all the pagerank stuff decently, and then people came into the app and were more patient to see their unique account data
squaresapp, not to be confused with Square App, Cash App or Block Inc, despite the propensity for convoluted design patterns that aim to become crucial open source libraries
There's a typographical error on the home page ("It's API design is complete and there are no known bugs" should use "Its"). I would've submitted a PR, but the link to the website repository actually links to a static site generator, not the website itself.
I don't have to admit anything, I think it's a complete waste of time until you're shipping something with so much value that juicing your conversion rate by 1% more is a meaningful improvement. And I don't care if the comment is tongue-in-cheek or not, even ironically this holier-than-thou style of argumentation grates like you wouldn't believe.
Help me turn my ideas into reality faster. Then you can be as snarky as you like. It's the only reason anyone tolerates DHH or anyone like him.
I'm gonna be honest, you need someone to proofread your website. I spotted two typos on a quick scroll-through, both of which could probably be caught by copy-pasting the thing into Word.
How does this compare to SolidJS which uses JSX and performs insanely close to vanilla JS already? If I really want to shrink my front-end I might as well, just go for Solid or Preact.
That's pretty great! For me, the great tragedy of "modern" programming is that we took the enormous potential of scripting languages and turned them back into C++. Whereas I started with C++ and have done everything I can to get away from it.
For example, everything today is built on promise chains, which are borrowed from monads in functional programming, which someone came up with (partially) to let immutable synchronous blocking code be written in mutable imperative style. But where FP tries to avoid monads and stay pure, promises are now considered so fundamental that we have async/await on nearly every function. Delivering such a degree of nondeterminism that we've effectively resurrected goto.
If I ever design a language, all variables will already be proxies so that everything can be observed. Just like it will use pass-by-value instead of references, the same way that php copies arrays via copy-on-write internally. And have channels between fork/join green threads with full memory isolation provided by the runtime, to provide a declarative style of multithreading that looks like vanilla higher-order functions. There are at least a dozen alternative approaches like that which reduce code complexity by orders of magnitude, that never got widely adopted in recent decades. So we're all manually managing exceptional behavior rather that avoiding it in the first place.
ArrowJS shows how simple programming could be if we catered to developers instead of some abstract notion of lightweight purity that results in GHz computers struggling to run unmaintainable GUIs that ran fine with less code on 33 MHz computers in the 1980s. ArrowJS <-> FP/spreadsheet, "modern" JS <-> C++/assembly language.
> But where FP tries to avoid monads and stay pure
Does not compute, monads are a construction you see pretty much only in functional programming. Monads are the tool Haskell uses to model effects and generate them from pure computations. They're not magic, they're nothing more than a pairing of a "map" and a "join" function (or "pure" and "bind" if you prefer that angle). Bottom line, monads are as pure as anything else, it's just the behind-the-scenes interpreter for the IO actions produced by the "main" function that isn't (edit: I suppose ST also counts as hidden magic)
Other effect systems not based on monads have recently been catching on, such as Effect for TS, or language features like Abilities in Unison. Right now I get "observable-everything" by using computeds in Vue as much as possible and keeping raw refs private (i.e. not exported). But ultimately, something has to set the refs, and there's still no easy way to account for that mutation behavior in the type system.
What I meant was that it's a small library with a relatively small surface area for bugs, and it's been under pressure from a few different projects for some time now, and it's been quite a while since we have discovered any behaviour I would consider to be buggy.
I'm sorry you took this as a "brag". This wasn't the intention.
Ah yes, "the frontend world reinvents everything".
VanillaJS has been a thing for a long time, and now these kids can come and think they can just rename the same idea and we won't catch them?! Pff, stealing framework ideas like that...
Besides that, all the code examples are not even written in JavaScript, why is the project called RawJS? Clearly should be called RawTS instead.
I respect the intention here. I'm a big fan of "DOM as State", myself. I'm more partial to modularity and encapsulation using custom elements, rather than runtime js objects that inject well-known elements, but I can't say one is better than the other. Just my current naive preference.
> RawJS is a better way to call document.createElement().
React is a way to reduce calls of document.createElement using virtual DOM, ie using React.createElement. It’s JSX which is supposed to be a better way to call document/React.createElement. So what exactly does this compete with?
The main thing RawJS brings is ergonomics when creating element hierarchies of plain HTMLElement instances. I don't see JSX as something that does this very well. A lot of people don't like JSX, because its not JavaScript. There are other libraries that are better document.createElement() that work somewhat similar. RawJS isn't new in this regard, I just believe that it's better executed than the others.
My biggest beef with JSX is that what I might call the "most natural way" and certainly the "most concise way" of writing certain somewhat-complex structures in JSX often ends up being a huge mess. E.g. an element is some JSX elements with some code embedded, and the embedded code is returning some other JSX elements that have yet more code embedded in them, and the easiest refactoring to make the whole thing less gross is extracting functions that don't really deserve a name of their own.
134 comments
[ 2.8 ms ] story [ 219 ms ] threadNo I'm not going to go digging in a repo without so much as a top-level overview of the approach
https://rawjssample.pages.dev/
I immediately see that it ~hijacks my back button~ fills my back-stack such that I can't use the back button normally. Doesn't look promising.
I guess rendering the UI as a function of state still has its merits.
I absolutely hate when pages hijack the back button, but this ain’t it.
It’s still a bad experience, though.
Maybe it's just a poor demo, are there better examples?
<div style="display:inline-block...." [style]="{ 'backgroundColor: hsl(215, 100%, 50%)' : active }" (click)="active = !active">
Like, I know you want to create an element and blah blah...but if it takes your dev 4x longer to write it, why are you doing it? Ultimately, in the real world, all of this is devs trying to make bragging rights for reasons with no real commercial viability intended. As much as we like the idea of less JS frameworks and all that, there is a reason why every major company uses them - they allow people to make business-impacting changes and features faster.
What is really funny to me though is that it is even an awful example - you should never use a div as a button, it is an accessibility nightmare. That is telling.
Eh, that's easily fixable with role="button" and tabindex="0". Oh, and adding a keyup handler so space and enter both click it. After that though, you have a perfectly good button. Well, minus any visual feedback that it's being clicked, but presumably you're doing some custom effect to go with the custom element...
So never say "never", but yeah, use a damn <button> whenever you have the choice. The roles are there to give you an escape hatch when you don't. And sometimes buttons are actually just button-shaped links, in which case you _really_ want to use an <a> tag, because those are heinous to imitate properly.
I have to say this is a bit disingenuous. You pulled the segmented button component which in a real-world environment would just be a part of a library. You should show the part where it gets used. From my experience, how this ends up playing out in a real-world environment is that these things end up getting boxed into higher-level UI libraries that turn all this stuff into quick function calls.
The vast majority of devs aren't (and shouldn't be) writing their own custom components.
Component frameworks are for doing exactly that, and they generally make it pretty easy, with no manual DOM manipulation required when state changes.
Rather than continue with my salty commentary, I suggest to anyone still reading to look at any other file in the example project and draw their own conclusions: https://github.com/squaresapp/rawjs-sample
The live sample of that is not very impressive. And even worse:
> These are the limitations you need to accept with this project structure:
> You have to be disciplined to only use dependencies that are published on jsdelivr (npm install programmers need to clean up their act)
That with a package.json which has dependencies @squaresapp/rawjs and rawter, both of which have no info on npmjs. Talk about "do as I say, not as I do". The idea that you might be able to handle things like i18n and a18y without dependencies screams "not invented here" syndrome.
that said, I do agree that pointing to a highly opinionated example project is a bit confusing
There's a demo app here: https://github.com/squaresapp/rawjs-sample
(Does that help you? Or do you think it still needs more?)
I'll get on updating the readme shortly.
https://dev.to/paulgordon/after-using-rawjs-im-never-touchin...
Both links helped to explain, the landing page is indeed not very good.
I wish I could upvote your comment a thousand times, after spending literally the whole day so far trying to pour water on a burning building.
https://github.com/madrobby/vapor.js
I didn't fork anything.
And your link just pr0n'd me in a coffee shop.
Thank you.
But the point of incremental code is that it completely changes how you think about data flow and changes. Which they never do.
TLDR: topologically sort your code by change frequency of the data.
I'm curious if you have anything to reference for what you are considering "proper and formal" react? Not sure if you're pointing toward the flux architecture with redux or something else...
[0] https://rightingsoftware.org/
there were never performance problems just because we used a ton of useEffects
there were never bounced users because hooks were not the most optimal
we did static landing pages without dynamic data that passed all the pagerank stuff decently, and then people came into the app and were more patient to see their unique account data
rinse and repeat
“last years framework” should be “last year’s framework”
“How long with it take to find and fix bugs as our app grows?” should be “How long will it take to find and fix bugs as our app grows?”
> You have to be disciplined to only use dependencies that are published on jsdelivr (npm install programmers need to clean up their act)
Yeah, no thanks, I'm sticking with my "unclean" ways.
You have to admit at least admit that minimizing dependencies is an admirable goal (despite my tougue-in-cheek comments in the readmes I write)
Help me turn my ideas into reality faster. Then you can be as snarky as you like. It's the only reason anyone tolerates DHH or anyone like him.
> No learning curve beyond knowing how to work the DOM.
Except, you know, all the weird and non-weird stuff that they have that may or may not work as you expect it to:
> No weird or unpredictable framework "magic".Except, you know, all of the above
> No performance overhead.
Remains to be seen
> No virtual DOM.
The weird obsession with "no virtual DOM" is weird because the fastest libs out there use virtual DOM. But zealots be zealoting
> Works in Node.js for server-side HTML generation (with the help of HappyDOM).
So, requires full DOM implementation to be used on the server. Most libraries/frameworks don't need that.
Honestly this whole thing blew up so fast I wasn't expecting any of this. The home page for the website isn't even done yet.
Like what https://youmightnotneedjquery.com did - comparisons between the popular library and the replacement.
Thanks for +1'ing this idea. I like what that website did and I might need to build something similar.
I think it's probably more fair to say that SolidJS is "insanely close" to React rather than RawJS.
For example, everything today is built on promise chains, which are borrowed from monads in functional programming, which someone came up with (partially) to let immutable synchronous blocking code be written in mutable imperative style. But where FP tries to avoid monads and stay pure, promises are now considered so fundamental that we have async/await on nearly every function. Delivering such a degree of nondeterminism that we've effectively resurrected goto.
If I ever design a language, all variables will already be proxies so that everything can be observed. Just like it will use pass-by-value instead of references, the same way that php copies arrays via copy-on-write internally. And have channels between fork/join green threads with full memory isolation provided by the runtime, to provide a declarative style of multithreading that looks like vanilla higher-order functions. There are at least a dozen alternative approaches like that which reduce code complexity by orders of magnitude, that never got widely adopted in recent decades. So we're all manually managing exceptional behavior rather that avoiding it in the first place.
ArrowJS shows how simple programming could be if we catered to developers instead of some abstract notion of lightweight purity that results in GHz computers struggling to run unmaintainable GUIs that ran fine with less code on 33 MHz computers in the 1980s. ArrowJS <-> FP/spreadsheet, "modern" JS <-> C++/assembly language.
Does not compute, monads are a construction you see pretty much only in functional programming. Monads are the tool Haskell uses to model effects and generate them from pure computations. They're not magic, they're nothing more than a pairing of a "map" and a "join" function (or "pure" and "bind" if you prefer that angle). Bottom line, monads are as pure as anything else, it's just the behind-the-scenes interpreter for the IO actions produced by the "main" function that isn't (edit: I suppose ST also counts as hidden magic)
Other effect systems not based on monads have recently been catching on, such as Effect for TS, or language features like Abilities in Unison. Right now I get "observable-everything" by using computeds in Vue as much as possible and keeping raw refs private (i.e. not exported). But ultimately, something has to set the refs, and there's still no easy way to account for that mutation behavior in the type system.
It's like someone peddling a medication and saying, "No known side effects."
What I meant was that it's a small library with a relatively small surface area for bugs, and it's been under pressure from a few different projects for some time now, and it's been quite a while since we have discovered any behaviour I would consider to be buggy.
I'm sorry you took this as a "brag". This wasn't the intention.
VanillaJS has been a thing for a long time, and now these kids can come and think they can just rename the same idea and we won't catch them?! Pff, stealing framework ideas like that...
Besides that, all the code examples are not even written in JavaScript, why is the project called RawJS? Clearly should be called RawTS instead.
React is a way to reduce calls of document.createElement using virtual DOM, ie using React.createElement. It’s JSX which is supposed to be a better way to call document/React.createElement. So what exactly does this compete with?
The main thing RawJS brings is ergonomics when creating element hierarchies of plain HTMLElement instances. I don't see JSX as something that does this very well. A lot of people don't like JSX, because its not JavaScript. There are other libraries that are better document.createElement() that work somewhat similar. RawJS isn't new in this regard, I just believe that it's better executed than the others.