Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
_hyperscript: A jQuery and JavaScript Alternative (hyperscript.org)
218 points by recursivedoubts on April 21, 2021 | hide | past | favorite | 126 comments


Hi there, I'm the creator of _hyperscript and htmx, happy to answer questions.

_hyperscript is much more speculative than htmx, but it is working out pretty nicely. One aspect of the language that HN readers might find interesting is that it is async-transparent: the distinction between synchronous and asynchronous code is largely hidden:

https://hyperscript.org/docs/#async

This allows for some pretty interesting programming techniques, such as event-driven control flow:

https://hyperscript.org/docs/#event-control-flow

One thing to be aware of with _hyperscript is that it is intended as a light weight, event oriented scripting language, I would not recommend a huge application being build out in it exclusively. It is designed to make it easy to plug into the event models of htmx and other libraries.

EDIT: I should also mention, it is still very early in development (0.0.9)


Some people are writing an alternative, Twinspark, inspired by intercooler/htmx but without inheritance and with batching [1]. Avoiding inheritance seems especially good to me. I'm wondering what is your take on removing inheritance/providing an alternative to it?

[1] https://solovyov.net/blog/2020/a-tale-of-webpage-speed-or-th...


I don't have a strong opinion on it: I think inheritance has worked out pretty well when I've used it (e.g. if I want a bunch of links to target a specific div, I can hoist the hx-target to a parent.)

But I salute twinspark as well and if it dovetails better with your sensibilities I encourage you to use it.


Do you work alone by chance? Because it's pretty easy to avoid problems when you work alone, remember what exactly the code does. However, when working even in a small team (3-5 devs), it's becoming much harder to avoid such footguns.

It would be really cool to see two projects merge (htmx and twinspark) and join forces.


The async transparency aspect is very interesting from a design POV! What were your inspirations for that?


I just hated the way that callbacks look or that you had to color your functions:

https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...

For light weight scripting I didn't want to have to think about that. I had implement a "wait" command in the old ic-action attribute from intercooler:

https://intercoolerjs.org/attributes/ic-action.html

And I wanted to generalize that.

(A motivation for creating _hyperscript was because I removed ic-action as well as a bunch of other event-based attributes when rewrote intercooler.js as htmx: https://hyperscript.org/docs/#history)


The async transparency stuff is really interesting, and reminds me of a comment[1] I made a couple of years ago here on HN about async/await and how I think it's backwards from what it ought to be. Really glad to see you exploring this further, I think you're on to something.

That post from Bob Nystrom's blog makes the point I was trying to make much more eloquently than I could, thanks for sharing!

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


Yeah, it's really annoying that if you want to introduce some async behaviour in a function, you end up having to deal with it at all the call sites

In the intro section I walk through adding a fetch to some code that jams text into a button and you can see how you don't end up having to change your code to do it: you just write the normal linear code with a fetch command in it:

https://hyperscript.org/docs/#introduction

  <button class='btn primary' _="on click fetch  /clickedMessage then transition opacity to 0
                                 put the result into me then transition opacity to 1
                                 wait 2s then transition opacity to 0
                                 put 'Click Me!' into me then transition opacity to 1">
    Click Me!
  </button>
The fetch, wait and transition commands are asynchronous (in javascript terms) but to hyperscript it's all just linear code.


Is this inspired by HyperTalk/AppleScript, which are also english-like?


yes, explicitly by hypertalk (I didn't use appletalk much and didn't like it when I did.)


Very cool! Just a heads up there's a bug with the event control flow example where it requires pressing the "stop pulsing" button the same number of times you've pressed the "start pulsing" button. I figured the behavior should be regardless of how many times I've clicked "start pulsing" the next time I press stop, it should stop.


Ah, you've stumbled on the event queuing behaviour of hyperscript:

If a triggering event is received while an event handler is executing, you can specify various behaviours:

https://hyperscript.org/features/on/#queueing

The default is queue last, which will queue the last event and trigger the event handler again once it completes. I agree that is wrong in this case, and so it should specify `queue none` in the handler. I will update the code.

Thank you for taking a close look at the example!


Have you any comparison with Turbo?

https://turbo.hotwire.dev/handbook/introduction


Several years back, when I was learning my first web stack, I got some very good advice from a seasoned developer.

"Focus on the fundamentals of HTML, CSS and JS. Everything else is ephemeral."

I don't mean to pick on whomever wrote these examples, but the ~7 lines of JS for the first example (fading out) shows either a lack of basic understanding or intentional complication to make hyperscript appear better in comparison. A more reasonable solution is 3 lines of code.

    .fade { transition: opacity 500ms ease-out; }

    <div class="fade" onclick="
      this.style.opacity=0;
      this.addEventListener('transitionend', () => this.remove());
    ">Remove Me</div>


This doesn't remove the object from the DOM after the animation is over, which the example on the website does. You'll need to add something that removes the element after the transition is over which would be a bunch more code (the eventlistener for transitionend) :)


Thanks for the heads up before the Hacker News edit window closed. +1 LOC


FYI you can set a "delay" in your profile of up to 10 minutes before your comments are shown, giving you more time to edit. May not have helped in this case but it's a cool feature.


thats's a nice tip. Thanks


one can learn a lot from reading the FAQ: https://news.ycombinator.com/newsfaq.html :)


:D that's fitting for HN.

Instead of finding a more descriptive name or adding a short description below, they put it on a completely different site.


Thank you, I'll update the example. I usually stay in es5 for IE11 compatibility (htmx is still supporting IE11) so I tend to write js in a more archaic style.


That 1% market share of IE gets smaller every day, as we wait with bated breath.


:) I know, I am looking forward to using IntersectionObserver in htmx.

But I'm a bit of a contrarian and every time someone tells me to drop IE support I think "Maybe I won't."


Also a heads up, the vanilla fade out demo doesn't work correctly (immediately disappears) as in the actual code it looks to be missing the transition line.


Thanks for reporting, fixed.


I generally agree that practically, focusing on the heavy weight technologies will be the most useful in the long run. In defense of DSLs, I do love them. It's the magic of doing a task specifically as the most intuitive magical incantation. A beginner can pick the DSL up easily and get excited about learning the underlying fundamentals. An expert can code complex scenarios more efficiently.

Still, there's a pretty steep curve to developing them, and that generally translates into a shorter lifetime unless they take off in popularity. For example, tooling support, for things like autocomplete, highlighting, debugging will need to be implemented. There's also a lack of community answering questions, making it difficult to pick up for beginners (no stack overflow, etc).


Won't the arrow function not bind `this` to the DOM element, causing it to refer to the window object? I think you have to use a real `function`, `function(){this.remove()}`


Arrow functions have the same `this` as the scope where they are declared (in this case, an onclick attribute). Both would work in this case.


Yes, I'm sorry but that JavaScript example code is terrible.

I realize this sounds harsh but truthfully, it made me immediately disregard the library. If this is how you would solve these issues in JavaScript I'm not taking you seriously.

The web API offers an elegant separation of content, style and logic and these examples are just stuffing everything into logic. Don't do this


For a trivial example like fading out, you're right, but if you want to make dynamically generated animations, hyperscript's features are very helpful (The Web Animations API is a boon, but browser support isn't there yet).

Separation of HTML/CSS/JS doesn't always mean separation of concerns. Every application has a different definition of a "concern", and if it doesn't align with the separation between languages, you don't get decoupled code, you intensify the symptoms of tight coupling.


Do you remember who said the quote? That's fantastic.


I'm not sure to be honest, but the above quote is the result of me distilling the seed he planted in my mind into as concise a statement as possible. Unless I am mistaken, his original (I think it was a StackOverflow post related to JQuery) was much longer.



See also: preact, mithril.js, etc

I mentioned this before[0] but it seems the author is committed to the name, despite the potential confusion downsides </shrug>

[0] https://news.ycombinator.com/item?id=26744932


I read this too late and was already confused.

Since the author is here, I’d like to take the opportunity to suggest they change it.


Yes, hyperscript is a well-established term, and is still in use today. An unfortunate name clash.


My gut feeling is that this won't scale to work well in a non-trivial app, but I don't want to jump to conclusions, either.

If the author is really trying to be a better jQuery without long chains of callbacks, then I'd like to see an example that shows exactly that. Show us an AJAX call that GETs data, add elements to the DOM based on that data, then binds events to those elements that call some existing functions. Maybe an example fetching data to build a draggable/droppable list with separate handlers for click vs. drag, or something along those lines?


There's some comparisons here[0]

As far as I can tell, where it falls somewhat short is in template dynamism, e.g. keyed arrays in React (which entails that drag/drop might also potentially be tricky), fractal structures like generating HN comment trees from JSON (vue, for example, used to have perf issues in the early days in this area due to recursive-descent rendering instead of batching), etc.

It seems to dabble a bit into normal control flow structures[1] but once you're at that level of language complexity, I'd probably prefer using a more established framework over this natural language DSL. The HN comment tree use case, for example, doesn't seem very easy to optimize if it turns out to be implemented in terms of reading the DOM to trigger subtemplate creation.

I think it's certainly interesting that there's now interest in alternatives to compiled stacks (e.g. React, due to JSX, anything using Typescript, etc) that are mindful of compile time creep and aim to bring development speed back into the limelight, but I fear that projects like this might be making the original "mistake" of shoving the perf pitfalls back to the runtime (where the users care). Personally, I think the future is going to be better compiler infrastructure e.g. esbuild, swc and the projects built on top of them (vite, etc).

[0] https://hyperscript.org/comparison/

[1] https://hyperscript.org/commands/repeat/


Just a shout-out to esbuild:

I've been working with it and, while it does have a few rough-spots occasionally...in addition to how fast it is, I love how easy it is to work with and write unique behavior for as necessary.

I never really fully digested Webpack, and I think part of that was because of the way it pushed its plugin ecosystem. By contrast, esbuild's plugin system is super easy to understand and placed front and center with the ecosystem off to one side, so if you write a esbuild script (in js OR Go), it's really easy to just write code to do what you want to have done instead of hoping that a bunch of third-party plugins can work together in the way that you want.

Anway, I haven't used swc, but I agree with your assessment. I look at all of the projects that are being worked in that rely on esbuild and swc and they all point to really pleasant development experiences that also have the capability of producing performant code.

What I haven't looked at recently is some of the other language specific pipelines. Is anyone here using non-TypeScript compilers to target JavaScript (like Kotlin, Scala, ClosureScript, ReasonML/Bucklescript) that could speak to the dev experience of the toolchain in 2021, as well as the resulting performance of the js? I'm pretty happy with TypeScript and get happier with each new release, but I'm also really interested in hearing other perspectives about language toolchains targeting js, and what folks are building with them.


Well sure, but this isn't for applications. It's to quickly and simply toggle a class or throw some AJAX functionality onto a page, which is all the vast majority of sites ever need to do. I can see it being super popular with the WordPress crowd.


> Show us an AJAX call that GETs data

    <button class='btn primary' _="on click fetch /clickedMessage 
                                            put the result into me 
                                            wait 2s
                                            put 'Click Me!' into me">
      Click Me!
    </button>
More here: https://hyperscript.org/docs/


I saw that, it leaves out a lot. In production you'll need something that formats the response and handles errors, which means defining a custom Event Source. It seems like the functionality quickly returns to traditional javascript when any normal amount of complexity is required.


As one of the other replies mentioned, the fetch will throw an event that you listen for. The server is the response formatter. The piece of the puzzle that you're missing is that the intent is that this library is used with the author's other library, htmx[0]. With htmx, the expectation is that you're always returning HTML as the response (though there are extensions available so you can return JSON that could be processed against a client-side handlebars template).

[0] https://htmx.org


Apparently when the fetch fails, it triggers an `fetch:error` event[1], which can (probably) be handled somewhere. No idea about formatting the response, though.

I think it's quite natural for there to be large gaps in functionality provided: it looks like a rather young and unpopular project, so the additional code needed to handle more situations from within the language still needs to get written. jQuery also didn't have a whole universe of plugins from day 1, but was useful enough anyway. Not saying this project has a chance to become another jquery, just that it too can be useful even in a far-from-complete state.

[1] https://github.com/bigskysoftware/_hyperscript/blob/master/s...


Yep, you can have an `on fetch:error` clause in the element's script.

Wrt. formatting the response, I'm experimenting with a hyperscript template language [1]. However, we don't yet have a design for imperatively building DOM trees (other than just doing it the same way you would in JS).

[1]: https://dev.hyperscript.org/commands/render/


My first reaction was that "this sucks, who would want to use some non-established DSL over universally understood JavaScript". But thinking about it more, this is just like functional CSS libraries (e.g. Tailwind CSS) that allow you to compose behavior from strings that you bake into the HTML. I don't agree with the syntax here or the use of `_` instead `data-*`, but I think it's worth looking into encoding common UI behavior into HTML classes or a custom data-* attribute.


From the docs:

> While the underscore (_) attribute is where the hyperscript runtime looks for hyperscript on an element by default, you may also use script or data-script attribute, or configure a different attribute name if you don't like any of those.


This is giving me some serious HyperCard/HyperTalk vibes from the late 80s/early 90s on Macintosh computers! Perhaps that is why the name has "hyper" in it?

_hyperscript:

    <button _="on click fetch /clickedMessage/ then put the result into #fetch-target-3">
HyperTalk (https://en.wikipedia.org/wiki/HyperTalk):

    put the value of card field "typehere" into theValue


Yep, I programmed in HyperCard/HyperTalk a long time ago and when i was thinking about how I needed a language with native event handling I remembered HyperTalk. :)


It's libraries like these which remind me that even today most of the web front-end consists of static pages with JS sprinkled on top.

Yes, there's Facebook with React and whatnot, but for every shared news article there you'll find an URL which leads to a WP site with jQuery added for interactivity.


The real problem is all the pages that could be static HTML with some JS on top, but are instead SPAs with a dozen layers of abstraction taking half a gig of RAM and five seconds to render.


I've thought about this a lot and my position is that it all boils down to how bad is the result when you apply any of these approaches wrongly.

Turns out static pages with JS on top can be even worse than badly done SPAs - especially when the server infrastructure is lacking and a single request takes a significant amount of time.


Surely all of the money invested into that SPA could be redirected into a simpler full-stack app, with sprinkles of progressive JS?

On the one hand you have a shared-nothing architecture that serves HTML and can enjoy varying forms of caching.

On the other you have an application that still depends on a server, but replaces all of that simplicity with a stateful client-server architecture that requires _more_ infra to manage, at a greater expense.


There's one important factor you're missing: for lack of a better word - "staffability".

Just about every programming language has also a web framework implemented in it, so if you want to create a full-stack web app, the range of options is just dazzling, which results in a highly fragmented ecosystem.

Meanwhile on the front-end there's essentially one language(with different flavours) and 3-4 leading frameworks, so once a developer has these covered, they can be hired to do anything in this part of the stack.

The overall result is that it's easier to scale work if you offload it to the front-end, because by the time you found your <insert highly specific language/framework combination>, your front-end developers would have done most of the work twice over.

There are many more reasons why you would want a SPA instead of a full-stack app, but this is one of the strongest.


I mean, that's just bad development though. You can write React with literally 0 external libraries and have a fully-fledged state management solution built-in.

The same folks who fail to understand that and just recklessly add dependencies aren't going to craft a nice static HTML site with smart, minimal, performant JS; they just don't have the chops for clean solutions. The medium barely matters.


I disagree. Making a good site with React takes more effort than not making bad site otherwise. Also because it’s fashionable React (and similar frameworks like Angular or Vue or Ember) are used in places where they don’t belong and it stinks.


I just am saying, someone with clean HTML/CSS/JS knowledge who abuses React to the degree you're implying just sounds like a strawman to me.


Frameworks shield from footguns like unpredictable DOM modifications all over the place put one over the other.

I was there when AngularJS was still this revolutionary new framework and back then any sufficiently sophisticated form would eventually become unmaintainable.


Wait.. no. There is enough information out there that suggests that React's Context should not be considered a replacement for Redux. Just think about having multiple contexts and derived state - there would be scenarios where your view layer would be unnecessarily coupled with stateful logic or other undesired patterns.


> think about having multiple contexts and derived state - there would be scenarios where your view layer would be unnecessarily coupled

Can you expand on this?

I have created entire applications which are operating off of a single React context, and then also created some generic components which themselves expose a provider to their managed subtree. I have not faced any issues or "coupling" between these layers; I just pass props from the top-level context to the top of another subtree / component, and it works as I would expect.

I don't rely super heavily on derived state, but I find useEffect and useMemo to both be quite simple and effective when I need side effects or to memoize a piece of derived state to prevent throttling.

What situations am I missing that introduce these issues you talk about? How does Redux solve them more cleanly?


I'm just speaking from my own experience where we had an redux app with 30-40 reducers operating on quite a lot (100-200) of dynamic attributes in those objects and approximately the same amount of attributes that are initialized just once and don't change over the lifespan. I can't imagine using a single context for it all. We used thunks heavily, of course. I would prefer to look at the code to better understand how we approached problem solving in each case. Also, have you ever had to invest a good chunk of time to solve performance issues in any of those projects? We did.


I love it. I am totally fond of the locality of behavior approach. Not many frontend tools do fit into the traditional niche of JQuery were you want a static site with some quick and easy way to add some interactivity.

Now I do share the concern that it might not be the best approach for really complex stateful applications but we will have to see how it scales once we see the first real world uses of it. It is good to know that the is always the escape of hatch of simply using plain vanilla js. Sure it wont replace React/Svelte/Elm level of use cases but I guess that is not the goal.

Also really dig the fresh take on a human friendly syntax. Sure there are pitfalls with that but hey for this kind of DSL it might work out. Nice to see people trying out non mainstream approaches.


<div _="on click transition opacity to 0 then remove me">

My immediate reaction was "Oh, web Cobol".

Edit: By the downvotes, I'm guessing people think it was a lazy attempt to poke fun. It's not though :) Cobol has a very repeated VERB->NOUN->ADVERB->ETC sentence style pattern that's very similar to what's in that snippet of _hyperscript above. Like:

DIVIDE NUMA BY NUMB GIVING RES-DIV

PERFORM VARYING LoopCount FROM 1 BY 1 UNTIL LoopCount GREATER THAN 4

And so on...


Thankfully, we have arithmetic expressions :]

Every command has an initial verb, which makes parsing easier (both by computer, and hopefully by people). Just for fun, here are your examples in hyperscript:

    get numA / numB then put it into resDiv
    -- or simply
    set resDiv to numA / numB
    
    repeat 5 times index loopCount
      log loopCount
    end


Ah, very cool. Thanks for sharing the hyperscript examples.


I had the exact same reaction. It's a very striking resemblance. Don't mean to detract from the project though, not my piece of cake but could be handy


The first example is already bizarre: use CSS and a transition listener on the JS side, why would you still implement it with a 1998 onclick, and a setTimeout? This isn't modern "vanilla JS", this is "ancient nonsense" =/

Add a CSS class "hide-animated" tied to your transition, add a transition end listener on the document (not once, perpemtual), with evt => evt.target.remove()

(That's right, ".remove()", not "element.parentNode.removeChild(element)". Actually looking up modern JS is a good idea if you're going to knock it).

And then the only other JS thing you need for your element is a click listener that adds "classList.add(`hide-animated`)".

Is "addEventListener(`click`, evt => evt.target.remove())" overly verbose and cumbersome? Sure is, I have no love for it, but if you want to show that your library is better than vanilla JS, show vanilla JS, not code from 20 years ago.


I would love a pull request with improvements.

I'd like to be as fair as possible in these comparisons.


Wait, you're looking for people to do the work you claim you did?


For htmx I have to stay in es5 to preserve IE11 compatibility, so there are modern features in the language I don't use on a regular basis. I appreciate any help from people who are better at the language, but of course understand if people aren't interested.


Thanks for commenting! I just did a pass over the vanilla JS examples addressing some of these issues.

Wrt. transitions:

> use CSS and a transition listener on the JS side

Now you need to have 3 files open in your editor simply to be able to say "this button fades away in half a second when clicked". The onclick is used to somewhat alleviate this (See "Locality of Behavior" [1]).

Separation of concerns is important, but different applications have different definitions of what constitutes a "concern". If one expects that the hiding animation will be changed by designers, one would likely use CSS as you suggested. The nice thing about `settle` in hyperscript (as opposed to just listening for a transitionend) is that you can switch from a transition to a keyframe animation and it will still work with no changes.

> add a transition end listener on the document

Wouldn't this also detect non-disappearing transitions (say, an element expanding or changing color)?

[1]: https://htmx.org/essays/locality-of-behaviour/


> Now you need to have 3 files open in your editor

Are you saying that isn't already the case? Do you inline all your CSS and JS directly? Because that'd be super weird.

> Wouldn't this also detect non-disappearing transitions (say, an element expanding or changing color)?

The event comes with information about which class the transition was for. So: sure, but if you have lots of different transitions we're no longer dealing with simple code that we can write simple "vanilla vs. jquery vs. your lib" code for?


Do you push arrow functions to production? IE still accounts for 2.5% [0] of browser share and has no support [1] for them.

My guess is that most of us have Babel in the mix of a production deployment, in which case I think the “20 year old code isn’t vanilla” loses some of it’s effect.

0: https://www.statista.com/statistics/272697/market-share-desk...

1: https://www.caniuse.com/arrow-functions


Whether you use babel or not is irrelevant: you'll be running it at the end of your build chain, while writing modern JS.

But yeah, I absolutely push modern JS out to prod, because our demongraphic is very much nowhere near 2.5% - our actual number for IE users is 0.4%, for all versions of IE combined (just IE11 would be 0.2%). Even Samsung's browser ("Samsung has a browser?") drives four times as much traffic as all version of IE combined.

IE use has properly died down ever since Microsoft themselves started making sure folks weren't using it anymore. And they really don't want you to use internet explorer: Windows hasn't had IE set as default browser for years now. It comes bundled with Windows 10, sure, and IE11's EOL is contractually tied to the Windows 10 EOL, sure, but Microsoft is working damn hard to make sure you're on Edge instead.

If you have to support IE, because you have a target demographic that for whatever reason is forced into IE use, then sure: roll whatever code you need. But if you're developing for the current web landscape: no, IE is not your concern anymore.


I don't think that 2.5% number is true. I can't click thru that paywall without signing up, but for example you rown caniuse link suggests 0.99% and this [0] suggests 0.73%

[0]: https://gs.statcounter.com/browser-market-share


The symbol-light, kind-of-English-looking syntax initially reminded me of Common Lisp's LOOP DSL[1] before I made the connection to HyperTalk/HyperCard.

[1] http://www.gigamonkeys.com/book/loop-for-black-belts.html


It looks interesting. There is a lot of complexity that can be hidden behind a well-crafted DSL. REBOL's View dialect and TCL's TK are examples of DSLs which make developing UIs much simpler than it would be with a full language. It might work with web frontends, too. It's also quite safe to use, in that it has an escape hatch and allows embedding JavaScript in it, and allows extension with JS code. The drastic simplification of the build process (and the reduction of the amount of code needed to do something useful) makes it attractive to people who don't work on the frontend often. I'll definitely give it a try.


Not to be confused with HyperScript [0], a popular JS templating library.

[0] https://github.com/hyperhype/hyperscript


In case you never knew you wanted AppleScript in the browser, here it (sort of) is!


Looks like it's supposed to be more like HyperTalk in the browser:

> It is based on an older and somewhat obscure (today) family of programming languages that originated in HyperTalk...

- https://hypescript.org/docs/#syntax


htmx by itself is so good—when paired with discipline in the backend in creating proper fragments anyway—that so far I haven't needed hyperscript. But then again, htmx is so good that any project by the author has my vote of confidence by default.

Still, I oughta try this to make a proper judgement.


:) I appreciate hearing that.

_hyperscript is far more speculative than htmx, so if you don't need it, don't use it just to use it.

But if there are places where a bit of light scripting might help, it's maybe worth a try.


I haven't started to use _hyperscript yet but htmx (by same author) has been a real pleasure to use with Django. SPA like behavior with 1/10th effort.


It seems that the strings in the _ attribute aren't actually being read at runtime. E.g. if you edit them in the DOM it doesn't change anything. I assume this means it's compiled once on DOM load?


You're pretty much right. Modifying the code at runtime is useful for devtools fun, but not much else.

If you'd like to play around, open the console and try calling the `_hyperscript` function:

    _hyperscript(`get the first <button/> 
                  transition its background-color to 'red' over 2s 
                  log ':]'
    `)


We have a (hidden) playground here:

https://hyperscript.org/playground/

Still a work in progress, but you can play around w/ the language.


Neat, appears to occupy a similar niche as Alpine: https://github.com/alpinejs/alpine


yep, very similar goals (although _hyperscript, sadly, requires a lot more code...)


I like the locality of behavior concept and am interested in learning more about hyperscript.

This VanillaJS example is just plain silly. I've never seen anyone set styles and call requestAnimationFrame & do all that in an inline onClick handler. I mean html elements have a `style` attribute, why would you set `transition` in a click handler?

The vanilla example should look more like the jQuery one, with the the code apart from the markup & referencing the element by id or class, attaching a handler with addEventListener.

Your will still compare favorably, and this a slightly less "intentionally ugly" way to write the code.


Wow! This is just sweet!

I love the natural language approach and simplicity.

I'm definitely going to block off some time to play with this.


I really like hyperscript et al. They seem to apply the 'everything-in-one-place' approach from modern JS development to HTML itself, extending hypertext without papering over it.


Tangential, the best web tech (in my opinion) I am considering at the moment (in this order):

- Svelte

- htmlx

- lit-html and perhaps also lit-element


Seems cool in general. I like their point about "locality of behavior".

Some of the syntax give me unfortunate flashbacks to AppleScript. Expressions like "the location of window" looks cool at first glance, but in reality "window.location" is easier to both read and write, especially when you start to compose more complex expressions.


> but in reality "window.location" is easier to both read and write

No, it's not easier to read. Really. You think it is, but that's only because you're used to it. If you take a step back and look at the "window.location" expression objectively, while forgetting all that you know about programming (but retaining your knowledge of English), you won't be able to tell what is it about, not with any kind of certainty. Or, if you have experience with some other programming languages, you might read it as "a composition of function window and function location". On the other hand, "the location of window", even if it's not 100% correct English, tells you all that you need to know to understand what is happening.

It is easier to write, but only because it has less characters. The docs state pretty clearly that they are optimizing for ease of reading, not writing, so this is expected.


Natural-language programming comes up from time to time and it rarely sticks around.

For myself, I can't parse them without my brain trying to read it as actual English. Having programming languages look distinctly different from human communication keeps my mental overhead low. I find Applescript impossible to use.

NLP also has a major issue with rapid comprehension. It's far harder to see the structure of code at a glance if everything is just keywords. While this is an issue with every type of communication, NLP has a significantly lower upper limit to almost every other language I work in. SQL is a middle ground. If you format it properly, it's really easy to scan and see what's happening. Applescript? Not so much.


I agree, applescript is a warning to anyone going down the hypertalk-derived road

I am adding things like CSS literals:

https://hyperscript.org/expressions/#css

in the hope that we can increase the expressiveness (and distinctness between different elements) that we don't fall into the wall-of-text nature of applescript.

It's a speculative project, we'll see how it works out.


But I am a programmer, and this code is going to be written and read by programmers. The experience from AppleScript shows IMO that a more English-like syntax does not actually make the language simpler to use, it just obscures the underlying semantics, making it harder to learn.


I don't disagree, but "simpler to use" and "easier to read" are almost orthogonal things :)


I guess programmers can mean different things with "easy to read", but to me it means "easy to understand by reading". This in turn has two aspects: How complex the meaning is, and how clearly the syntax express this underlying meaning.

The fallacy of AppleScript is to think that a syntax which looks familiar on the surface makes the semantics esier to understand. But since the underlying semantics are those of a programming language, not human-to-human communication, the syntax obscures the meaning.

So to me "easier to read" and "simpler to use" both depends on the ergonomics of the programming model and the syntax used.


How about `the window's location`?


... which syntax HyperTalk originally supported as a sugaring of `the location of window` ...


oh, we support that too :)

  set the location of the window to 'https://hyperscript.org`


I have a small marketing webpage I am working on and I could see this being useful for that. Most of what I want to use JS on for that is relatively straightforward and this seems like a simpler approach than using a full framework or writing everything from scratch in normal Javascript.


This seems quite interesting and powerful for what most server-side rendered websites need from javascript, however the _usage_ seems fairly klunky to me at this stage.

I could see this being a joy to work with though if a well determined usage pattern emerges where you have something like a `some_page_template.html` file open next to a `some_page_hyperscript.hy` where you define all the locally scoped functionality and the two are combined by your webserver template engine.

It wouldn't be very hard to set up, but having a de-facto way to structure and organize things it would likely help with adoption and prevent new users from being architechture astronauts.


As a developer with dyslexia I hope this never becomes popular as I would be out of a job.

Kuddos to the author looks cool but personally I wouldn't be able to make a single thing work.


It seems like this library was built to address the edge cases the author is familiar with, and for the more complicated actions it starts leaning closer towards a traditional language. For example, the debounce function referenced in the JS comparison isn't even a properly implemented debounce, which means his built-in language function for debounce is incorrect. I've had to build or use a debounce function maybe 10 times in 12 years personally.


Would you mind opening an issue on how the debounce is incorrect? I'd like to fix it if possible.


Looks useful for a lot of the mini sites or landing pages we need to do, would make it much easier to add some basic interactivity with potentially less debug time


I guess it could be useful for simple DOM manipulation. The issue with it is, despite how great co-locality of concerns is, is that it can't EVER be separated. So I would use something like this if I wasn't using any framework at all. As soon as you use a framework (e.g. svelte/react/vue), the need for manual jQuery/dom manipulation drops to near 0.


You wouldn't use a framework like react/vue with this. It is a companion project of htmx (1) which takes a different approach than your typical JS framework. There is a recent JS Party podcast (2) with the author if you want to learn more and have a better understanding of the motivation behind these approaches.

1 https://htmx.org/

2 https://www.youtube.com/watch?v=hJdxR6qoUOE


> recent JS Party podcast (2)

See also https://changelog.com/jsparty/171


I think this should expose something like `_hyperscript.on(domElementHere, 'your hyperscript string')` and that could resolve the co-locality concern.


we are working on supporting _hs files and you can write event handlers against other elements:

  on click from #some-btn
    log 'The button was clicked'
  end
However, we really lean towards directly embedding the scripts on HTML elements for Locality of Behaviour https://htmx.org/essays/locality-of-behaviour/


'guess' indeed, it probably doesn't take long to run into a situation where you have to go back to regular JS.

I'm confident the examples given can be simplified as well. The vanilla JS and jQuery examples are not equivalent for example, the vanilla one is (intentionally?) inline JS whereas the jquery one separates it out.

It also doesn't use ES6 arrow functions (neither vanilla nor native), which would remove the need to rebind `this` to `self`.

The vanilla one also sets style via JS, which isn't how you should do things. Transitions can be set in CSS beforehand. The one used sets the animation to 'all' properties as well, instead of just 'opacity' which is the only property changed.

TL;DR the article is making vanilla look more difficult than it is. The jquery example seems lifted off of Stack Overflow.


I wouldn't implement this in any larger projects. Reading through the syntax it seems to fluctuate between choppy flow and fluent English.

Possibly for smaller personal projects, but maybe that is what the library is for.


What's the debugging experience like? If some _hyperscript code I wrote doesn't do what I want it to do, what do I do?

Is there some browser extension of some sorts or some IDE-like tool?



This could be nice for new people but as a person well versed in jQuery and CSS selectors it would be more work for me to learn this than to continue using jQuery.


hyperscript has built in CSS literals, which can make code pretty tight:

https://hyperscript.org/expressions/#css

Not suggesting you give up jQuery, but a lot of your knowledge should transfer if you ever want to play with the language.


So say you want to start a fetch and some animation at the same time to indicate progress. Both run in parallel. Not very unusual use case.

How?


There is an example using event-driven control flow that could be used as a basis for this:

https://hyperscript.org/docs/#event-control-flow

Coupled with an async command:

https://hyperscript.org/commands/async/

The language is very young, so we are still building out the docs and examples.

For something like htmx, where there is already a rich event model around requests, I would instead listen for htmx:beforeRequest and htmx:afterRequest events:

https://htmx.org/reference/#events

And use that event-driven control flow technique to smoothly end the animation.


I see, async command would solve that. Thanks.


Looks like jQuery without punctuation.


This won't scale. It will be like AppleScript for Web :)


Hyperscript is great. Just like the real revolutionary htmx.


I haven't been this excited about anything in web dev for a while.




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

Search: