Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
RawJS is a better way to call document.createElement() (squaresapp.org)
43 points by synergy20 on Jan 3, 2024 | hide | past | favorite | 130 comments


You know what's an even easier way to call "document.createElement"?

    $.append
Sure, there's a reason why people moved away from JQuery, but I'm not convinced that a half dozen lines of boilerplate per element is a good solution either.

The example almost reads like a parody, here's a half dozen lines to write what you could write in one line of raw html:

    <div onClick="alert('Hello World')" style="{padding:100px;background:red}"></div>

But I guess I just don't get it, I don't understand the use case where you want to manipulate the DOM but don't want to do so directly through the DOM API. You also don't want the convenience of JQuery, nor want the composibility of react or similar components.

Somehow they think they've found a worthwhile middle ground between just calling the DOM API and using Jquery. I don't agree that targetting that is a worthwhile endeavour. It's almost avoiding the DOM API for the sake of it, and tying yourself to a library without many benefits.

p.s. Having had the concept of writing "Vanilla JS" hijacked by a library author, now writing "Raw JS" is too.

Any day now we can maybe expect a new "Libraryless" framework.


RawJS library author here.

$.append appends, in the name ".append".

Though

The point of RawJS is to help with element constructions. jQuery was a god-send back in the day for manipulation and querying (before we had document.querySelector()) but constructions of hierarchies were never really its thing.

There are other libraries that work like RawJS to make complex DOM constructions with function calls. I just don't think the ergonomics of them were as well thought-out as it is in RawJS.


I think the main reason why small things like rawJS are appealing is that a lot of devs got directly or indirectly forced into learning a framework and then got themselves burned one way or another while using it. We then developed a shared fantasy: "What if the native browser API was good enough so that we don't have to learn any fluff (frameworks, build tools, libs) to be productive? After all, other languages don't have this framework bloat problem. Let's just use this minimal lib instead."

But this is just a fantasy. Element constructions are not the problem. Updating the state and DOM is the issue. We don't do stuff like rawJS or jQuery for bigger apps because they are too low-level and they don't scale well. What we need is to operate at a higher level, not get rid of almost all of the abstractions entirely like rawJS. Have a look at https://github.com/squaresapp/rawjs-sample/blob/35939695dba6.... This is the kind of code that is meaningless to my app. It's just DOM housekeeping. The example app is small enough so that there isn't much of it: this is the only interactive bit of your demo app. But the bigger the app, the more housekeeping like this you need. Try to showcase a bigger demo app with a lot of interaction.

Now, there are specific cases where I don't want/need a framework. If I want better performance, the framework can become a hindrance (this is generally the case - when you want performance, you need to look at the lower levels). If the app is tiny, frameworks are just fluff. But for the overwhelming majority of cases (apps that are not tiny and don't need amazing performance):

As a web dev, I want to assign some object to some reference and then my app to be updated based on my state. When some event happens, I want to update some of the app state. That's it! I don't want to mix my business logic with DOM fluff. I don't need another piece of code to worry about. I want some dependency to do that for me. Is it going to happen via virtual DOM or change detection or something else? Who knows.


To me the usescase feels like: I am using Hotwire/htmx. When I need more complex behavior, instead of using stimulus/apline/hyperscript, you can make custom webcomponents which use rawjs for the rendering.


> Sure, there's a reason why people moved away from jQuery

And after all these years, I can’t see a technical one. Especially if the answer is React.


The technical reason is that jQuery increases the size of your page by a lot without really adding much benefit.


> p.s. Having had the concept of writing "Vanilla JS" hijacked by a library author

Woosh?

You've obviously missed the joke. VanillaJS is not a real framework or library - try to download it, its 0 bytes. The whole intent is that you are using built-in JS features, aka Vanilla Javascript.


This showed up in my google news feed last night and I immediately searched to see if it was posted to HN, which it had not. So it's interesting to see this reach the front page this morning.

There's a youtube video linked from the github that goes into some explanation into the "why", e.g. we should minimize deps, use standards instead of framework silos, avoid frameworks which have monopoly on dom, easier debugging, onboarding, etc. I agree with most of that in principle, I just don't know if this is the solution.

When we had larger component frameworks built on vanilla JS, like ExtJS, they had their own problems, e.g. framework code which alternated reading styles and updating styles from DOM causing reflow, or DOM listeners that were not properly cleaned up. But with those older frameworks, when something went wrong, it was trivial to debug the entire codebase including the framework, because it was all basic JS.

These days with something declarative like Vue, there's far less need to reach for a debugger and usually stuff just works, but when something does go wrong it's often a bit perplexing and you feel you're stuck because everything is happening in the framework black box. I still like Vue, but I must admit even if it's one of the simpler frameworks, there's a bit of an onboarding issue. I still see our devs making mistakes like doing side effects in computed variables, or modifying props state in children, even after a few years of experience.


This take is really on-point.

I'd like to add that from my experience, the more "out there" and the less "rudimentary" your UI and general app is, the more the frameworks really get in your way.


Apparently the author has it out for import statements.

"No import dumpster at the top of each file. Forget imports even existed. Just access whatever you want, wherever you want. TypeScript knows where to find it."

This is a bizarre preference. Is there some reason the JS community has turned against explicitly listing what libraries are used by a module?


I definitely would not say the authors’ opinions are representative of the JS community.


This is the third or fourth time I see today in HN of someone treating someone's personal project or opinion as "the direction the community is moving".

If every new toy framework is treated like this, it's no wonder people feel overwhelmed by frontend development.


RawJS library author here. Moving away from modules is definitely not what I've observed in the community, I see no evidence that this is "the direction the community is moving".

That said, I admittedly have a visceral hatred for ES modules. I personally believe them to be the worst thing that has ever happened to the language. Encapsulation is of course a great thing but in my opinion there are much better ways to do this. I'm not the only person that thinks this–there was a gist that got to the homepage of HN a while back titled something like "ES Modules are terribly, actually" (IIRC).


I'm going to read that gist ( https://gist.github.com/joepie91/bca2fda868c1e8b2c2caf76af7d... ), but what do you dislike or hate about ES modules? From my own experience, they are extremely frustrating when tooling doesn't work well or at all with them.

Given that I don't do JavaScript or front-end for work, I mostly run into these things in hobby programming. Given that this is programming for fun, I can voluntarily cut myself off from all the libraries that use other module systems. In this happy little bubble, over time, ES module support has gotten better and I've selected tools / found ways to use tools that work with modules and I rather like it.

Perhaps because I'm less invested in the tools, I evaluate the situation of "tool X doesn't support ES modules" more like "tool X isn't great" and less like "ES modules are bad".

