Hacker News new | past | comments | ask | show | jobs | submit login
Hyperapp – A tiny framework for building web interfaces (hyperapp.dev)
397 points by Al0neStar on June 30, 2020 | hide | past | favorite | 188 comments



I have tried Hyperapp some time ago. It's usable for small apps, but the lack of ecosystem makes it unfit for anything larger -- as is usual for all niché JS frameworks.

Funnily, the "ecosystem" page contains just Lorem Ipsum (https://hyperapp.dev/ecosystem) and the Awesome Hyperapp section for V2 is almost empty (https://github.com/jorgebucaran/awesome-hyperapp)


Is niché a portmanteau of niche and cliché?


No, it's niche with a French accent


Fun fact: niche is a French word that doesn't have an accent. So niché is the heavy metal ümlaut version.


niche with a french accent sounds like the "nish" in "varnish".


It’s pronounced “NEE-chuh”.


Like Nietzsche?


More like neesh.


Good content.


We're so close to the official V2 release, but there are still issues. I'll make sure to fix most by then. You totally have a point about the lack of an ecosystem, but building one is where the fun is. I am sure we'll get there! Thank you for your feedback.


It's been like that for months - seems like the project is not seeing the activity they expected for v2.

Also server-side routing is broken and that link will not work.


We are very close to the official V2 release, but right now that page is still a WIP.

The link works fine, though.


Also, if you click "join us" and then "tutorial" your scroll position is in an unexpected place.


It’s broken here too.


Do you know why?


Oooh, I see. It (https://hyperapp.dev/ecosystem) is broken if you've never been to https://hyperapp.dev before.


Ah, gotcha gotcha. Thank you for reporting it! :)


Yeah, I got a 404 page when visiting it, too.


I am on macOS / Safari 13.2.1 and I can not visit hyperapp.dev/ecosystem after visiting hyperapp.dev


The link does not work.


Any idea why? Any info you can share would help us debug whatever the issue is.


Missing a wildcard route? No idea how your routing is setup


It's all client-side. When I click that link, it opens the site as usual.


Click the link directly: https://hyperapp.dev/ecosystem

As the parent said, you don't have a catch-all route. That is why!


That's what it is, thank you for clarifying.


Their guide (https://hyperapp.dev/guides) page is also filled with Lorem Ipsum.


Ouch, yes, that's also a WIP, thank you for checking in, though.


The quickstart is quite clear, but I'd love to see some slightly larger examples like, how is state passed between components? How do event handlers work? The API page seems sparse as well.

But it looks like a great start


And you'll get it! Just check again soon as we should have the official release out there in just a few months, maybe less.


> but the lack of ecosystem makes it unfit for anything larger

What does this mean?


Some problems are hard, common and already solved. Sometimes solving these problems yourself adds no unique value to your product. In that case, you should just use a well-reviewed external ecosystem package.

A large project will run into many of these problems. It is a waste to re-invent the wheel because a cool new framework has too few pre-made wheels.


Lack of libraries, as sibling says. Any libraries that exist are not generally well supported relative to similar libs for popular frameworks. Much smaller community, much less ease at finding others who may have had similar issues. Fewer eyes on, fewer bugs picked up. Fewer contributors, slower fixes/updates. Docs there are tend to atrophy faster.

Developed with Hyperapp on big prod apps about three years; was used to inject small amounts of interactive functionality into existing apps (.Net with jQuery powered frontends). Sorta worked, nice, simple idea, but docs almost nonexistent at the time (to be fair there's very little to it), was in process of being dumped for React just as I was leaving (to work on apps with Elm frontends, which Hyperapp takes a lot from, and suffers from similar issues, heh)


I interpret this as you need to do everything yourself rather than using off-the-shelf libraries.


To be fair, they did make a pretty deliberate effort to warn visitors that the website is incomplete, with some animated text:

> this site is a wip, stay in touch!


Thank you. That's a marquee haha.


So I have extensively used hyperapp (1 and 2) for hybrid mobile applications that run the cab of big rigs. We actually won best in show this year at Freight Waves for our two apps.

These are medium/larger apps, with lots of functionality, need to hook into native device features (done with ionic capacitor, and custom plugins), and need to be fast, robust, and flexible. Hyperapp has allowed all of those things.

Hyperapp can and will work, with larger applications, but hyperapp does not have super strict "guide rails" like other more popular frameworks do, so its up to you to design, and implement a clean code base. It ships with minimum overhead, and you can either roll features you need, or see if someone in the community has created them.

I have worked with angular (1,2,4,6) and react for quite a few projects, and I actually work faster, and end up with a better end product using hyperapp. Its an amazing little framework. Sure, not having stricter guide rails you can write very poor apps in hyperapp, it will let you do stuff poorly, but if you play to its strengths, and get comfortable with it, it really shines.


Hey there, really happy to hear of the success you've had with Hyperapp. I've played with Hyperapp v1 in the past for small toy projects, and it was relatively easy to become productive with. I'm wondering if you have any open toy projects or boilerplate you could share for v2, as I'm looking to jump back on it when I get the chance, and would love to see what a scalable project skeleton looks like.


I do not have anything that is open as of now (but about to start a new project soon)

I would check out https://medium.com/hyperapp/a-walk-through-hyperapp-2-b1f642...

to get your toes wet though, good resource, also feel fee to join the hyperapp slack https://hyperappjs.herokuapp.com/ nice community and super helpful.


Why didn’t you go with Ionic or Stencil? Did you roll your own design?


Bit of a Hyperapp fanboy here, so bare with me.

First, I think Hyperapp can make both small and big applications, opposed to u/PufPufPuf's opinion. A lot of people have this opinion because they are more familiar with v1's wired-in actions, which can become quite unruly. In the latest version, actions are decoupled, and can be organized/extracted however you see fit.

I've made a handful of applications in both v1 and the current released Hyperapp, and they work very well. If you want to see the latest Hyperapp in action, you can check these out:

- A timer for mob programming: https://github.com/mrozbarry/mobtime

- A canvas game, using Hyperapp for dom/state: https://github.com/mrozbarry/smash

- A router for Hyperapp: https://github.com/mrozbarry/hyperapp-router

I have a handful of older youtube videos regarding v1, you can check them out here:

- Intro to Hyperapp (v1): https://youtu.be/uWIyjI8nkz0

- Hyperapp (v1) forms and localstorage: https://youtu.be/qpt6aaMxm1E

- Unit testing hyperapps (v1): https://youtu.be/5wvPUj--HaA

Note, they are outdated, but there isn't much on youtube about Hyperapp in general.

One thing to keep in mind is the naming. A lot of people talk about "Hyperapp" as the first version, and "v2" as the current version, but this is wrong. It's more like "v1" (legacy) and "Hyperapp" (current). It gets confusing, because not everyone is on the same page with that, but this the the naming Jorge (primary author/creator of Hyperapp) has mentioned several times.


> "A lot of people have this opinion because they are more familiar with v1's wired-in actions, which can become quite unruly."

u/PufPufPuf only mentions the lack of ecosystem, nothing about the wired-in actions/etc, so it's odd that you defend v1 vs v2 instead of the lack of ecosystem here. This should probably have been a reply to that thread as well because otherwise it's two very unrelated comments in the list.


Yeah, I should have split things into a reply and a separate thread for the other stuff. That said, I didn't have any comment on the ecosystem - there's definitely a lack of userland things for Hyperapp, and that's for a number of reasons, the biggest being the latest is still in a bit of a transition period from v1, and as a community we didn't think someone would be posting about Hyperapp and make it to the top of hacker news. That really put us on the spot to try and get on here and explain the state of Hyperapp since we're probably more in a release candidate/late-beta situation rather than a full blown release.


( s/bare/bear/ )


You are absolutely correct!


Your mobtime app does not look like it was built with hyperapp, but instead is using ferp.


While the backend (src directory) is certainly ferp, the frontend (unbundled js in public) is 100% Hyperapp.


Someone got inspired by re-frame, I see :) I like the approach. Wondering if there's a way to get ever closer to hiccup (without having to resort to JSX)

Also, letting the framework decide if a function inside the markup should be called or not gives opportunity for more optimizations that go beyond VDOM diffing. That would require an even more declarative approach.

i.e. [h1, {}, [MyComponent, {}]]

vs.

h("h1", {}, MyComponent({}))

If the framework figures out that MyComponent wasn't changed, it can re-use the VDOM nodes.


Yep, there's a feature called Lazy (will be renamed to memo for the official release) that allows you to do just that! :)


Been using this for a while and loving it - it feels like functional programming for GUIs (“describe what you want the end result to look like, and the framework makes it happen” as opposed to “describe what steps to execute”).

I’m pretty sure a lot of frameworks have similar mindsets, but Hyperapp is the one that I found works with the fewest headaches :P (as opposed to eg React, where I spent hours simply trying to untangle the knot of thousands of dependencies before I could get step 1 of the quickstart tutorial to compile...)

As an example of how trivial problems require trivial code:

https://github.com/shish/divetools2/blob/master/src/screens/...

https://scuba.shish.io/#screen=MaxOperatingDepth


I'm a big re-frame fan from the Clojurescript world so this all looks rather familiar. For me it's a great framework and worth learning Clojurescript for.

Seeing the h() function makes me realise how much I miss Hiccup syntax for HTML and your component tree, especially with editor support for parens it's a joy. But it looks nicer than JSX.

I'm going to give Hyperapp a try, I like the small size aspect especially, and familiarity of the overall architecture, my fear is that if you're going off-piste enough to avoid the React/Angular well trodden track on an app, you might as well go the whole way and use Re-frame which is very pragmatic, with JS interop it's possible to do pretty much anything you want. And whilst the type system and compiler of Elm is nice, the slightly more 'infamous' parts of restrictions to JS extensions make it more limited in the real world.


Haven't been using react because of the JSX, but is this really where we are heading? https://hyperapp.dev/tutorial#rendering-to-the-dom

Looks like som obfuscated JS-code..


If I ever need to render HTML from JavaScript, this is my solution, https://lit-html.polymer-project.org/ or tagged templates directly, although I rather prefer straight MVC separation, SSR/Angular/Vue style.


Mithril was doing this exact thing before React became big - it's what we're moving away from (with JSX), not where we're heading.


I wouldn't necessarily say we're moving one way or another. React technically released before Mithril. It just so happens React became more popular and JSX is idiomatic in React. But hyperscript is usually compatible w/ JSX (in fact, in Mithril you can choose whether you want to use JSX or hyperscript)

Personally, I think indentation w/ hyperscript tends to look more natural for large sets of props, e.g.

    h('div', {
      id: 'hello',
      title: 'hello'
      onclick: () => {
        console.log('hello')
      },
    }, [
      // hi
      'hello'
    ])

    // vs

    <div
      id="hello"
      title="hello"
      onclick={() => {
        console.log('hello')
      }}      
    >
      {/*hi*/}
      hello
    </div>
With Mithril's variety of hyperscript in particular there are also some other neat features, such as the ability to pass css selectors as the first argument, e.g. `h('input[type=password].password')` or `const TailwindComponent = '.rounded-lg.md:w-56'; const element = <TailwindComponent />`.


Many projects still predominantly use Hyperscript with the option to use JSX (including Mithril and Hyperapp, and others like RE:DOM, snabbdom to name a few). Even React has an option to use it if you want to skip the JSX compile-step. So I wouldn't say we're necessarily moving away from it.

Personally, I prefer Hyperscript. It took maybe a day for me to get over its perceived ugliness and actually appreciate that it's plain, valid JavaScript.


Going back to PHP and ASP you mean.


Hay! There is some power in being able to bang out a page with <h1>Hello <?php echo "World"; ?></h1>


Agreed, the problem is when that page gets to a book size.


That's why there are components that you put together, so that no one component is very large.


Text templates are the technology for web development. They are so much better than anything else that there's no comparison.

There are some bad templates implementation, and some good ones. The original PHP and ASP are bad. But that doesn't mean templates are bad.


Text templates are a good idea, placing them into the middle of JavaScript code, not really.


I absolutely disagree, but I also feel it's unfortunate that HTML, CSS, and SQL aren't first-class citizens in most languages. It's strange to treat things backed by entire standards bodies and with fully developed ASTs as plain-text.

It seems unnecessarily limiting, and I'm not sure why; For the sake of history? "Division of Concerns"? How is it that using libraries meant for string manipulation upon a standardized format not a concern in and of itself?

The reason JSX, Mithril, PHP's template tags, ASP, Mustache, Twig, etc, exist is because we want to generate HTML - a language that has been standardized for decades - so why are we still playing around with string manipulation tools?


It's an evolutionary constraint. Text templates are initially much more useful than HTML and CSS ones, so people adopt the first, despite a bigger potential usefulness of the later.

The tendency for SQL is even weirder, it's for replacing it with languages that are much less useful for querying data.


We aren't, only those that keep fighting against MVC, HTML Templates and Web Components are.


I do agree with that. But on the case of JSX, it is located inside JS code, but is completely self-contained, thus, it's not as bad.

The original PHP and ASP are really singular beasts, people aren't creating things like those anymore.


What do you consider some of the good ones?


*improving on PHP and ASP


With thing like GraphQL, I get a definite ColdFusion vibe, too.


Worth noting that ColdFusion actually did components before it was cool :-) (I don't mean ColdFusion components which are really just classes in .cfc files, but custom tags which let you write custom markup)

    <cf_menu position="left">
      <cf_menu_item current="true" label="Home" url="/"/>
      <cf_menu_item label="Accounts" url="/accounts" />
    </cf_menu>


We are definitely in ColdFusion territory:

https://github.com/seancoyne/awesome-coldfusion#application-...


> obfuscated

I’ve heard this reaction before when people see hyperscript-like APIs. I don’t understand it. Isn’t it abundantly clear what is going on if you know DOM and JS? What is your suggestion if you don’t like hyperscript and don’t like JSX? Parsing string templates at run-time?


Wasn't the unwieldiness of render functions the entire reason JSX was created?


Not sure of the reason, but it's a godsend comparatively. The reaction against JSX I find to be largely by people who've never actually used it.

If you keep your components small, as is best practice, whatever gut reaction one feels to it (which IMO is misplaced to begin with) is minimized, and quite readable.


If you keep your components small, then using this `h` function instead of JSX doesn't make a lot of difference from readability perspective.

Also, don't forget that `h` is just a function, so nothing prevents you from creating your convenience functions, which allow more concise/readable code, eg:

const div = (...args) => h("div", ...args) const span = (...args) => h("span", ...args)

(or something along those lines)

I've experimented with this approach before (in ClojureScript) and you can get pretty far with it:

https://github.com/enumatech/cljs-abi-viewer/blob/state-chan...

In fact the Hoplon (https://hoplon.io/) framework as already doing this many years ago, even just using the DOM directly.


The same is true of JSX. You can abstract and generalize its components with equal ease.

I agree with another commenter that a lot of the common objections to JSX and React more generally, especially on HN, sound like things that people who've never used it but only seen a few examples would say.

It's a shame, because with a little more experience those people could complain about stuff like how the complex form logic story in React just isn't really there yet, or how you can't really provide a lot of the subtle touches that go into making a really polished form UX without having to wrap an uncontrolled component inside a controlled one and handle all the state interactions manually.

Forms are boring, I know, and everybody hates it when they have to be complicated. But they exist and are used for a reason, and I wish someone with fewer deadlines than I have right now would take the time to really nail down some of this stuff.


I personally never found much inherent value to JSX outside of making it easier to onboard other developers who are already familiar with HTML, or have seen React before. Otherwise, I found Hyperscript easy to read after about a day of using it, and there's no extra toolchain or compile-step required to use it. Plus it's "just JavaScript."


I do rather like JSX, but I agree Hyperscript isn't difficult to read. As I noted in another comment, though, it also isn't difficult to set up a build step, and being able to use JSX is far from the only benefit of doing so.

The point about onboarding deserves more consideration than it receives, too. I'd have an easier time finding good devs to work on a React/JSX project than one in Hyperapp, just because of the latter being unusual.

The syntax isn't so much at issue here; Hyperscript could as well be sugar over React.createElement calls, just as JSX is. Anyone familiar with the DOM can look at it and see what it's doing quickly enough.

What would concern me more would be the underpinnings; Hyperapp brings its own VDOM and ancillaries, parallel to React's, that anyone wishing to work on a Hyperapp project needs to learn to reason about - and that will have their own bugs, infelicities, and performance issues, just as React's does. But React's are generally very well known and not too hard to design around, even if actually designing around them can be a pain on occasion.

No shade on the team, and I'm not trying to turn anyone off the project - I used to be much more of an early adopter until I got badly burned that way a few times, and these are the sorts of considerations that result from that kind of experience. I'll definitely be interested to see how Hyperapp holds up, and what kind of profile it achieves, over the next year or so.


When I'm not using JSX, I often do something like this

    const define = (componentDefinition) => (props, ...children) => isReactNode(props) ? React.createElement(componentDefinition, {}, props, ...children) : React.createElement(componentDefinition, props, ...children);
    const elements = new Proxy({}, {get: (target, tagName, _) => define(tagName)});
    // ...
    const {div, h1, button, input} = elements;
But although I really disliked JSX at first, once I tried it a little, I realised that it's about making the code describe what you want rather than how to get it. That mind set shift is actually valuable, even if underneath it's still turning into function calls.


My big issue with JSX is that it forces you to use a pre-processor and source maps.

If you have to do that anyway, I think I could use JSX instead of "pure" JS.


Setting up Webpack and Babel isn't so bad, these days, and you really only have to do it one time and then you can reuse the setup in other projects.

Plus, once you've done it, Typescript is easy to slot in, and that by itself makes the effort worthwhile.


I can highly recommend you watching this talk: https://github.com/matthiasn/talk-transcripts/blob/master/Hi...

It explains very well why is something being easy shouldn't be the main metric, when choosing some technology.

In this case you are advocating to pull in webpack (28MB, 348 packages from 210 contributors), @babel/core (12MB, 54 packages from 60 contributors), typescript (53MB, 11 packages, 4 contributors), to just mention the most obvious and necessary dependencies, not even mentioning the different plugins for integrating them with each other, test frameworks, linters, IDEs (syntax highlighting and auto-formatting) and of course the mountains of type definition boiler-plate.

100MB+ of dependencies which are all a responsibility to learn, teach, configure and upgrade.

Versus this ~12000 bytes: https://unpkg.com/hyperapp

It's like 6 pages of code on a 2K iMac monitor and none of the above...

I'm not saying that there are circumstances when you might want to put up with all that cost, but have you consciously considered, whether it really worth the overhead? What's missing from hyperapp, which is only present in the 100MB+ deps? Maybe `htm` (1MB, 11 packages, 4 contributors) is a better compromise between bloat and ease of development?

And if you are willing to take on the extra dependencies, wouldn't ClojureScript provide a lot lot lot more benefits? It's also based on the super mature Google Closure Compiler, which supports extremely sophisticated optimization techniques and DCE... Just to mention some recent optimization surprise: https://twitter.com/roman01la/status/1277148232276234240


> [...] have you consciously considered, whether [it's] really worth the overhead?

Yes, I have. The overhead of a React/TS stack is considerably less than the overhead of having to hand-build all the stuff that Hyperapp's 12 kilobytes aren't enough to provide, or that using ClojureScript means very few other engineers will want to work with me to build because I'm doing everything in a language and stack they've never heard of.

> What's missing from hyperapp, which is only present in the 100MB+ deps?

Eleven years! Hyperapp is written in pure ES5, which was finalized in 2009, around the same time PHP 5.3 came out. The world has moved on a great deal since then. (But hey, I haven't had to think about hoisting for like six years now, so that was a fun blast from the past!)

That said, those 12 kilobytes of ES5 code are very concise, for sure. They also implement a virtual DOM and a sugar syntax over element creation and nothing else. To compare it based purely on codebase size, with a stack that provides orders of magnitude more functionality, seems at best very incompletely thought through, and at worst deliberately tendentious - although I'm sure that can't be the case.

There's a lot of misinformation floating around about the modern Javascript world. A lot of that dates from years back, like the left-pad problem, or that builds aren't reproducible - both of which were true at one time, but have long since ceased to be. Or that using these tools makes it impossible to deliver compact, performant code to the frontend - which, again, hasn't been true in quite a while. It's not false to say that webpage bloat is worse than it ever has been, but it is false to blame the tools for that problem.

Of course, I freely grant that it's hard to see these kinds of nuances if you don't have much or any context on what modern Javascript is actually like. What I don't grant is that that ignorance is any kind of worthwhile place from which to pass sweeping comments on the whole field of endeavor.


If you are doing back compat for old browsers, Babel is necessary anyway.

Typescript is a choice independent from anything else.

There are alternatives to Webpack, none of which have gained traction, possibly because developers appreciate other features that webpack provides out of the box.

But, you are complaining about the developer tools, why? The source code size of emacs/vscode/vi is just as relevant, or the size of the linter, or the complexity of whatever build environment is used to deploy code to production.

All of those require upgrading and maintenance, and occasionally have bugs!


> But, you are complaining about the developer tools, why? The source code size of emacs/vscode/vi is just as relevant

I think you have a fair point that if it's not making the build artefacts larger in size it shouldn't be criticized for that.

Where the problem arrives is really about cognitive load: If my tools are emacs/vscode/vi or even visual studio or webstorm, I can use these tools, and come back to them in 18 months for a different project and use the new versions without giving it more than a few seconds of thought.

With Webpack, I am strongly encouraged to use create-react-app to allow for sane creation of new react apps with React/Redux/SASS. But: it's April 2018 and create-react-app doesn't yet support TypeScript, so I have to find somebody's forked version of it that does, but then that forked version doesn't support SASS, so I have to stitch support for that together into my own fork, and then understand it well enough to debug that if it doesn't immediately work.

When I want to make a new app 18 months from then, there is a new version of Webpack, CreateReactApp, etc which finally adds full typescript support, but the way these tools are configured is completely different which itself requires a lot of time and effort to adjust for.

The truth is that the experience of using a developer tool like Webpack is categorically very different than choosing your Code editor.


So...don't use CRA? You don't have to, although it does make a lot of things easier, and it's kind of a surprise to see the claim that Webpack encourages its use. I've never run across anything like that in the docs, and I have found those docs to do a good job of covering how to set up and use Webpack, with CRA nowhere involved.

Or - a much easier tradeoff - just don't use Sass. I mean, Sass isn't without its merits, but if you're already compiling something else down to CSS, you may as well go full CSS-in-JS and get the benefit of a real programming language instead of whatever sharply limited DSL Sass has, that I've totally forgotten about because I haven't needed to touch it in years and I'm honestly a lot happier for that. Yeah, you'll have to look at and vet some new tools, and you'll have to get used to thinking a little differently about how you write stylesheets. But on top of learning the ins and outs of an entire new tooling stack, how much extra cognitive effort is that, really?

There's always going to be tradeoffs. You make the ones that are right for you. And if you find yourself, while investing in a new paradigm, trying so hard to stick with an old familiar tool to the point where it's compromising your efforts to get productive with the new tools - that's a signal to start looking at whether it's time for the familiar old approach itself to be replaced with something that not only composes better with the new paradigm, but, as with CSS-in-JS versus older approaches like Sass or Less, might prove to be a lot better in its own right.

I mean, don't get me wrong, I see a lot of merit in sticking with proven, familiar technologies in which I'm quickly able to be productive. I don't expect I'll ever stop using Emacs, for example, and that's almost as old as I am. Platforms change considerably faster, though, especially in web dev. I started with Emacs eleven years ago, and at that time the frontend "framework" of choice was jQuery - even AngularJS was still a year in the offing - and the closest you could come to a standard backend stack was Rails. But you were more likely to be using something written in PHP, or a hoary old pile of Perl 5, or the like. We've come a very long way since then.

The pace of change has slowed considerably in recent years, I think, and I expect it will continue to do so. But it's not going to stop, and individual tools and stacks will continue to develop regardless. There's always going to be new features, new approaches, better ways of doing things, and some of them are going to be breaking changes. Keeping up with that kind of change, and knowing how to recognize and take advantage of the good, is one of the things it's an engineer's job to do.


> So...don't use CRA?

Sure, I can get by fine without that, but then I've got to educate 2 other members of my team, both who can program in numerous languages but are quite inexperienced with web development, how to correctly set up each project using the React/Redux/Sass/Typescript/Jest. I can do it myself and hand them a project template, but then no-one else will learn how to do it. The reason for CRAs existence is (more than any argument I might make) an implicit acknowledgement that setting up new webapps is a far more painful experience than it should be.

> it's kind of a surprise to see the claim that Webpack encourages its use.

It was React that recommended CRA, not Webpack recommending CRA, apologies for my misleading description.

> Or - a much easier tradeoff - just don't use Sass.

I'm already quite familiar with plenty of reasons to not use -or to use- SASS. The point is that as a tech choice it's hardly a minor player, and yet the experience of setting up / migrating a project using easily recognisable tech (React/Redux/Sass/TypeScript) is a long way from a straightforward. In my example, I already had SASS on existing related projects. My team members were already familiar with it. Create-React-App was at the time was also actually already built to include support for SASS - the problem IIRC was that the fork of CRA that added Typescript support was forked from a CRA version before SASS was supported, so (at the time) it was a "one or the other" situation before I forked it and fixed it myself.

> Keeping up with that kind of change, and knowing how to recognize and take advantage of the good, is one of the things it's an engineer's job to do.

It's also part of our jobs to look at processes and procedures identify areas of inefficiency, and to ask questions about what a better way of doing things would look like.

Finally, the trajectory of this discussion is pretty absurd. I'm offering examples of what happens in web development to illustrate that there is a massive difference between treating developer tools like Webpack / CRA as though they're similar to text-editors that you don't have to invest a bunch of time to understand and keep up to date with (a point that if I'm understanding you right, you likely agree with). My comment above's central claim is: that while critiques on size of dependency chain of developer tool like CRA or WebPack might be misguided, they are hardly lightweight cognitively, and the choice to use these tools (or not use them) isn't something to just take lightly because we clarified that our deployed artefacts didn't balloon in size.


Okay, that's fair. I certainly can't disagree that setting up a new web app in the modern style, from scratch and without prior experience, is cognitively heavyweight, and that reducing that complexity wherever possible is valuable.

I would say that CRA's cognitive overhead, in a situation like that, isn't all that different from that of Rails, for example. They're both trying to do a very similar thing, albeit with very different approaches, and they're both very much of the convention-over-configuration school, which attempts to trade off not having to think very much at first about decisions you may not have enough information to make well, with making those decisions costlier later on once you do have enough knowledge to approach them. I have reservations about that entire school of thought, but despite them, my experiences with Rails and with CRA lead me to think that CRA does a generally much better job with those tradeoffs than Rails ever managed.


The _only_ reason I use webpack and friends are for JSX and Typescript. For me, those two tools are worth the compilation step. Qs soon as it's possible to stop using compilers while still enjoying the benefits of both, I'll dump them from all my codebases.


ah, and the article also mentioned https://github.com/developit/htm which pretty much provides what JSX does, just in a lot less complex way (at the cost of a little run-time)


If you like htm, check https://github.com/zaceno/hyperlit too


Haha, I have spent my fair share of time procrastinating over what a type-safe JSX alternative would look like for React.

The most ergonomic solution (well, atleast for me) has been their old factory API upon which I layered a set of convenience utilities [1]. I have been trying it out in a hobby project and I find the reduction of className boilerplate, elimination of closing tags etc. quite productive. And unlike alternatives like react-pug etc. I don't have to compromise with type checking of attributes.

I'll probably release it as a library after doing some performance evaluation and if needed, wrapping it in a babel-macro [2] that eliminates the runtime overhead.

--

[1] Example in CodeSandbox: https://codesandbox.io/s/pedantic-shape-lq9q9?file=/src/reac...

Code in github gist: https://gist.github.com/lorefnon/53377e4d6a6b13adbcfa155f486...

[2] https://github.com/kentcdodds/babel-plugin-macros


Elm defines separate functions for each element type which in js would look like

    view: () => div({id: "app", class: "container"}, [
      div({class: "filter"}, [
      " Filter: ",
      span({class: "filter-word"}, "ocean"),
      button({}, "\u270E")
    ]),

I'm admittedly used to this from years using Elm but to my eye I'd far rather use this than JSX.


100% agree, that's exactly what @hyperapp/html package attempts:

- https://www.npmjs.com/package/@hyperapp/html


that is pretty much how React looks like after JSX is compiled to "pure" Javascript.


Thank you! This is exactly the kind of feedback that we need to improve our presentation. I might just update the tutorial to use @hyperapp/html [1] instead.

[1]: https://www.npmjs.com/package/@hyperapp/html


Please don't. Not everyone uses these additional libraries or preprocessors, and it was a big hurdle to figure out what was actually being generated behind the scenes in the v1 docs.

A good approach is to show us what we need to do with no other dependencies (i.e. just as you're doing now with this h() function), and link to alternative syntaxes/libraries that may be optionally used instead.


Thank you for the feedback. I'll keep this in mind too. I'm definitely not advocating JSX usage. I favor hyperscript myself, but I understand it's an acquired taste.

Idiomatic JavaScript alternatives that don't involve compilation include:

- https://github.com/zaceno/hyperlit, and the aforementioned - https://www.npmjs.com/package/@hyperapp/html


the tutorial is great this way. it's gradually introducing concepts and shows what's possible with very few building blocks. at the end, it would be nice to mention that at the cost of some extra code and learning a few more functions/concepts, you can gradually make application code either more concise with @hyperapp/html or having a different aesthetic or more familiarity - similar to JSX - with htm or the hyperapp-tailored variant of it, hyper-lit.

but please keep the current didactic of piecemeal introduction of concepts, providing clear reasons for their existence!


A nice flourish would be to have every example with both, and have a global switch to pick which one you prefer.


JSX evaluates to code that looks like that anyway. Not sure why we’d want to go backward on this front.


htm [1], mentioned in the paragraph that you linked, is a very clever alternative, similar to jsx but in pure javascript

[1] https://github.com/developit/htm



In the tutorial it says: "In this tutorial we'll stick with `h` to keep it simple and close to the metal." I'm pretty sure they put that in there just to aggravate the HN crowd.


There's a a JSX-like ttl for Hyperapp too, check it out:

https://github.com/zaceno/hyperlit


I think they use "Close to the metal" as a way to say "Less abstractions"


The `h` function isn't too bad to read if you keep small/manageable components. Obviously, any component, whether JSX or something else, with enough content in it, becomes quite hard to read.

Personally, I like using `h` over JSX - JSX can be nice to read, but for people that don't know how it works behind the scenes, it makes things look like magic.

Once you know how Hyperapp works behind the scenes, it's much easier to make the decision to JSX if that's something you care about when developing. I have the same opinion about React, and other libraries that have a strong preference to JSX over their native/function implementations.


Or it’s a joke? Assume good intentions


You might find using htm with hyperapp useful: https://www.npmjs.com/package/htm


Just use https://preactjs.com/ and call it a day


What are the caveats? Why doesn't everybody use preact instead of react?


There’s not many. I used it for several years on theoutline.com and it was great


I have built https://gridjs.io on top of Preact. It's pretty stable and the API is very nice. Supports most events/callbacks that React has (nothing against Hyperapp though)


there's a valuable comment if I ever saw one


This.

I like how HyperApp takes this to another level, but the ecosystem of Preact is simply better.


I love it, but I actually stuck with version 1, which was way more intuitive for me.

Just a side note, I'm not fulltime front-end, so keeping up with modern frameworks is out of my capacity.

It's great for smart components to my standard multi-paged systems, but I used it even for small PWA applications.


I resisted the change to v2 for a long time. In the end I found that v2's state management is much better, so it might be worth a look for that alone.


I read about it but it just did not click as V1 did. Also I will not rewrite old code just for sake of change and I want all system to be on same framework if possible. I may actually do my own fork where only difference will be passing root state and root actions in addition to partial ones, which will fix great amount of issues I have.


Agreed.

The lack of lifecycle events in v2 complicates things a great deal for seemingly no reason. Subscriptions and Events are similar enough that they could have become a single thing, instead of having two highly similar but not-quite-the-same things to grok. The tuple syntax it uses is very strange coming from v1.

I wish I could call it a strict upgrade instead of saying "some things are worse, but other things are better."


It's my fault for not fully understanding the functional universe I was getting into when I first started working on Hyperapp. The latest Hyperapp is more strict, but it's all in good measure. Lifecycle events are impure, that's why they're no-good.

I can tell you that Hyperapp is not for everyone. If you want to write pure, immutable, functional JavaScript and think hard about client side app architecture (unidirectional state management, controlled side effects, toggleable subscriptions), then you'll love it. I also suggest looking at Elm while you're at it.

If you are looking for a more accommodating, meet-in-the-middle kind of approach where you can mix programming styles, you might be better served by, say, P/React.


If we talk about functional API, did you consider providing a push method, like with a Promise, to express the updating of an effect or a subscription ?

(the function 'update' in the code below)

  app({
    init: 0,
    view: state =>
      h("div", {}, [
        h("h1", {}, state),
        h("button", { onclick: (state, event, update) => {
          window.setTimeout(() => update(state => state - 1), 1000);
        } }, "subtract"),
        h("button", { onclick: state => state + 1 }, "add")
      ]),
    node: document.getElementById("app")
  })


We built it into the framework, if you happen to be familiar with Elm, this should make sense right away, but here's how you'd write something like that using Hyperapp:

    import { h, app } from "hyperapp"
    import { delay } from "@hyperapp/time"

    const Decrement = (state) => state - 1

    app({
      init: 0,
      view: (state) =>
        h("div", {}, [
          h("h1", {}, state),
          h("button", {
              onclick: (state/*, event*/) => [state, delay(100, Decrement)],
            }, "subtract"
          ),
          h("button", { onclick: (state) => state + 1 }, "add"),
        ]),
      node: document.getElementById("app"),
    })

See how you never actually called setTimeout as that would be a side effect.

Instead, we have "controlled effects" in Hyperapp. This `delay` function doesn't even call setTimeout itself, but return an object that tells Hyperapp how. Just like how `h("button")` or `<button>` with JSX doesn't actually create a button, but an object representation of it.

Finally this part: [state, delay(100, Decrement)], only placed here for convenience (as you'll usually want that in its own action) is how you tell Hyperapp to do the effect when the button is clicked. This is the same (model Cmd) continuation pattern used in Elm.


I'm familiar with Elm but i think the model of Hyperapp is better than the [state command] pattern. This is how i see Hyperapp, the event part of Hyperapp is not about commands, it's about transition functions, functions that takes a before state and returns an after state. Hyperapp doesn't let the user to control the state by itself.

But there is worst, the problem with the pattern [state command] is that it doesn't work well with async method, because at the time the command is called, the state which is passed alongside the command and the state maintained by Hyperapp may be different.

With your example, the issue is that Decrement may be called on a previous state and not on the actual state.

The idea of the updater is to provide the function that takes the transition function as parameter, so delay will be written that way

  function delay(updater, timeout, fun) {
    window.setTimeout(() => updater(fun), timeout);
  }
If you want to decrement the state after a delay using the state at that time

  h("button", {
    onclick: (state, _, updater) => delay(updater, 100, Decrement),
    }, "subtract")
(from the Hyperapp perspective, the event listener return undefined so you don't have to update the state at the time the event listener is called)

and if you want to decrement the state using the state at the time the user click

  h("button", {
    onclick: (state, _, updater) => delay(updater, 100, _ => Decrement(state)),
    }, "subtract")
The other benefit is that because delay() takes an updater as first argument, it's clear that the function delay does a side effect. Conceptually, the idea is that instead of trying to hide the side effect, you make it clear to the developer (more like Haskell does).


My example actually has no issues, but [here is an example][1] so you can confirm that. I included the implementation of `delay` there as well so you can also see what happens behind the scenes.

---

So, in Hyperapp there are no async/await functions. Or Promises. Can't use functions that create side effects. Can't use setTimeout, setInterval, new Promise, fetch, add/removeEventListener, etc.

delay(100, Action) looks familiar to setTimeout, but it's just a function that returns an object that tells Hyperapp what to do. It doesn't do anything by itself. You can write your own delay function too if you want as long as you give Hyperapp what it wants.

The state becoming stale is never an issue in Hyperapp, because you get a fresh copy of it inside actions, which is the only place where you can "update" the state.

[1]: https://codesandbox.io/s/hyperapp-minimal-counter-with-effec...


Thanks for taking the time to explain me how it works. So you're right that you can not use a previous state.

And if i want to get the dispatcher directly, i can write a helper function

  function effect(fun) {
    return state => [state, [dispatcher => fun(dispatcher)]]
  }
and use it to access to the dispatcher/updater

  h(
    "button",
    { onclick: effect(updater => setTimeout(() => updater(Decrement), 1000)) },
    "subtract"
  )
Thanks a lot !


Basically, yes!

In practice, we don't advocate users to reach out for dispatch, as Hyperapp intends to provide all the fx/subscriptions building blocks you need to create the right abstractions and stay within the safe, declarative side of things.

The reality is, though, that crafting these building blocks takes time and thought, so we don't have them all yet. But people in the community have created fx/sub libraries that are already available, see e.g. this one: https://github.com/okwolf/hyperapp-fx that

Cheers!


I haven't done a great job at explaining why the current Hyperapp is superior than its previous incarnation, but V2 isn't officially out yet, so I encourage you circle back to it when it is.


I've used this for building the browser extensions for my app [1].

It is simple, easy to understand and easy to reason with. However, I would recommend this only for small apps. As soon as your app's features/complexity increases, you end up writing a lot of biolerplate code that libraries like Vue or Preact already handle you for.

[1] https://www.emailthis.me


I haven't used Hyper but I'm looking for something to use for a browser extension I'm making.

I'd love to hear what kind of boilerplate you had to write that Vue or Preact handle. It can be hard to see these gaps ahead of time so I'd appreciate the benefit of your experience.


Curious to hear what boilerplate you think Vue or Preact already handles for you.


Your open source browser extension framework was really helpful to me a few years ago!


Glad you found it useful.

I had sort of neglected it for a while, but during the course of the lockdown, I have started working on a major rewrite - replacing Gulp with Webpack, adding support for Edge, etc. Will release it soon :)


To me every JavaScript framework feels to me like it wants to reason about components as data, ala Hiccup: https://reagent-project.github.io/


Reagent is amazing, thank you for sharing it.


Does modern web development just completely abandon the idea of "separation of concerns"? Looks like content is freely mixed with markup and logic and results in a horrible, difficult-to-read mess of code.


The idea now is not to separate thing by file type (all .js go here, html goes there) but to separate by logical components, thing that work together, go together.

I guess it's like working in vertical slices of related logic rather than layers with logic and layers with markup and such.

That has its problems tho, that for sure.


There has never been any separation of concern in web development. Just because you put your scripts, HTML and CSS in different files doesn't mean they are separated.


Isn't that the definition of separated? If you want to edit content or markup, you open the HTML file. If you want to edit business logic, open PHP or JS. And so on.


Yeah but then your JavaScript spews out unholy tendrils that mutate the DOM and dynamically add/remove CSS classes and style attributes. Separating HTML/CSS/JS made a lot of sense for web sites but separating by component makes more sense for web applications.


They are still tightly coupled.


IMHO, yes. This is why some folks (like myself) find it hard to wholeheartedly embrace JS for building entire apps.


What code are you referring to? Hyperapp has clear separation of presentation, logic, and side-effects. Of course, developers can choose to keep that a clean and distinct separation, or let a bunch of code inter-mingle.


It seems that scrolling is somewhat broken. Scroll position under one route affects position in others.


That was enough to make me not consider using Hyperapp.


Yeah, the site is a WIP, but that should be fixed soon when V2 is officially out.


How is it 2x faster than react? Where does this claim come from?


A lot of other frameworks/libraries are faster than React. I know React used to be touted as the fastest option, but the reality is that it isn't.


Probably from here: https://krausest.github.io/js-framework-benchmark/current.ht...

Hyperapp does outperform React in most benchmarks (along with many other frameworks). Not sure how the "2x" was measured, though.


At 1.7K I'm not surprised by this, and I'm not sure why you would be. React is plenty bloated, not saying it's badly coded, but it's a larger codebase than many other SPA frameworks. This one in particular seems to be using as much of native JS code as possible.


How much faster is vanilla DOM API calls compared to all other transient DOM API abstraction libraries?


Haven't seen the numbers but in most benchmarks React.js isn't the quickest.


Just shows a blank page without JavaScript. Does Hyperapp have any way to render out an HTML fallback if JS doesn't load?


That's an issue with the site that'll be fixed when Hyperapp is officially released.


Dang, I registered hyperapp domain because I thought it was a good name and wanted to build something cool there. Like all side projects it’s not about the idea but the execution. I’ll put this in my bin together with slackday (Should have registered slack:)

On topic: This looks interesting and I Will be giving it a try. Well done!


Do you happen to own hyper.app?


React was made in 2013 and is pretty old at this point. How does Hyperapp compare to current tech like Svelte?


This deserves a much better answer, but I'll just say this for now. Svelte is declarative/imperative (but mostly imperative) and also not based on functional principles. React is definitely more on the declarative side. And Hyperapp is essentially Elm in JavaScript, so it's as declarative/functional/immutable as the definition allows for.

Maybe the person that said Svelte was more declarative was only familiar with an older incarnation of Hyperapp that wasn't completely based on functional principles, or maybe they're using a more loose but inaccurate definition of declarative (kind of like how people often say "theory" when they actually mean "hypothesis").


What do you think the advantages and disadvantages are? I remember briefly looking into Hyperapp and mostly liking it, but still wasn't sure which JS framework is the best choice (the other one I liked was Vue).

Some time after that I learned about Svelte and very quickly concluded that this would be my choice, everything just feels right about it. For the record, I've only done a small project in Svelte.


That's fine. If you're already happy with Svelte, I encourage you to explore more with it. Try building a couple of non-trivial projects and keep learning about your craft. If you're also into computer science, I recommend you look into functional programming if you haven't done so yet. Then look at Svelte again. Try React too. Check out Elm.

I can tell you that Hyperapp is not for everyone. If you want to write pure, immutable, functional JavaScript and think hard about client side app architecture (unidirectional state management, controlled side effects, toggleable subscriptions), then you'll love it.

If you are looking for a more accommodating, meet-in-the-middle kind of approach where you can mix programming styles, and don't want to think much about those things I mentioned above, then React, Vue, Svelte are all great choices.

V2 will be released in a few months, so do circle back to Hyperapp then to see how you like it again.


what else is missing other than docs? in hope you won't remove the current state, just because you don't consider it released yet :)


Finish the site and docs, merge the minimizations branch (has memory performance improvements, and brings it down to 1690 bytes gzipped / 1528 bytes brotlified total), add tests, then we can officially proclaim V2.

Definitely not planning to remove the current state or anything haha.


Svelte is more declarative. Svelte is also a compiler, which generates very efficient code for keeping the dependent parts of the DOM up-to-date when the app state changes, effectively moving the vDOM diffing cost from runtime to compile-time.


When last I checked, Hyperapp was basically the elm architecture implemented in JS, a gateway drug.


I had the impression it was the other way around.

People starting with Elm, love the idea, but not the ecosystem, and come back to JS in the end.

That's how Redux was created.


I wish people would stop demonstrating new languages or frameworks using fonts with ligatures.

"Surely, you couldn't use an actual arrow here... right?"

I find myself having to copy and paste the text to find out for sure.


Love the website aesthetic!


This page does not inspire confidence in the framework.

I don't need a non-ui piece of software to have the slickest site... but no lorem ipsum please.


I put it there, so I apologize for it. We were in the middle of a rewrite while working towards the official V2 release and weren't expecting to be on HN right now haha. Thanks for chipping in!


Ouch. that's rough.

I've seen some incidents before where backend frameworks were posted before they had things like authentication ready.


What are the difference with Mithril.js? Both seems to embrace the same philosophy in almost the same way. Or am I missing something?


They're similar, but Hyperapp is purely functional and more comparable to Elm.


I love hyperapp! It has very few concepts to learn, and the source code is less than 500 lines. Sadly its ecosystem is non-existant.


Just another transient DOM API abstraction library


Almost like the DOM Web API isn't useful for its intended purpose anymore and should be replaced or built upon to avoid all this abstraction churn. Why is simplicity the enemy of the Web APIs? Why is everything useful left to user-defined dependencies? Are the spec creators even checking to see what their code looks like when people have to cobble it together to create something useful? I suspect they are NOT.


The DOM API is useful and usable. Oh and software built on it is maintainable because it's a standard. Software "devs" toiling about with their transient libraries are writing code that goes unmaintainable once the "next new thing" comes out and all the sheep flock to that. The spec creators are the only ones with logic and rational in the whole web dev "ecosystem"/culture/whatever.


Hyperapp only makes sense if you want to write immutable, purely functional SPAs in JavaScript. There's no Web API or native abstraction for that. And if your site was only content, then I'd say why even bother with JavaScript.


Okay, so there's no Web API or native abstraction for what? Immutability? There is, but it's somewhat semantically obtuse to express natively with Object freezing, not even to mention some other variably-efficient jiggery-pokery with proxies or something (or maybe there's a new language feature for this that I've forgotten about, so many after all, or was it a proposal?). Purely functional single-page application: oof, such a mouth-full. Can mean so many things too. So this entire new abstraction is for a front-loaded SPA?

Maybe the Web should be reinvented, slightly at least. Maybe it would be a good thing if Web Assembly in conjunction with HTTP3 or something akin to it ate the whole beast, ecmascript and all.


Just saying "purely functional SPAs" was lazy, but it's usually enough to convey what makes Hyperapp different from other frameworks like React, etc. Let me try harder.

There's no native API for representing apps as finite-state-machines (Moore style) [1]. Admittedly, we could do a better job at explaining why you should care.

Hyperapp actions (Elm messages) correspond directly to FSM "events". Hyperapp effects (Elm commands) correspond directly to FSM "actions". The "single-global-state" corresponds to the fact that an FSM is always in just one of a number of "states".

Hyperapp is FSM architecture for JavaScript apps.

It is also bundled with a VDOM implementation optimized for immutability, e.g., you must derive your UI from the state, can't produce uncontrolled side effects, and can't use traditional DOM events, instead you think of every UI interaction as a state transition.

One more cool thing about Hyperapp is subscriptions. An abstraction to toggeable event streams: think bidirectional effects, e.g., global mouse/keyboard events, time, animation frames, geolocation.

[1]: https://en.wikipedia.org/wiki/Moore_machine


> can't use traditional DOM events

Wtf are you doing man?


Can't use DOM events to create side effects. What we do is define UI interactions as state transitions. Transitions allow you to say [nextState, myEffect] to update the state and create a "controlled" effect (just an object representation of a side effect, very much like how VDOM uses objects to represent DOM nodes). Effects in Hyperapp are the same as Elm commands.


I hope not! :)


Blank page when JS is disabled. :/


How does this compare to Stimulus?


Stimulus is not so much concerned with rendering HTML. Hyperapp is almost exclusively focused on rendering HTML and client side application architecture (state management, controlled side effects, subscriptions).

It's more comparable to Elm than React, Vue, Angular, Svelte, etc., since it's based on functional principles and you can only write pure, immutable code.


Now it looks like Elm


Exactly! And the latest version (which is not officially out yet) is even closer to Elm that the first version ever was.


Looks like mithril


so.. a lighter react?


Preact would be the lighter React. Hyperapp is more comparable to Elm.




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

Search: