7 ms·
Build a hit counter for Gatsby with React, AWS Lambda, and FaunaDB
- sntran 6y agoI may be missing something here, but... all that for a hit counter? Even using React for the front-end seems overkill for a little widget.
- tyingq 6y agoI don't see any locking either, so I imagine it misses some counts.
- tyingq 6y agoThe right way to do it with FaunaDB: https://news.ycombinator.com/item?id=24618998 https://news.ycombinator.com/item?id=24618998
- vsdvvsderer 6y agothese days the hard part isn't the view counter logic, it's managing the 395,000 dependencies in your project
- dclowd9901 6y agoI used to be “dependency-first” for library code, but I’ve noticed lately that my first question has been “why wouldn’t it be a good idea to build in house?”
- notJim 6y agoHard same. After having a few experiences where a dependency hardly does anything, my approach is to read the docs first and see if I can implement the parts I need in a couple of hours. Often I can.
- joshmanders 6y agoTwo reasons not to build in house: 1. Edge cases. You cannot possibly cover every possible edge case. This is why back in the day we had "Site works best on IE". Libraries are often used by a lot of people thus edge cases you couldn't possibly think about are covered. 2. Someone else maintains it. If your job is to build an application, why are you spending all your time maintaining a library that just facilitates your application? If I'm building a racecar, I'm not gonna make the wheels in house, let people who are better at that do that while I focus on what I do best.
- vsdvvsderer 6y agoOne reason to not not build-in house: 1. Edge cases. Chances are you do not need to cover every edge case, at least when building an MVP. It can take more time to learn a complex API than to build in house. See also premature optimization. 2. Someone else maintains it. In the event you decide to use someone's dependency and they decide to unpublish it with the click of a button.... (ok at least this one has been fixed, but API versioning can still be a bear).
- thrownaway954 6y agoi totally agree. plus the fact that he's using a DAS for storing the data. if there is one thing i refuse to do is not be in charge of my database or using something proprietary.
- gibs0ns 6y agoIt reads to me more like a sponsored blog post by the db saas mentioned in the article.
- prezjordan 6y agoThe hit counter is merely an example! I see this blog post as an intro to how-to-connect React up to a hosted database over this fancy serverless paradigm thingy.
- Royalaid 6y agoAnd more importantly this is what a lot of people are doing in industry, for better or worse, and so seeing this all laid out together is important IMO.
- reaperducer 6y agoI may be missing something here, but... all that for a hit counter? Up next, the Angular-powered guestbook in just 10k lines of code. Then stay tuned for the Go-powered e-card sender in just 50k lines of code. And then, the Typescript web ring... the cloud... using BespokeDB... and service workers... in WebASM!
- joshwcomeau 6y agoTo be clear I am not advocating switching to React in order to add a hit counter. The article is meant for folks who already have a Gatsby/Next site.
- deleted 6y ago[deleted]
- schemescape 6y ago> q.Update(document.ref, { data: { hits: document.data.hits + 1, ... Does FaunaDB have an "atomic increment" a la Firestore? Knowing nothing about FaunaDB, I suspect this code in the blog post has the potential to "lose" hits that come in at roughly the same time...
- quotemstr 6y agoFaunaDB appears to have some kind of transaction support[1], so atomic updates of the sort you mention seem feasible. That said, I'm a huge SQL partisan, and I'd much rather talk to a SQL database than this custom thing. https://docs.fauna.com/fauna/current/concepts/isolation_levels https://docs.fauna.com/fauna/current/concepts/isolation_leve...
- tyingq 6y agoI did find an example of an atomic increment in Faunadb. Sometimes SQL is easier :) : Update( Ref( Collection('topics'), '254119747652682260' ), { data: { clickCount: Add( Select( ['data','clickCount'], Get( Ref( Collection('topics'), '254119747652682260' ) ) ), 1 ) } } )
- grawprog 6y agoI can't help but feel like this article is a good summary of what's wrong with the modern internet. It's not a bad article, it just feels like a parody. 'Ok guys, now here's the modern way to make one of the more simple things from yesteryear. First, lets bust out react.... A few hundred loc later... Ok guys the database... Sign up for account Several more hundred loc later... 'Now to actually write our functions' Download some dependencies Several hundred loc later... And...here's your hit counter guys... This whole article just captures perfectly the essence of all the things we complain about with the modern web. Overengineered, convoluted solutions to simple problems. Honestly, it would be nice sometimes if modern solutions remembered sometimes, it's ok to just keep it simple. I did have a quick look around to see if i could find a simple, 'modern' hit counter. https://www.codementor.io/@jamesezechukwu/how-to-create-a-simple-counter-using-javascript-html-css-bxcjgbbxa https://www.codementor.io/@jamesezechukwu/how-to-create-a-si... Personally, I prefer the simplicity of this to the article myself.
- jedimastert 6y agoThe one you've linked to doesn't seem to actually store the count anywhere, which seems to be the hard part.
- tyingq 6y agoAgree with a lot of what you wrote, but the example is weird. It's a client side counter with no persistence.
- grawprog 6y agoYeah, i realize that, it was just something quick I found after about a 30 second search. I wasn't trying to complain about the original article itself, it's obviously a production ready example whereas my linked one not so much. It's just the general idea that, such things are required even for something so simple just seems over the top when you look at something like a hit counter alone. It's just overall, if we tried to simplify, the simple things, would all the rest of the frameworks and apps end up being so convoluted and overengineered?
- Whitespace 6y agoI don't think this is at all in the spirit of hit counters of the past; IIRC they were an img tag that would be dynamically rendered serverside. Static markup » dynamic content. Perhaps a more apples-to-apples comparison would be an img tag that returns an SVG, allowing CSS styling. You can still choose serverless backend, or you can use the tried-and-true apache/nginx with memcache, just like the 90s.
- kbenson 6y agoMore like CGI with local state file and locking, or a DB back-end. I'm sure some major sites used memory, but at the point you need that you might be using a load balancer, reducing the usefulness of the technique.
- nurgasemetey 6y agoPaid article of Fauna.
- duxup 6y agoI suspect this is intended to be just an example tutorial that isn't intended to be "this is how a hit counter SHOULD BE". Queue the OMG modern web complaints that are correct that this is a lot for a hit counter, but this also I don't think that's the point here. If someone were to take this article and think "oh this is how to build a web counter" that's not OMG modern web, that's a different problem.
- butz 6y agoWouldn't it be easier to access Google Analytics using API and pull data from there?
- joshwcomeau 6y agoHey folks! Author here. Just a quick clarification, this is NOT a sponsored post by Fauna, as some have claimed. As the article states, the choice for database is somewhat arbitrary, you can swap it out for Mongo or whatever else you’d like and not much code would need to change.
- woat 6y agoThis is going to sound crazy but about a few years ago I sent you an email about learning Javascript. I think you were at Unsplash about to go to Khan Academy? Or was it the other way around haha. I just want to say thank you for your kindness - the tips and advice you gave me definitely contributed to the career path I have today. I know that responding back to some random kid may not seem like a big deal, but I would not have been able to get here without the help and generosity of experts like yourself.
- joshwcomeau 6y agoGlad to hear it was helpful :D
- MartinMond 6y agoNow compare this with Elixir + a good old database: https://dashbit.co/blog/homemade-analytics-with-ecto-and-elixir https://dashbit.co/blog/homemade-analytics-with-ecto-and-eli...
- klysm 6y agoTaking a step back, it’s truly insane that it is standard practice to apply this level of complexity to the storage, incrementing, and rendering of a single integer. The number of dependencies involved is surely enormous. Perhaps I am underestimating the complexity of the task at hand, but how is this not like a 2 line flask app or something comparable.
- coffeemaniac 6y agoIt could be done in a 2-line flask app. Josh's blog is about building things using Gatsby and the tooling built around the React ecosystem. So he wrote about how to build it with that. I don't know that I'd call it "standard practice" but it's a programming tradition to demonstrate how to use a set of tools by building something simple with them.
- ticmasta 6y agoPretty funny that the push towards static serverless has made something you used to get essentially for free on your dynamic client-server app into quite a complex undertaking. Static compile-time sites are fantastic for a huge swath of applications, but this is a good reminder that you can shift the work around and even come up with better isolated, decoupled approaches but somewhere it still has to get done. Introducing functionality that is dynamic outside the browser and requires state (i.e. persistence) is definitely an area that seems to "fight" the natural inclinations of frameworks like Gatsby et al.
- chopraaa 6y agoI'd just like to say that this is one of the most beautiful websites I've ever seen!