Perhaps it all stems from being a person who genuinely likes JavaScript, has a high affinity for standards, and a relatively low opinion (yes, I'm a snob) of the Node ecosystem?


You can already do encapsulation without them by using TypeScript namespaces. It's sad that namespaces didn't become part of JavaScript.

I really dislike having to include every last identifier that exists in other files. Yes I know that IDEs will sometimes do this for you

I guess the main thing is that they result in your needing a bunch of additional infrastructure (webpack, rollup, bun.js, HMR solutions, etc) just to get your app to run, when TypeScript can already do all this.


> I really dislike having to include every last identifier that exists in other files.

How do you feel about esm's namespace import feature [1]? For example:

  import * as React from 'react'
> I guess the main thing is that they result in your needing a bunch of additional infrastructure (webpack, rollup, bun.js, HMR solutions, etc) just to get your app to run, when TypeScript can already do all this.

You can obviously use es modules directly in the browser without additional infrastructure. Bundlers simply combine (bundle) all your dependencies into a single file to prevent multiple http requests (although this is less relevant today with HTTP2). HMR solves a completely different problem — replacing individual modules in the browser during development when they change instead of reloading the entire page. HMR isn't something that es modules necessitate. You're free to reload your entire page every time you make a change in development.

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


Off topic and unrelated to the discussion proper, but:

I really wish React had gone with "component factories" instead of `import ... from 'react'`.

This would not only allow for framework-agnostic components (so they could also work in Preact, Mithril, Inferno, etc, etc), it would also make the hooks implementation not dependent on global state.

For example:

    export default const Component = ({ createElement, useState }) => () => {
      ...
    }
Then you would only have to import from React from the entry point.


I don't personally have a problem with ES Modules per se, but I do agree with the "I really dislike having to include every last identifier that exists in other files" part.

I'm a big fan of "global" components in Vue.js, which are "dependency injected" into all your components but in a totally transparent way. You can "just use them" in templates, with zero boilerplate. You also don't have to mock imports in unit tests, you just inject them on an as-needed basis. To me this is 100x cleaner and simpler, there's no room for accidentally running a unit test that actually tests multiple components.

The "irony" is that people avoid them because of the name, but the ones called "global" are actually definitely not global :/

React could also benefit from something like that. The `import { createComponent }` part (which is hidden but must be added by Babel plugins) is the worst part of the framework, and is an obstacle to having cross-framework components that work in React/Preact/Mithril/Inferno/etc.


> I don't personally have a problem with ES Modules per se, but I do agree with the "I really dislike having to include every last identifier that exists in other files" part.

Isn't this exactly the problem that esm's namespace import feature solves?


Not really. I elaborated more in the rest of the message.

IMO the language is fine, and imports are fine too, but the way they're used in popular frameworks isn't good programming. Again, IMO.

My problem is with the excess of transitive dependencies in JS files as a programming style, even though the language supports other more modern idioms just fine. It's the classic Banana-gorilla-jungle problem, to quote Joe Armstrong. One component depends directly via imports on dozens of others, and it can't be separated. This specific style needs lots of compilation trickery to mocking imports in unit tests, for example. It's like Java or C++ in the 90s: zero independency and maximum coupling of everything, killing all portability and reusability.

Every React component directly depends on React, for example. This was a design decision, and is not strictly necessary, from first principles. This is IMO bit of a regression in terms of framework design. Like I said, with injection this would be unnecessary.

IMO one doesn't need "dependency injection everywhere" or "interfaces everywhere" (like 2010s Java, which is also not good), but when you have such a good and simple abstraction like "components" in React or Vue, it is a bit of a waste IMO to not use them and just use the imports-everywhere strategy.

Vue got it right, IMO, with "global" components for example. But this is also shunned by the community (even though it is used a lot by the authors of Vue and authors of libraries).


You're editing your comment very frequently, so I'll reply to it as it appears to me right now.

> IMO the language is fine, and imports are fine too, but the way they're used in frameworks isn't the best.

Ok so I think we're talking about two different things. The RawJS author was saying that he doesn't like es modules as a language feature because he has to separately import each identifier from a package. I was pointing out that you don't have to import each identifier separately, you can simply use the 'import * as identifier from "package"' syntax (es module namespace imports).

You seem to be talking about a separate issue (dependency injection).


Yes, I edited it as I went to make it more clear.

> The RawJS author was saying that he doesn't like es modules as a language feature [...] You seem to be talking about a separate issue (dependency injection).

Yes, that's why I said "I don't personally have a problem with ES Modules per se". Because I don't. But I dislike the abuse of the feature, and frameworks that force its use.


> Yes, that's why I said "I don't personally have a problem with ES Modules per se". Because I don't.

But you also quoted a criticism of ES Modules and explicitly said "I do agree". That's the part that threw me off. The commenter you were quoting (and agreeing with) wasn't talking about dependency injection. Earlier in the thread he said "I admittedly have a visceral hatred for ES modules", and this was him listing his grievances. Dependency injection and ES Modules are completely orthogonal.

I think your other comment where you admit that this is off topic was a more straightforward statement of your position, because you didn't quote (or purport to agree with) an unrelated argument [1].

[1] https://news.ycombinator.com/item?id=38865550


Well, sorry for throwing you off, then. That's why I was verbose with my edits: to ensure there was no misunderstanding. Hope all is clear now.


This seems to happen on subjects much broader than FE community direction. Fringe twitter posts on politics are very frequently interpreted as "what the entire <x> community believes."


It's an awful trend really. When authors do this sometimes I even feel personally attacked and have to hold myself to be nice in the comment section. That usually means I don't even comment at all.


Same. I was quite happy that jakelazaroff was able to phrase it in a better way than I would.


the namespacing is also odd as well. I don't usually see it used that way in Typescript.


Can someone explain these bullet points from the sample repo? [1] They seem contradictory, but maybe there's some esoteric definition of "builds" that I'm missing.

> - No bundler, no build system. Near-zero complexity.

> - TypeScript builds your app in milliseconds, even if your app gets huge.

[1] https://github.com/squaresapp/rawjs-sample


Repo author here. Sorry–maybe not the best choice of words.

By "no bundler, no build system", it kind of means "no webpack, rollup, gulp, etc".

I tend to think of TypeScript as a non-negotiable for any serious project (hopefully I don't get flamed for saying that), so using the build system that's baked into TypeScript means you don't have to rely on yet another tool to handle this.


I see. I don’t really agree with lumping everything else into “yet another tool”:

- The marginal cost of adding a second tool to your build step is generally lower than adding a build step in the first place

- Tools like esbuild give you both TypeScript compilation and bundling out of the box with zero extra dependencies, so you don’t actually need to add an extra tool to your workflow

- Tools like Vite technically do include extra tools but hide the complexity from you, so from your perspective it’s just a single tool


I think they reference two different things

The first statement means you don't need a compiler (or larger build system) to use the library. With React/Vue/etc you need at least something like Babel (but usually also needs a bundler); which has become common lately in the web dev ecosystem. This is all just vanilla JS (or TS) you write; no need to transform JSX or some else.

I assume the second statement means there's not a lot of added type checking time burden for using the library, if you do decide to use TypeScript in your project (but don't have to). Not sure what this means specifically, but I might be something along the lines of it relying on simpler types or eager `any`s in internal types to short-circuit resolving/checking types.


> With React/Vue/etc you need at least something like Babel (but usually also needs a bundler); which has become common lately in the web dev ecosystem. This is all just vanilla JS (or TS) you write; no need to transform JSX or some else.

The TypeScript compiler has native support for JSX. You don't need Babel, you just have to add the '"jsx": "react"' line to your tsconfig file to enable it.


The TS compiler might produce something, but that's not usually enough in the context of a larger React application (eg, they often import non-ts files).


> The TS compiler might produce something

It'll produce calls to React.createElement provided with: the tag name, props, and children. That's all JSX is.

> but that's not usually enough in the context of a larger React application (eg, they often import non-ts files)

React and JSX don't require you to import non-ts files. If RawJS's nascent ecosystem picks up momentum, people might start importing non-ts files in RawJS projects (e.g. css modules). My point is that there's nothing special about the RawJS api that allows you to skip a build step, and conversely, there's nothing about React that requires Babel (assuming you're already using TypeScript).


> With React/Vue/etc you need at least something like Babel

VueJS works with just a CDN link and a script tag. Nothing serious actually uses this approach, and they stopped using it for examples, but it still works.


I appreciate that there is a code sample at https://github.com/squaresapp/rawjs-sample , but I'd prefer something more explicit.

Like what https://youmightnotneedjquery.com did - comparisons between the popular library and the replacement.


RawJS library author here.

Thanks for +1'ing this idea. I like what that website did and I might need to build something similar.



These are also marketing texts. The crowd at HN is very tech savvy. You could at very minimum implement the classic TODO app to show it off.


lol geez the React devs in the comments of that dev.to post are out for blood


Totally unfair: I’m a Vue dev and I’m out for blood too (did not comment on the article though)


Cool. My arm is available if you need a donation.


RawJS library author here.

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.


The page needs some code examples. It's just marketing talk, needs to be more oriented to it's audience.


RawJS library author here.

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.


From the example repo:

> 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.


Repo author here.

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)


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.


Another 2kb “JavaScript got better” library is https://www.arrow-js.com/


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.


You never _needed_ React in the first place.


exactly, unless you like exchanging time for food and shelter via rendering anything in the browser


HN is really on one today with the hyperbole.


It just strayed so far. Everything has gained so much complexity.


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...

[0] https://rightingsoftware.org/


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

rinse and repeat


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.


RawJS library author here.

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.


Big claims and zero code examples?

No I'm not going to go digging in a repo without so much as a top-level overview of the approach


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)

    namespace App {
      export class SegmentedButtonComponent {
        readonly head
    
        constructor(...segments: ((element: HTMLElement) => Raw.Param)[]) {
          this.head = raw.div(
            raw.css(
              "> *", {
                display: "inline-block",
                padding: "1em",
                borderRadius: "5px",
                userSelect: "none",
                webkitUserSelect: "none",
                cursor: "default",
              },
              "> .active", {
                backgroundColor: "hsl(215, 100%, 50%)",
                color: "white",
              },
            ),
            () => {
              const buttons: HTMLElement[] = []
    
              for (const fn of segments) {
                const button = raw.div()
    
                raw.get(button)(
                  raw.on("click", () => this.select(button)),
                  fn(button),
                )
    
                buttons.push(button)
              }
    
              return buttons
            },
          )
        }
    
        select(childElement: HTMLElement) {
          toggleClass(childElement, "active")
        }
      }
    
      function toggleClass(child: Element, cls: string) {
        Array.from(child.parentElement!.children).map(e => e.classList.toggle(cls, e === child))
      }
    }


...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:

<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.


> 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.


Example author here.

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


Even worse, their "Check out Squares" link takes me to 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.


Author here. It was a tongue-in-cheek comment. Let it slide.


The demo is here.

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.


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?


Anything that's like a combination of react and a static site generator? Where it has the ability to build a static site but also includes reactivity


When you click links it changes the URL, so the back button takes you to the previous URL.

I absolutely hate when pages hijack the back button, but this ain’t it.


I mean, it’s not a dark pattern hijacking the back button, it’s a bug hijacking the back button.

It’s still a bad experience, though.


It's not hijacking back like it happens with some sites that redirect and such. It's just pushing each color into history.


I'm not a fan of websites with super huge font. I'm on a 1080, and a lot of the words fit in a smaller font just fine.


The modal when showing a single colour also suffers from backdrop stacking issues, which the back button navigation doesn't undo.

I guess rendering the UI as a function of state still has its merits.


So it implements core SPA functionality?


Why is that bad? That's implementation detail and I would say the right implementation.


Reminds me of componentized jQuery. It appears this has you have to once again apply DOM patches manually; hopefully you implement that correctly every place you update the state.


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.


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.


Two more I noticed:

“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?”


I understand some of the disparaging replies i regards to execution, but if I'm honest, as someone who writes a lot of React, the idea of ditching it for a universally support standard of any kind, is a very appealing idea.


> ditching it for a universally support standard of any kind

RawJS ain't it.

If anything, React' JSX is the universally supported standard these days :)


React is great when you absolutely need state management on the frontend, but is overkill for the vast majority of frontend components to the point I would say it basically doubles the time to create a SPA. I wish I could just import it for one-off components and use traditional HTML rendered by the server for everything else.


You can use many other frameworks for that like Svelte (with SvelteKit), or Solid (with SolidStart)


We can also use React for that–the issue is the bundle size and it does not appear to be designed to share the DOM. I would love to see these smaller libraries document the process and best practices for using them within otherwise vanilla environments.


The first thing that popped in my head seeing this post was the Christmas Dunkin Donuts commercial about ties.

The guy would keep opening up the present year after year and it was another tie.

It seems like the same thing with frameworks and now this library.


>You have to be disciplined to only use dependencies that are published on jsdelivr (npm install programmers need to clean up their act)

...what?

Are people actually using 3rd party hosted CDN scripts for anything even remotely serious in production?


> Are people actually using 3rd party hosted CDN scripts for anything even remotely serious in production?

No, and I think that point makes a very important distinction here: Projects like this might be great for small / personal projects, but they fall apart fast in any sort of large-scale project. The reason people think React is bloated is because they've never worked on a project large enough to take advantage of what React offers.


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.


RawJS author here.

I think it's probably more fair to say that SolidJS is "insanely close" to React rather than RawJS.


While I agree that React has become too bloated, productivity wise I can't see anything like this (or something similar) replacing React.

Yeah, we need something lightweight, but not this.


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.


Whenever I see projects like this, I'm convinced the authors have never worked on actual large-scale frontend projects and teams, especially not for a meaningful amount of time. It's telling when people say "React has gotten too complex."

This might be good for "Squares", but I am not looking forward to having to explain to the new bootcamp grad why this would ruin any sort projects of size.


RawJS author here.

I've been working on said large scale projects for 20 years.

Thank you for your positive encouragement.


Not according to your LinkedIn you're not. I'm talking real scale, hundreds of developers and millions of users. Hell, even midsized companies like Redfin, Grammarly, Brex, etc would suffer using something like RawJS.

Seems fine for hobby projects though.


RawJS-style development (using whatever library to accelerate document.createElement) becomes more appropriate the more divergent your UI is. This is the kind of thing I've found myself working on over the years.


I guess they forked Vapor.js? :)

https://github.com/madrobby/vapor.js



Library author here.

I didn't fork anything.

And your link just pr0n'd me in a coffee shop.

Thank you.


Sorry about that, I don't verify links on N+1 level.


Before switching to some new tech I would go through the likes of VueJS and Svelte first. And htmx is often enough.


> 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?


RawJS library author here.

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.


Ah yes. Yet another "we know better" lib/framework of the week with unsubstantiated claims

> 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:

    raw.section(
      "some-class",
      functionThatMightReturnAString(),
      e => e.classList.has("the-returned-class-string") && "another-class"
      raw.on("click", () =>
      {
       alert("Button clicked!");
      }),
      "section-class",
      raw.div("text"),
      ["class-2", [raw.div()]],
      "section-class-other",
      raw.on("connected", () =>
      {
          // Magic non-standard event!
      }),
      { attr: "value" },
      e => raw.on(window, "keydown", ev =>
      {
          // somehow global events
          // and e is magically our element, of course
          if (ev.key === "Escape")
       e.remove();
      }),
     )
> 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.


The amount of MASSIVE SPANS is really annoying and distracting. I have to scroll a whole view to see another sentence, this doesn't give me much faith in OP.


If only we have custom components and JSX directly supported by browsers without the burden of using React


RawJS requires TypeScript?

I’m always excited when I see an attempt to replace React, but TypeScript is definitively not raw JavaScript.


Feels worse than something like dom-chef


It seems so obviously bad to have to write your CSS and HTML in javascript.

I don't get why people keep coming back to it.

I mean, I get that the point is to add something that plain CSS and HTML don't do on their own, but it seems so much better to start with regular CSS/HTML and enhance... keep the standard syntax and semantics everywhere you possibly can, so that the dev only has to deal with framework-specific syntax and semantics where it's needed.


I mean, that is basically JSX is it not?

I agree with your points, however. How the W3C has not come up with a good solution is beyond me.


> I mean, that is basically JSX is it not?

Yes, exactly.

I get that many devs have learned and internalized how JSX (and the rest of react) renders to HTML and CSS, and have come to understand the mechanism well enough to debug when mistakes are made and things go wrong. But time and effort dealing with the framework takes away from time and effort spent on the thing you're actually trying to build. It just pays to minimize that where you can. JSX isn't as bad as this "rawjs" but it certainly has its issues.

Beyond requiring extra dev attention, JSX is also part of and implies the whole virtual DOM diffing/rendering mechanism, which just limits the rendering optimizations the framework is capable of doing on its own. That leads to poor performance (and/or incorrect rendering), or, again, the dev spending time on something the framework could have taken care of if it had been designed differently.

Fundamentally, a framework needs to be able to figure out what needs to be rerednered and what doesn't when state changes because it can't reredner everything on any change. That's just harder and more limited when everything is rendered dynamically.

I'm not trying to bash react and JSX... obviously it was workable and did a ton to popularize the reactive approach. But I don't think anyone thinks it was perfect from the start and obviously we've learned a lot about what works and what doesn't. To me this "rawjs" is a step backwards from even where react started out.


Dear god, not another one.


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 is an example page: https://rawjssample.pages.dev/


Reading these comments... this is a disaster.


Getting a broken SSL cert accessing this site


The polar opposite of htmx. . .


"No known bugs" is not the brag that they think it is.

It's like someone peddling a medication and saying, "No known side effects."


RawJS library author here.

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.


"no known bugs" is technically the same as "may contain unknown bugs"


Author(s) of this may be the type of people to not use a library because it has a lot of open github issues


could be rewritten as "0 open bug reports".


it's like someone collected all my least favorite coding styles in a single library




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: