122 comments

[ 2.8 ms ] story [ 386 ms ] thread
That is really ugly code.
For me HN is a great reminder that done is better than perfect.
More like, "It kinda works, we don't give a crap".
as it should be

think about all the other things perfectionist coders and product managers could be working on

Yep, and they could easily find volunteers to improve the site (make the login page look nicer, maybe even implement 2fa) but there's no incentive to improve
That's not nice. I don't mind if you diss our code. But I do mind if you say we don't give a crap.
OP here. Dissing was not the intention of my post, if I can help in any way to improve HN let me know, would be more than glad to do so. Peace!
Solving a real problem with clarity and simplicity of use by knowing your target users is far more important than clean code. However, in the long run, you need good code in order to keep doing this.
Clean code is something you should arrive at through iteration rather than a minimum acceptable requirement to put something in production.

In general I would like to achieve the functional goal of the present in the most expedient way possible. If cruft and technical debt from being expedient yesterday is slowing me down, it's time to refactor.

Trying to write perfect code from the start is a fool's enterprise. Often times the full requirements and constraints of a problem will not make themselves known until you're halfway done solving it, or until you're on to the next related problem. Front-loading architecture and software design work often means solving problems you don't really have, or painting yourself into a corner when it turns out the problem is not exactly what you thought it was.

I definitely agree with that. If you look at how HN does any individual thing, it's almost always "wrong", but it really doesn't matter. It's become (and stayed) a thriving community for over 10 years anyway, and almost nobody knows or cares how any of it works.

My favorite example is probably how the "AJAX" voting works: when you vote, the Javascript creates a new <img> tag with the src= attribute set to the vote endpoint, so when the browser tries to load that "image" it does a background request.

It's the kind of dirty hack that hasn't been necessary for an extremely long time and could be replaced with a proper method in minutes, but nobody even notices that's how it works.

Screen reader users might disagree with you.
Done is only better than perfect because you can't have perfect.

You can still often have better than done, though. The first working implementation is rarely the best possible one.

> There is also a GET request to https://news.ycombinator.com/collapse?id=1234567 to save the state of the collapsed/expanded comment if the user is logged in, but it's an async request so it doesn't have an impact.

Is this a correct place to use 'GET'?

It does modify state on the server so I would think it should be a POST or something.

even better, they could do what reddit does with upvotes/downvotes, and store that information in the user's cookie, so that it gets sent with the next request to the server.

I never realized Reddit did that. That's a really cool hack; like a poor man's version of Background Sync[1]. I guess the disadvantage of using cookies is that if you just click to vote and then close the tab, your vote might not be recorded for a long time.

[1]: https://developers.google.com/web/updates/2015/12/background...

That's a pretty big downside.
They probably figure that with the amount of clicking on threads that people on reddit do that the site will capture almost everything except for that very last page you upvoted on before you closed the tab and went to bed. However, you're probably getting on reddit soon anyway and the votes will be counted then.
It's fine for Reddit's purposes. Randomly losing 10% of voting interactions wouldn't be a big deal for them. Of course, that wouldn't be ok for many other applications.
I'm pretty sure they save it in the cookie and fire off a POST at the same time in an async thread and then don't check if the request succeeded. That way it's a backup if you're on crappy internet or the server was down or something.

The cookie isn't the only way the vote gets there.

Should be a PUT as the operation is idempotent.
Man that gave me some ideas regarding some users I have who have crappy internet connections ....
>Is this a correct place to use 'GET'?

Not at all; GET requests are specified [0] to not cause any modifications to the resources (aside of meta-data like logging etc.). It should also be 100% safe for web spiders to issue any GET at any time [1], server overload aside.

I presume it's an artifact of earlier implementation -or just an idea- to have the collapse work without JavaScript. It would be doable with a normal A HREF with the current link format of https://news.ycombinator.com/collapse?id=20336970

--

[0] "In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval." - https://tools.ietf.org/html/rfc2616#section-9.1.1

[1] in the early day of the internet, a friend lost most of his CRM's content because he had record deletes implemented as A HREF issuing GET requests. Having learned the lesson, he instead turned to JavaScript code issuing GETs...

The weight of a well used ellipsis...
The 'logout' button is also a GET request.
I thought that the normal way to have this work without JavaScript would be to have a form tag with the submit button styled to look like the collapse button.
with get you can also have multiple inserts when some network things break. because get requests might be retried.
why not store this state client-side?
I might visit Hackernews using multiple user-agents.
is cross-session comment folding really that important/neat?
Yes! It's subthread "marked as read" or "hide".
I would say it's more important than caring if something is a GET or POST on the backend.
then why not do it client side and bundle state saving later.
Isn't that vulnerable to CSRF? What if a page linked on the front of HN makes a request collapsing every single comment?
One of the top posts in the history of HN was a link that upvoted itself due to this issue.
Yes, but you need a token to log out. For collapsing comments it should work though
correction: same origin policy, so it doesn't work
SOP isn't relevant here - it relates generally to _reading_ content from another origin.

What is relevant here is whether the cookies are SameSite and/or whether a token is required.

Following the rules of REST is very important if you are presenting a public API to the world. If it's your own server you can do whatever you want. For example I used to work on servers for games and often there would be a single endpoint for processing one or more commands, and this would be technically a GET request regardless of what those commands did. Furthermore it's common to send application level error details with a 200 status code; i.e the http level transaction succeeded but the application layer produced an error. Much heated discussion emerges around these design choices :D
As you say it will work just fine as long as your client and server agree, but free-wheeling it with the HTTP spec can come with operational drawbacks.

I've worked with a lot of different internal webservices as a freelancer, and if they're reasonably RESTful and built according to spec, it's easy to just get started with the codebase. Ones like you're describing mean a lot more conversations and reading through code.

Of course it depends on the nature of your team and how often you on-board, but to me the HTTP spec is one of those things like following coding style conventions: sure you don't need to do it, but at the end of the day it's not that much more work once you're in the habit, and it makes it that much easier to work with other people.

I absolutely agree with your points, and that's good advice as long as your application works by modifying resources of a single type with each request. In my specific case we wanted to reduce round trips to the server by using compound commands that may do multiple things on the backend, affecting multiple entity types that would have to be, in rest, a resource. Also in our case my team was responsible for the client and the server, and the commands/responses are clearly documented for everyone to see.
> If it's your own server you can do whatever you want.

This is not at all true. For example, say I'm a user in a dorm that uses a proxy that I have no control over. If you make your GET request modify things, that proxy may cache the request, or worse, may repeat the request later to maintain its cache.

My point is, you don't know what is between your server and their client, and even well behaved infrastructure will sometimes make or modify GET requests on your behalf, but won't do that with POSTs.

It's also an issue when you don't even fully control the client, which in this case is the web browser. A game at least behaves exactly as you program it. Browsers are not necessarily consistent, especially when you throw in extensions.
Yes excellent point. Some browsers/plugins will prefetch every GET on the page to speed up browsing.
Some browsers also show a "here's your top 10 most visited webpages" shortcut when you make a new tab, which does a GET. I ran into that one when I was being lazy about building/testing an API.
In the Hacker News case there isn't a GET request on the page, it's triggered by the javascript so this would not happen
There are ways to make sure that your GET requests are not cached. For example in the case we're talking about here the server sets that URI to have "Cache-Control: private; max-age=0". Now sure, a proxy could simply ignore HTTP protocol and cache it anyway, but that would break a lot of things and AFAIK is not seen often in the wild. Certainly in the case of the applications I worked on we did not have customers that reported connection difficulties over HTTP.
Or just use my Greasemonkey/Tampermonkey plugin which disables the Hackernews collapsible comments and introduces its own collapsible comments logic, which is much faster and has a variety of convenience features:

http://mental-reverb.com/creations.php

The slow behaviour is mostly noticeable on mobile Chrome, but will have a look, thanks for sharing.
I am just now realizing that HN comments are collapsible...I wonder if anyone has ever looked at upvote/scroll behavior when the collapse button is used vs not? There are a ton of threads where the top comment is also a non-sequitur, but I know when that happens I frequently don't scroll past the hundreds of replies to see what the other first level comments are.
Okay. I'll bite. What is everyone talking about ?

I see an upvote triangle, a down vote [-] and nothing else. Is this a mobile only thing ? I can't see a way to collapse comments under Chrome or Safari on a desktop.

I am out of the loop what's the secret ?

I would use the <details> tag to solve this problem. Most people don't know this exists and I have no idea why. You would probably have to rewrite the html so it no longer uses tables but I don't really consider that to be a negative.

I would also question why we are saving collapsed comments. I feel like this is something that doesn't need to be persisted forever. If you want this behavior why not use local storage instead?

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/de...

This is awesome! I had no idea! You're right, I don't think most people even realize. There's often times I get upset when using Bootstrap or just doing CSS and look up ways to do specific things and don't find out of the box solutions, this is one time I'm glad I found a decent alternative. One case that comes to mind is collapsible trees and dropdown boxes where you can type / search on them, and anything with dropdown boxes like checkmarks gets a wee bit hacky.

Note that it's not yet supported by Edge: https://developer.microsoft.com/en-us/microsoft-edge/platfor...
Edge is turning into Chromium soon, so that shouldn't be a problem for much longer.
Considering there are millions of people still using IE11, I'd say it will continue being a problem for a long time.

18% of my users are on IE11. Some industries (healthcare, for example) don't change if they don't perceive something to be broken.

Doesn't Edge auto-update though? How easy would it be, as someone in enterprise IT, to keep users on an old version of Edge?
The reason is active-x, somebody wrote a way to scan with active-x and now virtually every healthcare web app works that way.
This was before webcam support was mainstream in browsers. Capturing stills from ultrasound is in many legacy systems still done with a TV capture card and the really old legacy cards don't even use any standard API but carry their own driver so you can't use them as a webcam but need the vendor app.

source: did support for a doctor some years ago

Edge isn't IE11. They are both installed, side-by-side, on Windows 10, and IE11 is the only one that ships on Windows 7.
In healthcare, the most common EMR systems (Epic, Cerner, Allscripts, etc) use IE11 in iframes as the platform environment for 3rd party applications embedded in their UIs. So convincing a few large vendors to upgrade would make a huge difference, but the hospitals themselves don't have the option of upgrading some of those browser environments. (My company makes apps that run in the EMR platforms)
To be fair, if we're staying in the parameters of the thought experiment, we're targeting the HN user base, which I suspect isn't using IE11 at nearly that rate...
Hmm, that's cool, I don't know how I've never heard of this before. Probably much better than some more-expensive CSS or Javascript.
Persisting it on the server allows users to browse on multiple devices and keep their collapse settings in sync. This is useful in particular for long threads of comments, where collapsing can be used as a tool to keep track of progress through the thread by collapsing comments along the way.
FWIW, you can still do this with the `<details>` tag, though. Have the page background-sync collapsed statuses back to the server and have the server remove the appropriate `open` attribute from collapsed `<details>` on subsequent page loads.
That sounds like a solution in search of a problem tbh
Sure I get that this is possible given that you know this is what the code does but the bigger questions are who knows that you can do this, and who actually uses this feature?

Is this the expected behavior when you collapse or show a thread? I would suggest that it is not, as most minor interactions on a page are only stored locally.

How many people actually use this feature? In order get a benefit from this feature you have to be logged into hacker news on multiple devices, collapse a thread on one device, come back to that thread later on the second device and then continue reading from where you left off. Alternatively you can just scroll past the stuff you've already read, which has a minimal cost to the user.

The benefits seem negligible for the amount of developer time that likely went into making this feature.

> you can just scroll past the stuff you've already read, which has a minimal cost to the user.

Both vote count and age influence the order of comments, which means that the stuff you've already read may appear below stuff you haven't read yet.

If you use the feature at all, I'm not sure why you wouldn't want collapsed comments to be in sync across devices.

> Sure I get that this is possible given that you know this is what the code does but the bigger questions are who knows that you can do this, and who actually uses this feature?

I do.

> In order get a benefit from this feature you have to be logged into hacker news on multiple devices, collapse a thread on one device, come back to that thread later on the second device and then continue reading from where you left off.

I actually do exactly this. I read on my phone/laptop and later come back to the same thread (when more people have commented) on my home computer, usually at the end of the day. Having threads of conversation that you are not interested in already collapsed on multiple devices is very useful.

> Alternatively you can just scroll past the stuff you've already read, which has a minimal cost to the user.

Scrolling and quickly scanning over multiple threads is more time consuming and becomes actually annoying if you just want to passively follow a thread. If you want to follow multiple threads under the same topic, you either have to remember unique words/usernames/dates of that thread or resort to scroll & scan method mentioned above. One is annoying, the other is simply non viable for N amount of threads.

Until there is a way to subscribe to a thread, this feature is super helpful. Its actually just as good or better than a subscribe mechanism because atleast you can avoid getting multiple notifications for every single comment that get posted in the interesting thread. In the current scheme, all the irrelevant ones are already out of your way.

Actually i use the collapse feature for totally diffentent use case: Navigation.

I don't want to scroll over all the replies just to find the next post or i want to see all replies to one post. Therefore collapsing is convenient, but the slowth is annoying.

> If you want this behavior why not use local storage instead?

My guess would be that the decision was made before a standardized, widely available cross-browser implementation of localstorage was a thing.

I looked into using <details> to handle collapsing comment threads on Tildes, and ended up deciding it wouldn't work well and just went with JS.

It was a long time ago now so I can't remember much specifically any more, but I think that the styling and behavior for <details> were both too limited and too inconsistent across browsers.

I do use it in some other places though, like collapsing/expanding the text of text topics from the listing pages, and it works really well for that (other than the current lack of support in Edge).

I like the saving collapsed comments feature but past 7 days, I would not care if the server forgot about them because I usually never go back to posts 7 days or older
> You would probably have to rewrite the html so it no longer uses tables

This reminds me: What happened to the markup rewrite that was announced almost 5 years ago together with the Firebase API? https://blog.ycombinator.com/hacker-news-api/

As far as I can see the markup never changed after all.

Didn't know about <details>. I was actually working on a site that uses threaded comments recently, so I might consider using it.
> I would also question why we are saving collapsed comments.

I can't be the only one who had no idea it did this? And if so, I'd could argue that there isn't really a need for it.

I would absolutely vote to do comment state saving in local storage. The need to have synced collapsed comments across devices is pretty minimal, compared to the performance increase that everybody will experience.
Removing a feature few know about for a small increase in performance for some?

Now that everyone knows about it people will start using it and people will start noticing the slowdown.

Somethings are best not mentioned

Holy heck. I always wondered why there wasn't a tag like that. Thanks!
I tried ctrl+f on text inside collapsed details and it didnt show up. I would have expected that with correct semantics, the browser would have figured out that it should expand the details and highlight that text.

Its also missing a group name, so I can expand only one details of a group.

Why is it useful?

This is a really good point. The lack of searchability of the collapsed text makes this pretty useless for comments. Please consider this when thinking of using it anywhere.
I cannot visually notice any delay. It seems instantaneous in my browser.
Same. I am really picky about performance, and I've never seen anything but instantaneous response from collapsing comments. I just tried it right now on a few example threads from the home page and confirmed that it's instantaneous. I would estimate less than 50ms. I can rapidly click a + and - and collapse/expand a comment tree more or less as fast as I can click (the limiting factor being that my browser wants to select the + button itself as text).

For whatever it's worth, I use Firefox on Windows. But I just fired up Chrome and gave it a test, and I see the same thing there. But I don't do a whole lot of HN comment browsing on my mobile device, so I suppose that's the difference.

I've only noticed on mobile
It's really only an issue on mobile when you're collapsing larger threads. Try collapsing the first comment in this thread, for example: https://news.ycombinator.com/item?id=14656945

Not terrible, but there's a noticeable (maybe ~1 second on my phone) delay. My desktop is fast enough that it still feels instant.

It's instantaneous on my old iPhone se. Is it a budget android only issue?
A way to reproduce is to use your browser's profiling tools to throttle your CPU.
One answer to this is to paginate long threads so there's a definite upper limit to the length and depth of the thread on any page.
this is a bit ridiculous... folding a few thousand lines of plain text should be fast no matter what. If it isn't, then there's something quite wrong.
I don't want to knock dang or whoever wrote it but when I look at HN's JS it looks to me like it was written more to resemble Lisp idioms and to look elegant than to be efficient. If so, that may just be someone working in their comfort zone, which is fine - it works, and if it were much more complex than it is, HN being HN would complain. It's not bad, it just doesn't scale.

Also, I suspect but don't know that the table based layout makes showing and hiding elements a lot slower than it would be with, say, divs or an unordered list. If this is the case, it would probably only be exacerbated on mobile.

Not great, not terrible.
I suspect the pg answer to this question is "there's too much noise on some posts, and deterring interaction with posts of 300+ comments is a feature, not a bug.
It’s fast on Safari mobile but very slow on Firefox desktop. Goes to show many things.
I have a budget moto and HN comments section is completely unusable on Chrome but perfectly smooth on Firefox. Haven't explored why.

On Chrome any comment section with more than about 100 comments grinds to a halt. If I try to type in a comment there's a three second delay waiting for every letter to appear.

The typing thing also happens on 4chan and reddit for me. I wonder what's causing this.
I didn't want to make the post even bigger and deal with other browsers but that's a good idea for a follow-up.
A lot could be gained by simply storing the jQuery objects instead of doing the lookups multiple times per method. That’s a lot of unnecessary dom traversal.
In the similar vein, feature request to sort by best/new :)
(comment deleted)
Fun fact

In a previous company we were building a session replay tool, and as you may know it is pretty complex to evaluate the impact of the single script on a page.

The only way we found to test the impact of the script was to execute it on a page with the most mutations on an event, and try to see how much the event was impacted.

The only place where we found a heavy use of mutations was the hackernews page that had more than 100 comments in a thread. And the first time we tested, we tripled the time to collapse the thread

I dug into the collapsing code recently because I wanted to make a script that collapses HN threads by default. In other words, only the top-level comments would be shown at first. To me this makes more sense. If I am interested in continuing a thread, I can expand it. If I am not interested in continuing, I don't want to have to scroll past its children.

According to the comments here, maybe I would be better off implementing my own collapsing scheme.

If you don't mind me being negative here for a moment:

1. It's not your website, why spend so much time and effort on dissecting the issue? If one did this for every webpage they visited it'd be a more than a full time job.

2. Does it really look like Hacker News has had any serious development effort poured into it anytime recently? What incentive does YC have to put time and money into a forum that generates zero revenue?

3. Do we really expect web browsing to be pleasant on a 3 year old budget smartphone with a Qualcomm 617?

The Moto G4 Plus is solidly in the bottom 25% of phones listed here:

https://www.androidbenchmark.net/cpumark_chart.html

As for your first point, my answer would be because it can be fun to do so.
Fun, interesting, you learn stuff, what's not to like?
"Generates zero revenue" is silly. Hacker News has certainly generated tens of millions of indirect profits for YC; probably much more. It's tremendous marketing value for the organization and its companies.
(comment deleted)
1. Too much free time I guess. I'm a frontend guy, I find frontend stuff interesting.

2. No. Probably none.

3. Are you saying that you are willing to sacrifice the user experience of the bottom 25% of the users of a website?

3) Most of the internet does this now. Even on my Q6600 PC, web sites grind to a halt. Whereas actual applications run just fine, even my 3d animation software. The overhead of the web has become unbearably lazy.
(comment deleted)
(comment deleted)
>1. It's not your website, why spend so much time and effort on dissecting the issue? If one did this for every webpage they visited it'd be a more than a full time job.

1) This is a community with a lot of web developers and programmers, and people who have a professional or hobby interest in these problems, and are hanging out here anyway clearly with nothing better to do.

2) We have to do it here because they don't take issues and pull requests.

(comment deleted)
I wrote a browser extension to collapse HN comments past the first depth and ended up just attaching their css classes and setting the sub-comment count myself. It was the fastest behavior I could find at the time for reasons I've since forgotten. I did try to use their existing js but it took forever to collapse the page.

Here's my collapse code if interested

https://github.com/a13o/disengaged/blob/master/src/hacker-ne...