[HN Gopher] Show HN: Use Go's HTML/template to write React-like ...
       ___________________________________________________________________
        
       Show HN: Use Go's HTML/template to write React-like code
        
       Hi all,  I'm currently working on my hobby project, and one of the
       fun constraints I put in was to build using as less dependencies as
       possible.  I chose Go as it has a really good standard library, and
       all went well for building backend. But for frontend, I was
       wondering whether I should break the constraint and go for React. I
       tried options like Web Components, but I really didn't like the
       ergonomics and I didn't want to use jQuery either.  Out of
       curiosity, I was exploring Go's html/template package to see if I
       can write UIs in a React-like manner. I found most of the online
       docs using the "slots" like approach which I found unintuitive.
       But after trial and error, I found an approach that's very close to
       React and without using any 3rd party packages like templ.  I'd
       like to share this with the community, not sure if it's a common
       approach - https://www.sheshbabu.com/posts/react-like-composition-
       using...
        
       Author : rkwz
       Score  : 83 points
       Date   : 2024-05-27 13:39 UTC (9 hours ago)
        
       | rkwz wrote:
       | Here's the link: https://www.sheshbabu.com/posts/react-like-
       | composition-using...
       | 
       | Didn't realize HN doesn't convert link text to clickable links
        
         | zoidb wrote:
         | Huh I was able to click on it fine, maybe it wasnt clickable
         | initially?
        
           | rkwz wrote:
           | Ah yes, maybe my mistake!
        
       | verdverm wrote:
       | Go's template system (both text/template and html/template) is
       | pretty powerful. You can add custom functions and partial
       | templates too. I use these concepts in https://docs.hofstadter.io
       | to generate any code, not just frontend. Hugo uses the same
       | system to do static site generation, which may be even closer to
       | what you are showing. Helm templates is the epitome of the worst
       | use (go/templating yaml files, I use CUE for this now).
       | 
       | For frontend, as in your example, this has the older feel for UI,
       | where each navigation requires a round trip to the server and a
       | full-page response to the client. This is part of the reason
       | people have moved to React and full-stack TS. I love Go, but I'm
       | definitely a big fan of writing webapps in Next at this point.
       | React Server Components are a really nice DX.
       | 
       | I now generate much of the React / Next code at develop time,
       | rather than runtime. Hof's original goal was to make adding a
       | field to a type a one-line change in a source-of-truth file, and
       | then generate all the changes through a full-stack app by running
       | `hof gen`.
        
         | rkwz wrote:
         | I love React too, but it pulls in a lot of dependencies and the
         | dependencies need periodic maintenance.
         | 
         | Sometimes you get the feeling that you're spending a
         | significant chunk of your time not writing code but fighting
         | with configs and dependency churn.
         | 
         | Using Go's html/template definitely makes the UI feel dated
         | because of re-rendering, but I rarely notice it in my side
         | project. My next exploration is to use HTMX.
         | 
         | I'm planning to gradually add dependencies like HTMX to see how
         | far I can go to reach React's smoothness.
        
           | verdverm wrote:
           | There eventually has to be JavaScript somewhere, and once you
           | have to use that for any dynamic frontend, might as well use
           | a proper JS/TS framework.
           | 
           | Not being a frontend person first, I have learned to choose
           | whatever they are using these days. It will be hard to hire,
           | onboard, and maintain anything that strays too far for the
           | normal patterns they use.
           | 
           | Next has skyrocketed in popularity for a reason. It makes the
           | React DX much better, losing a lot of the config hell from
           | other framework/library amalgamations
        
             | rkwz wrote:
             | > There eventually has to be JavaScript somewhere, and once
             | you have to use that for any dynamic frontend, might as
             | well use a proper JS/TS framework.
             | 
             | Yes, totally understand it's hard to escape JS in Web
             | frontend. Even writing a simple dropdown requires a little
             | bit of JS.
             | 
             | > Not being a frontend person first, I have learned to
             | choose whatever they are using these days. It will be hard
             | to hire, onboard, and maintain anything that strays too far
             | for the normal patterns they use.
             | 
             | Since this is for my hobby project, it's more fun to be a
             | irrational ;) I use standard React at work.
             | 
             | > Next has skyrocketed in popularity for a reason. It makes
             | the React DX much better, losing a lot of the config hell
             | from other framework/library amalgamations
             | 
             | Need to check Next again, I tried it many years back and it
             | was good.
        
               | 8organicbits wrote:
               | If you really want, you can avoid JS for drop down menus
               | too. I've seen the CSS hover [1] and the summary/details
               | [2] approach before. My recent sites use Bulma for all
               | the styling, so the only JavaScript I'm using is the
               | toggle for the navbar burger icon on small screens [3].
               | 
               | [1] https://www.w3schools.com/Css/css_dropdowns.asp
               | 
               | [2] https://codepen.io/Ajay-Anand/pen/OJoZjPd
               | 
               | [3] https://bulma.io/documentation/components/navbar/
        
             | tomohawk wrote:
             | "might as well"
             | 
             | Those are the most expensive 3 words in the english
             | language!
        
               | verdverm wrote:
               | It's very natural for humans to avoid choice perplexity
               | and deviating from the norm when an unknown ROI or LOI is
               | involved for alternatives. Sticking with the tried and
               | true certainty has value and can reduce unforeseen or
               | secondary "costs"
        
           | be_erik wrote:
           | HTMX + React style server rendered components would solve 80%
           | of the use cases for a modern SPA. Keep going! This is a
           | breath of fresh air for many simpler applications.
        
             | verdverm wrote:
             | I haven't tried HTMX, can it fetch and load html fragments
             | into an existing dom?
        
               | dlisboa wrote:
               | That's pretty much all it does. It reacts to an event,
               | fetches from an URL, swaps the result from that URL in
               | some part of the DOM.
        
               | verdverm wrote:
               | Then does the server handling the requests needs to
               | produce html fragments?
               | 
               | If I request a page, how does it know to only serve /
               | fetch / render the main content vs the full page?
               | 
               | ---
               | 
               | It seems like a lot of would be logic a real language has
               | been moved to DSL and strings, i.e.
               | 
               | https://htmx.org/docs/#swap-options
               | 
               | `hx-on:htmx:config-
               | request="event.detail.parameters.example = 'Hello
               | Scripting!'"`
               | 
               | Not a fan of this fad of moving programming to embedded
               | strings, also seen in lots of Yaml based systems
        
               | dlisboa wrote:
               | Yes, the idea is to send HTML on the wire.
               | 
               | HTMX sends some headers that help you identify the
               | context, this way you can render just a portion of the
               | HTML (e.g. just the partial of the "Todo" list in your
               | "Todo App" homepage). You need some backend logic to
               | handle that but still much less than a full blown JSON
               | API would have.
               | 
               | They also have extensions that can diff and merge the DOM
               | so even a full page load would replace just what changed,
               | this way your backend is pretty much unaffected (you just
               | end up serving more MBs).
               | 
               | There are other libs in this space by the way, like
               | Unpoly and Hotwire, HTMX just got more mindshare.
               | 
               | > Not a fan of this fad of moving programming to embedded
               | strings, also seen in lots of Yaml based systems
               | 
               | I absolutely agree. I had a comment thread with HTMX's
               | creator about this, I feel like it's a bad idea to shove
               | logic into that. He also created Hyperscript
               | (https://hyperscript.org) so it's something he doesn't
               | think is an issue.
               | 
               | In general I think it's pretty easy to rein that in. Just
               | use HTMX to do most of the plumbing it's strong at
               | (react, fetch, swap) and keep the logic server-side. In
               | my experience that covers the vast majority of web apps.
               | If I absolutely need more client-side logic I'd reach for
               | a little JS code or create a Web Component.
        
               | verdverm wrote:
               | CEL (Common Expression Language) has gained the mindshare
               | in the devops / Yaml world, though typically just for the
               | expression evaluation in the context of another system's
               | data
               | 
               | https://cel.dev/
        
             | robertoandred wrote:
             | Why switch to something new and complicated like htmx?
        
           | dlisboa wrote:
           | You can absolutely do it with HTMX. It'll feel SPA-smooth
           | without all of the complexity. Some companies have rich and
           | responsive UIs using plain HTML and an HTMX-like lib on top
           | of it (like Hey.com). Pretty smooth and can be even reactive.
           | 
           | This is a reaction video (sorry) because I couldn't find the
           | original, but in it you see plenty of things associated with
           | SPAs being done in HTMX, from a company that went from React
           | to HTMX: https://www.youtube.com/watch?v=wIzwyyHolRs
           | 
           | Add a few animations and transitions on top and I doubt
           | anyone could tell the difference.
        
       | lucideer wrote:
       | [off-topic comment but somewhat relevant for anyone choosing a
       | lang/ecosystem]
       | 
       | I noticed that the syntax highlighting for the Go html/template
       | examples in the article is incomplete. We're using Go
       | html/templates on a new project (within a team that does a lot of
       | React frontend & some Python) so this kind of project seems like
       | it would really suit, but a massive bugbear has been the very
       | poor IDE-level syntax highlighting support for Go html/templates.
       | Can anyone recommend a good syntax highlighter for Go
       | html/template in VSCode for example? None of the
       | main/official/popular addons seem to get this right.
       | 
       | Seems a pretty unexpected oversight from a language from Google.
        
         | rkwz wrote:
         | > I noticed that the syntax highlighting for the Go
         | html/template examples in the article is incomplete.
         | 
         | Sorry, it might be something wrong with my blog setup. I use
         | hexo, might need to play around with the config.
         | 
         | I use this VSCode extension for coding and it works fairly
         | well:
         | https://marketplace.visualstudio.com/items?itemName=jinlimin...
        
           | catlifeonmars wrote:
           | This is something that should be part of gopls IMO.
        
         | dabber21 wrote:
         | there are also projects that let you use HTML directly in Go
         | like: https://www.gomponents.com/ (I'm currently using it in a
         | side project and liking it so far, but I also just started)
        
           | markusw wrote:
           | Hey, I wrote that! :D I hope you find it useful.
        
         | impune wrote:
         | In Jet Brains family IDEs (not sure how they call the go one)
         | you can use Inject language or reference option to get most of
         | editor support (inspections,highlighting,intellisense etc.) for
         | snippets of one language embedd in files of another language.
         | I've been using it with JS scripts inside custom xml for a
         | while and it works pretty well.
        
           | michaelcampbell wrote:
           | Thanks for this; JetBrains stuff continues to amaze me. Its
           | blessing and curse is the incredible breadth of functionality
           | I keep learning about.
        
           | lucideer wrote:
           | JetBrains "Inject" is fine for contiguous embeds like JS in
           | XML, but doesn't cut it for inline intertwined string-
           | templating.
           | 
           | E.g. (from the article):                 <a class="button
           | {{if .IsPrimary}}primary{{end}}" {{if eq .IsSubmit
           | true}}type="submit"{{else}} href="{{.Link}}"{{end}}>
        
         | rickette wrote:
         | I've given my Go templates a double suffix like index.go.html
         | and index.go.json. Most tools will recognize these as HTML and
         | JSON files so highlighting works as expected. Additionally in
         | JetBrains IDEs you can assign the "GoTemplate" language to
         | .go.html and .go.json files and it will also recognize the
         | template/html and template/text syntax. So this gives you full
         | syntax highlighting of both HTML/JSON and Go templates.
         | 
         | See https://github.com/PDOK/gokoala?tab=readme-ov-
         | file#intellij-... for a script to set this up.
        
       | senthil_rajasek wrote:
       | This is nice. Thanks for sharing.
       | 
       | When I heard "react" I immediately thought SPA and Event handling
       | in the browser.
       | 
       | This is more close to ASP .NET ( organizing views on the server
       | side).
       | 
       | This is very useful but this is not for handling events on the
       | client.
       | 
       | Thanks again for sharing.
        
         | rkwz wrote:
         | Yes, it's more about organizing your UI code/templates similar
         | to a React codebase than running Go code in browser.
         | 
         | I think apart from vDOM, a big contribution from React is how
         | we organize code.
        
         | michaelcampbell wrote:
         | Yeah this is more like go-template-jsx than "react"
        
           | fourside wrote:
           | It's not even JSX-like templates in Go because one of the
           | biggest advantages of JSX is that for any logic you just use
           | JavaScript instead of having to learn a template language.
           | It's extending HTML in JS rather than extending HTML to allow
           | for scripting. I agree with the parent comment that this is
           | more like the Go version of ASP.NET templates.
        
       | michaelnny wrote:
       | Although I don't know Go programming language, I do appreciate
       | people making stuff using as minimal dependencies as possible.
       | I'm glad that I'm not the only one who has this habit.
        
         | geek_at wrote:
         | it kinda looks like a small PHP boilerplate. Except with GO you
         | still need some code to make templates render
        
         | rkwz wrote:
         | Thanks! Go makes it really easy to go minimal dependencies.
         | 
         | I was able to build a website analytics project with just 2
         | dependencies (sqlite driver and bcrypt package) -
         | https://github.com/sheshbabu/mouji?tab=readme-ov-file#philos...
        
       | graemep wrote:
       | I am not a Go or frontend person, so I am a bit confused. I
       | cannot figure out where any necessary JS is generated. The
       | documentation for html/template only says it generated HTM, and a
       | React alternative is presumably producing dynamic frontends
       | (otherwise why would you be using react?). Am I missing something
       | huge?
        
         | rkwz wrote:
         | I apologize for the confusion. I meant React for component
         | composition in codebase rather than for building SPAs.
         | 
         | https://news.ycombinator.com/item?id=40491188
        
       | esprehn wrote:
       | This looks like pretty standard template based web apps like old
       | school php with includes? Not sure I understand the React like
       | approach?
        
       | didip wrote:
       | My style for building web app. I was never convinced that doing
       | everything on JS layer is a good thing (regardless the backend
       | language).
       | 
       | But you need to show more interactivity to convince the JS
       | people.
       | 
       | I personally like this style and add HTMX for partial updates.
        
         | szundi wrote:
         | Depends on what you want to do
        
         | catlifeonmars wrote:
         | It depends strongly on what you're building. Interactivity is a
         | property of the app and different types of apps have different
         | interactivity requirements. For example a page that is more or
         | less a UI proxy for CRUD operations typically does not require
         | too much client side state. On the otherhand, a flow chart
         | editor (any document editor really) needs to function largely
         | without round trips to the server. If the web app is intended
         | for mobile, you would expect to see many more interactions with
         | limited bandwidth or no internet connectivity, so you would
         | need to account for that. This is much more about application
         | architecture than preference (although you can certainly choose
         | to only work on applications that match your preferences).
        
           | fallinditch wrote:
           | Good perspective, thanks, this is the kind of information
           | that is often hard to find: deciding on a tech stack is
           | nuanced, is more than preferences. I am looking for a good
           | source of information about approaches to application
           | architectures that is relevant to modern times.
        
         | slmjkdbtl wrote:
         | but JS is the only answer to client side interactivity without
         | hacks, there's nothing to be convinced
        
       | qaq wrote:
       | https://github.com/a-h/templ is a similar mature project that has
       | JSX style templates but using Go instead of Javascript with good
       | VS code support etc.
        
         | chabad360 wrote:
         | Except that its syntax choices are a little odd, instead of
         | making all code inside curly braces, there are some special
         | keywords which only mean something if they are at the beginning
         | of a paragraph (iirc).
        
       | dlisboa wrote:
       | I'm not a full-time Gopher but I had a similar thought a few
       | weeks ago, this idea of just having template partials for
       | components and maybe a function constructor. Templ has a similar
       | feeling but you can get most of what you want with pure Go. In
       | Ruby-world there's the ViewComponent pattern/lib that Github came
       | up with, a sort of HTML non-JS component, but I just can't really
       | see why you need more than simple functions to do it.
       | 
       | Haven't thought it all the way through, I expected the code to
       | come out a little bit cleaner but Go being a bit more explicit is
       | for the better, not much one can do here.
       | 
       | But it's a valid idea: 80% of JS component libraries are just
       | reimplementing "<button>" as "<Button>" with no added value atop
       | the HTML.
        
       | philo23 wrote:
       | A bit off-topic, and maybe it was just an example made without
       | too much thought put into it, but I've noticed there seems to be
       | a lot of people now who write button/links like this:
       | <button><a href="/blah.html">My Button</a></button>
       | 
       | As far as I know that's technically invalid HTML. You can't have
       | an <a> as a child of a <button> (or even the other way around.)
       | I'm also ignoring the invalid type="submit" against the <a> tag
       | in the example button component in the post.
       | 
       | I think it stems from people who want their links to take on the
       | default button styling, but I'm not 100% sure. Has anyone else
       | noticed this trend at all?
        
         | szundi wrote:
         | Maybe this works on IE6 or something like that?
        
         | rkwz wrote:
         | > As far as I know that's technically invalid HTML. You can't
         | have an <a> as a child of a <button> (or even the other way
         | around.) I'm also ignoring the invalid type="submit" against
         | the <a> tag in the example button component in the post.
         | 
         | It definitely feels weird to have anything other than text
         | nodes inside <button>, didn't realize it's actually invalid
         | HTML.
         | 
         | I used this approach mainly to have the button component behave
         | as a link button and a form submit button. Here's the actual
         | code from my project -
         | https://github.com/sheshbabu/mouji/blob/master/commons/compo...
         | 
         | What are the drawbacks of this approach? I'm pretty sure I've
         | used this before, can't recall any downsides.
        
           | philo23 wrote:
           | > I used this approach mainly to have the button component
           | behave as a link button and a form submit button.
           | 
           | Personally I think the "proper" way to do this would be use
           | just <a> for links, and <button> for submitting forms, and
           | then have the same CSS styles applied to both so that both
           | <button>'s and <a>'s look the same visually if that's what
           | you're going for.
           | 
           | I'm not particularly familiar with Go, but I'd either make
           | the wrapping tag name itself a template variable (maybe an
           | enum between "Anchor" and "Button"? again not familiar with
           | Go) or have two components one for forms and one for links.
           | If I've understood the syntax, something like this?
           | <{{.Tag}} class="button-container"></{{.Tag}}>
           | 
           | But given both <button>'s and <a>'s have lots of different
           | attributes to manage its behaviour and state
           | (name/value/type/disabled vs href/rel/target etc) I'd
           | personally split them into two separate components, even if
           | it ends up doubling up some of the logic and styles.
           | 
           | > What are the drawbacks of this approach? I'm pretty sure
           | I've used this before, can't recall any downsides.
           | 
           | As others have mentioned, while it's technically invalid
           | browsers will still happily accept it so there's no real
           | issue with it, personally I just find it a bit quirky to
           | read. There's no harm in leaving it just as it is :)
        
           | robertoandred wrote:
           | It breaks accessibility and semantics. Use a <button> for an
           | action and an <a> for a link.
        
           | zdragnar wrote:
           | A button with type "submit" will happily submit the form when
           | you click on it. If you want it to look like a link, use CSS.
           | Putting the submit on the anchor tag is pointless- the lack
           | of a type on the button itself means the browser is inferring
           | the intended behavior and defaulting to type "submit" rather
           | than type "button".
           | 
           | As others have mentioned, the main downside is likely
           | accessibility.
        
         | idontknowifican wrote:
         | yeah it is invalid html, and probably done for the ui only. now
         | people are just copying it. would totally break if the button
         | anchor was in a form
        
         | tlb wrote:
         | Once the major browser engines support it, it's de-facto legal.
         | 
         | This also explains why there are so few alternative browsers.
         | Writing a new browser that supports everything that happens to
         | work in the major browsers is ridiculously hard.
        
           | jitl wrote:
           | The big innovation of the html5 spec was to specify how to
           | handle all the "invalid" html states; recovery from user
           | error is now part of the spec instead of wholly
           | implementation specific.
        
             | erik_seaberg wrote:
             | HTML 5's error recovery pseudocode _replaced_ the formal
             | grammar that HTML 4 had, and in authoring I find it harder
             | to take guidance from.
        
               | smrq wrote:
               | Well, what's the point of having a formal grammar if
               | nobody follows it and things outside the grammar have
               | defined behavior?
        
           | rkwz wrote:
           | Yes, html is one of the unique languages of our era. It's
           | very forgiving and lenient.
           | 
           | > This also explains why there are so few alternative
           | browsers. Writing a new browser that supports everything that
           | happens to work in the major browsers is ridiculously hard.
           | 
           | IMO one of the reasons Chrome won was because they supported
           | both Firefox and IE's interpretation of web standards.
        
           | philo23 wrote:
           | Yep, the HTML5 spec has an agreed on way to parse and
           | interpret invalid HTML, so all modern browsers should handle
           | it pretty consistently.
           | 
           | I was more interested in finding out where this style had
           | come from really, because I've seen a lot of devs doing
           | something similar and semantically it's just always struck me
           | as a bit odd looking!
        
           | 38 wrote:
           | > Once the major browser engines support it, it's de-facto
           | legal.
           | 
           | thats madness. just because the browser allows it, doesn't
           | mean you should do it.
        
             | recursive wrote:
             | "Legal" is not the same as "recommended".
        
       | dncornholio wrote:
       | Building a new response for every action you make in the app not
       | something I would compare React to. This is more akind to old
       | school PHP.
        
         | recursive wrote:
         | A growing faction of developers consider that to be a good
         | thing.
        
       | aw4y wrote:
       | amazing, great work. This would be very "reactive" adding HTMX.
        
       | todotask wrote:
       | I remember the Astro web framework was written in Go before they
       | moved to TypeScript. If there's a lot of JSX on the page and it
       | needs to be escaped, what is the performance impact? Could you
       | optimize the code to minimize slowdowns from templates?
       | 
       | Hugo, Jet, and other template engines are certainly interesting,
       | but I chose to write in the Go template, which I later migrated
       | to Astro with TypeScript. This was due to the challenges of
       | managing two codebases for a medium-sized site as a solo dev.
        
       | jackothy wrote:
       | I've been doing something very similar in Rust recently using
       | Askama or Maud for templates (components), optionally with Axum
       | to include a server in the binary.
       | 
       | The author mentions wanting to colocate templates with logic,
       | Maud allows much tighter/automatic integration in this regard.
       | 
       | This approach also synergizes almost perfectly with HTMX.
        
         | rkwz wrote:
         | > Maud allows much tighter/automatic integration in this regard
         | 
         | Interesting, can you share some examples?
        
           | jackothy wrote:
           | In the linked Go approach, and also with Askama, you have to
           | define each template (component) twice. Once as a .html file,
           | and then again as a struct inside a source file.
           | 
           | With Maud, templates/components are only defined once, so you
           | no longer have to worry about keeping the two in sync or
           | colocating them.
           | 
           | This is because Maud provides a macro for writing HTML with
           | Rust-like syntax, so all your HTML (components) ends up
           | inside regular Rust files, and you can refer to variables as
           | usual.
           | 
           | This really makes for almost seamless integration between
           | Rust code and the HTML you serve.
        
         | Klonoar wrote:
         | I do this but using hypertext, since the syntax is closer to
         | JSX and less confusing for others to touch.
        
           | jackothy wrote:
           | Just checked out hypertext! Have you noticed any other
           | advantages over Maud, except for syntax?
        
         | sgt wrote:
         | Recently rediscovered htmx and applied it to a Django project.
         | It really does give that SPA feeling without much of a hassle,
         | and it's also easier in a team setting where there's less
         | stepping on other people's toes, which is often the case with a
         | full blown Vue or React app.
        
       | kissgyorgy wrote:
       | I like the experimentation, but it's still using templates. I was
       | hoping something pure-Go code components without any template
       | rendering at all.
       | 
       | I was trying to do the same React-like Component framework, but
       | for Python. No templates needed, you write 100% Python code. Here
       | are some examples how it looks like for simple components:
       | https://github.com/kissgyorgy/compone/tree/master/core/examp...
       | 
       | I use it in a Django project everywhere, no template rendering
       | for custom views!
        
         | pelme wrote:
         | We have been doing something similar with https://htpy.dev the
         | last ~6 months.
        
       | codegeek wrote:
       | Interesting. I am actually doubling down on building web apps in
       | Go using mostly standard library, powerful templates and sprinkle
       | in with a library such as Alpine JS. Seeing some success so far
       | and it makes me so much happier knowing that I don't have to deal
       | with node_modules BS (well may be except tailwind for css). I
       | actually want to test the limits of how far one can go without
       | using a JS framework like React/Vue especially for smaller teams.
        
         | flashgordon wrote:
         | This was exactly my journey too. And I went from a server side
         | templating to going deep into Nextjs/react and then back to
         | htmx/go templates. Every time I think "oh this pattern would
         | have been possible with react" I find a much simpler way. All
         | that dependency bs and bloat was just not worth it.
        
         | BaculumMeumEst wrote:
         | This is the direction I've moved to as well. I've used ROR and
         | Clojure w/ heavyweight frontends in the past, but I eventually
         | came around to the idea that I value Go w/ stdlib to avoid
         | dependencies/framework churn, have painless deployments, and
         | get extremely solid performance w/ minimal memory footprint out
         | of the box without doing anything special.
        
         | distalx wrote:
         | I'm really interested in your approach to building web apps in
         | Go. I used to build toy projects with Go using just the
         | standard libraries.
         | 
         | What are the current frameworks or tools that are popular or
         | recommended for building web applications with Go these days?
        
       | Philip-J-Fry wrote:
       | This is a nice approach I've followed myself before. It feels
       | like common sense web development, just writing things in a way
       | which allows them to be reused. A button will likely be the same
       | on any page of the site, so make a button component.
       | 
       | I don't think this is "React-like" though. Making components
       | isn't specific to React. We've been doing that since ASP and
       | probably earlier. Your views still need to know what components
       | to render here.
       | 
       | You can go further and just define a template function which
       | takes a template name and a data object. Then render arbitrary
       | children. That way your UI can be fully composed in code and the
       | only thing your components need to know is how to render
       | themselves.                   var templateFS =
       | os.DirFS("./templates/components/")                  type
       | Component interface {          Type() string         }
       | type Button struct {          Name string         }
       | func (b Button) Type() string {          return "button.html"
       | }                  type Div struct {          Children
       | []Component         }                  func (d Div) Type() string
       | {          return "div.html"         }                  type Page
       | struct {          Children []Component         }
       | func (p Page) Type() string {          return "page.html"
       | }                  func main() {          component := Page{
       | Children: []Component{            Div{             Children:
       | []Component{              Button{Name: "Test button"},
       | },            },           },          }
       | templates := template.New("")         funcs := template.FuncMap{
       | "exec": func(tpl string, data interface{}) template.HTML {
       | var sb strings.Builder           templates.ExecuteTemplate(&sb,
       | tpl, data)           return template.HTML(sb.String())
       | },         }              templates =
       | template.Must(templates.Funcs(funcs).ParseFS(templateFS, "*"))
       | templates.ExecuteTemplate(os.Stdout, component.Type(), component)
       | 
       | Your page.html file becomes                   <!DOCTYPE html>
       | <html lang="en">         <head>             <meta
       | charset="UTF-8">             <title>Title</title>         </head>
       | <body>         {{range .Children}}             {{exec .Type .}}
       | {{end}}         </body>         </html>
       | 
       | For example
        
         | Trufa wrote:
         | I 100% know it's a preference/style kind of thing, and I know
         | the React/Node isn't perfect and comes with it's downfalls, but
         | I whenever I have to code in anything other, I just miss the
         | visual/mental model aspect of having your tsx code basically
         | identical to your actual html.
         | 
         | The mental load of going from this to                   func
         | main() {          component := Page{           Children:
         | []Component{            Div{             Children: []Component{
         | Button{Name: "Test button"},             },            },
         | },          }
         | 
         | to this                 <Page>         <div>           <Button>
         | Test button</Button>         </div>       </Page>`
         | 
         | or going from this:                 const main = () => (
         | <Page>           <div>             <Button> Test
         | button</Button>           </div>         </Page>       )
         | 
         | To, well... case in point, exactly the same thing is just so
         | nice.
        
           | 38 wrote:
           | fair enough, but you're also downplaying/omitting the huge
           | dependency cost of React, both server side and client side.
           | so pick your poison.
           | 
           | you're basically saying "I want server side code without
           | having to actually code anything". of course nothing is going
           | to beat react, its an impossible ask
        
           | srhtftw wrote:
           | Reminds me of https://github.com/8byt/gox which I bookmarked
           | when working with Go but never got around to using.
        
       | pbhowmic wrote:
       | OMG! No! Having dealt with Go templates in the context of writing
       | Helm charts, I would say this is not a a great idea. Please,
       | invent a better templating language for Go, and then perhaps go
       | down this path. That being said, I am not a great fan of
       | templates in any language. Jinja2 might be a heck of a lot better
       | than Go templates but it can still be hard to get right.
        
         | Philip-J-Fry wrote:
         | What is so wrong with this approach that makes you exclaim
         | "OMG! No!"? This is practically no different to any basic
         | server side rendering framework in any other language. This is
         | a very basic pattern used all the time.
        
       | smarkov wrote:
       | I've been using Go's html/template for the last couple of months
       | and all I can say is that it's still very much a toy. It's fine
       | for basic loops and conditionals but anything beyond that is
       | extremely limited and having proper reusable components is a
       | constant fight against limitations, specifically because of the
       | lack of being able to pass multiple arguments to a template. I
       | wish the Go team had gone with something more akin to PugJS[1],
       | which in contrast is very rich in features, flexible and dare I
       | say fun to build components and pages with.
       | 
       | [1] https://pugjs.org/api/getting-started.html
        
         | mbivert wrote:
         | > because of the lack of being able to pass multiple arguments
         | to a template
         | 
         | I'm not sure if this I understand the issue correctly, but one
         | can pass multiple arguments, by wrapping them e.g. into a hash
         | (https://go.dev/play/p/89gP42K8XRb):                 package
         | main              import (           "log"           "os"
         | "text/template"       )              func main() {
         | err := template.Must(               template.New("").Parse("{{
         | .greeting }}, {{ .user.name }}!"),
         | ).Execute(os.Stdout, map[string]any{               "user":
         | map[string]any{                   "name": "earthling",
         | },               "greeting": "hello",           })           if
         | err != nil {               log.Fatal(err)           }       }
         | 
         | In my experience, the module is far from a toy, but it's not
         | always obvious how to use it properly, at first.
        
       | kunley wrote:
       | Very well written article, just the right amount of text,
       | pictures and examples. Thank you!
        
       | carom wrote:
       | This is what I do but my components have three sections: script,
       | styles, and the component. I include those in a page. The page is
       | generally another component with head and body that fits into a
       | base page template.
        
       | reactordev wrote:
       | You can use go's builtin build features and embed the results
       | into a http.FS.                 go generate npm build       go
       | build
       | 
       | And declaring the resulting frontend build as an embed.FS using
       | //go:embed dist/       var frontend *embed.FS
       | 
       | And use that in a http.FS
       | 
       | https://blog.logrocket.com/using-go-generate-reduce-boilerpl...
        
         | peter_l_downs wrote:
         | Yeah this is what I do to. The OP's approach is interesting but
         | I think that using typescript/javascript/whatever to build your
         | app, then "render" using a build step (like `vite build` or
         | whatever) and embedding the resulting static bundles is the
         | best of both worlds.
         | 
         | That said, the JS ecosystem is so weird that I totally
         | understand the urge to bail entirely and do things in Go. But
         | JS/TS and all the related frameworks really are decent if you
         | pick a reasonable subset of them.
        
         | irq-1 wrote:
         | You can also use `go generate` to create all the .html
         | routes/handlers at compile. Not that it would matter much in a
         | small app.
        
       | pard68 wrote:
       | I have something kind of similar written in Common Lisp, however
       | it uses stock HTML and then lisp. A template is a literal HTML
       | template element, and it's referenced with custom elements. So
       | `<my-el>` is in the file that will be compiled, say indet.html,
       | and then there is a my-el.html file which is the reference that
       | is inserted into the `<my-el>` as a child. This file is just
       | stock HTML with a `<template shadowrootmode="open">` as the root
       | element and then whatever in that. This is all rendered properly
       | by the browser because it is just standard HTML. The slot element
       | can be used to inject into these template els. All the lisp does
       | really is recursively compile the HTML and then manage any logic
       | writtel inside of `<script lang="cl">` tags
       | 
       | It actually supports any language, long as you define the lang=
       | name in a config file to tell the compiler how to process it. Ie
       | for python `python="python -m '$'"` would then let the cl
       | compiler know how to handle `<script lang="python">`.
        
       ___________________________________________________________________
       (page generated 2024-05-27 23:02 UTC)