Adding Comments 4 Client Side
This is part of a series on building my own comment engine for Hugo. You can start with part 1.
Last time, we made sure that all existing and future posts will have a unique post_id:
in the Hugo front matter. This time, we’ll make sure that they get shipped down to
the client side so that the javascript can use them.
The client side code for the comment engine just has a few requirements:
- It should fetch comments from the backend
- It should display those comments nicely enough that my mediocre CSS isn’t distracting.
- It should let people post new comments
- (voluntary extra requirement) It should be in vanilla JavaScript and not really add anything to page sizes or load times.
- (involuntary extra requirement) deal with CORS.
If you want to see all the client side code exactly, feel free to inspect the page 😀. But let’s talk about the interesting parts.
First, fetching comments. The last time I worked on frontend web development full time, where were lots of JQuery AJAX calls everywhere, and it was sort of gross. I’m very pleased to report that now fetching JSON from some backend is downright pleasant:
var commentsURI = 'https://{{ .Site.Params.comment_backend }}/prod/comments/{{ .Params.post_id }}';
function fetchComments() {
fetch(commentsURI).then((response) => { return response.json(); })
.then((json) => {
var commentSection = document.getElementById('comments')
// TODO: display some comments
})
.catch((err) => { console.log(err); })
}
In a future post will talk about the API Gateway + Lambda + DynamoDB stack that fetches the comments, and how comments get approved, but for this client side post, that’s the whole code that fetches all the comments.
Here’s the code that displays the comments:
json.comments.forEach((comment) => {
var timestamp = new Date(new Number(comment.sk));
var displayHeading = `On ${timestamp.toDateString()} ` +
`at ${timestamp.toLocaleTimeString()}, ${comment.author} wrote:`;
var commentDiv = document.createElement('div');
var body = document.createElement('blockquote');
body.appendChild(document.createTextNode(comment.body));
var author = document.createElement('div');
author.appendChild(document.createTextNode(displayHeading));
commentDiv.appendChild(author);
commentDiv.appendChild(body);
commentSection.appendChild(commentDiv);
})
I think a larger problem would use a framework like Vue or React to generate these, but I don’t want to learn to
use a framework (and to make Hugo bundle / compile / minify / whatever my javascript) to save myself from writing a ten
line forEach
.
One nice thing going on here is that document.createTextNode
does the HTML escaping for me (see for example the comment below
by “some dubious character”).
That’s all for today! Next time, which will hopefully be sooner than 7 months from now, we’ll talk about the remaining requirements the comment engine, and how they were implemented.
Till then, happy learning!
– Will
Love this post? Hate it? Is someone wrong on the internet? Is it me? Please feel free to @me on mastodon
I used to host comments on the blog, but have recently stopped. Previously posted comments will still appear, but for new ones please use the mastodon link above.
Discussion