Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace html/template with a-h/templ #25

Merged
merged 17 commits into from
Mar 27, 2024
Merged

Replace html/template with a-h/templ #25

merged 17 commits into from
Mar 27, 2024

Conversation

applejag
Copy link
Member

@applejag applejag commented Oct 20, 2023

Heard about templ and wanted to try it out.

Templ uses static compilation of templates.

Core motivation to use templ instead of html/template is just that, the static compilation.

Instead of guessing the models of the template contexts, you get them statically compiled. Also, it has a language server, so working with it isn't half bad. It's a bit buggy, but still works better than nothing.

Also, the syntax is almost identical to Go.

Findings when trying it out

  • I still get a lot of control over the output.

  • A bit restricted when it comes to using components:

    • Can't use them on the same line as normal text
      • Apparently you can. Can't with @myComponent() syntax, but you can with the {! myComponent() } syntax.
    • Can't have multiple "slots" Edit: They recently added "components as parameters", which could solve this a bit: https://templ.guide/syntax-and-usage/template-composition
    • Can't loop over the "children". Only the { children... } syntax works. children isn't actually a variable. Edit: Now you can with templ myTempl(foo ...templ.Component)
    • No good way to set defaults, as everything is normal parameters, and Go doesn't have default values for parameters. So always have to create tons of similar functions just to do simple tasks. (See link.templ for example)
  • Editor support is kind of in its infancy.

    • The LSP is quite buggy.
    • Added to nvim's lsp-config! Nice!
    • No docs on emacs support, and I didn't have the energy to try set it up. Shouldn't be big issue with lsp-mode though.
  • Even with some lacking features, it has a very nice developer experience. Compared to html/template, it feels so much better.

  • The number of files quickly becomes a mess. The duplicated files has such a similar name, I found myself clicking on the wrong ones all of the time. Doesn't help that VSCode only has icons for .go files and not for .templ files either...

    • Found out that VSCode has file nesting support, which helps a lot.

Overall, I really like it.

Can we keep it? :3

@applejag applejag requested a review from a team as a code owner October 20, 2023 18:07
@applejag applejag requested review from jadolg and RI-Kai and removed request for a team October 20, 2023 18:07
@applejag applejag self-assigned this Oct 20, 2023
@applejag applejag added the enhancement New feature or request label Oct 20, 2023
@jadolg
Copy link
Member

jadolg commented Oct 23, 2023

Maybe I'm being pessimistic today but you just listed a bunch of good reasons not to adopt it 😬
My overall feeling with Templ is it has a lot of potential but it's not fully there yet, so if you feel like becoming early adopters is a good idea, I say :shipit:
It's fun to play with and we are not creeping a huge part of our system by doing so, plus it can be reverted if we find an unbreakable wall.

@jadolg
Copy link
Member

jadolg commented Oct 23, 2023

Question: are files autogenerated from some other code?
Asking cause a bunch of them are missing the empty line at the end.

@applejag
Copy link
Member Author

Question: are files autogenerated from some other code? Asking cause a bunch of them are missing the empty line at the end.

Only the _templ.go files are autogenerated. The .templ ones are written by hand. The missing new line comes from my usage of VS Code, before I added the .editorconfig. Fixed in dbc8f25

Maybe I'm being pessimistic today but you just listed a bunch of good reasons not to adopt it 😬 My overall feeling with Templ is it has a lot of potential but it's not fully there yet, so if you feel like becoming early adopters is a good idea, I say :shipit: It's fun to play with and we are not creeping a huge part of our system by doing so, plus it can be reverted if we find an unbreakable wall.

Yea I'm just keen on being early adopter, to goof around with it. The drawbacks I mentions means we can't do anything fancy, and that it works a bit different than other templating engines found in other languages. I'm personally used to Razor (from C#/ASP.NET), which is a very mature templating language.

I'd say it's better than html/template, but worse than Razor. :)

@applejag applejag requested review from nicmr and removed request for RI-Kai October 23, 2023 11:38
@nicmr
Copy link
Contributor

nicmr commented Oct 23, 2023

I appreciate the effort of the developers to introduce some kind of JSX-alike to go but the generated code is pretty garbled, making it harder to review, tooling is missing / requires manually written scripts because compilation becomes a two-step process. Also I would prefer to avoid any in the codebase.

In regards to early adoption, I don't really see a future where this becomes a much better experience without Go introducing metaprogramming (generics came after all, so maybe in 5years?). To illustrate what would be possible:

// JSX-style code with a macro in rust
use yew::html;

html! {
    <ul class="item-list">
        { for self.props.items.iter().map(renderItem) }
    </ul>
}

This is 100% valid code, requires 0 extra tooling, it's all handled by the compiler resolving the macro.

The one alternative I see would be building the html entirely from functions, which in some languages can be very elegant (see purescript example) but would probably be too verbose in golang.

-- html built entirely from functions, completely type-checked
-- with every html element accepting a list of attributes and children
import Flame.Html.Element as HE
import Flame.Html.Attribute as HA

view  Model  Html Message
view model = HE.main "main"
--      <function>  <list of attributes>   <list of children (or just 1 element)>
      [ HE.button [ HA.onClick Decrement ] "-"
--    equivalent to he.button([ha.onClick(decrement)], "-") in Go
      , HE.text $ show model
      , HE.button [ HA.onClick Increment ] "+"
      ]

I would personally prefer to stick with the old templating.

@applejag
Copy link
Member Author

I appreciate the effort of the developers to introduce some kind of JSX-alike to go but the generated code is pretty garbled, making it harder to review, tooling is missing / requires manually written scripts because compilation becomes a two-step process.

The generated code is certainly not the best. But it's also not meant to be reviewed.

A two-step compilation is common in the Go ecosystem. I know you like your Rust, where that isn't the case, but in Go it is.

Also I would prefer to avoid any in the codebase.

Where's this any use you mention?

This approach arguably reduces the amount of any. Before the template context was an any, but now it's a static type.

In regards to early adoption, I don't really see a future where this becomes a much better experience without Go introducing metaprogramming (generics came after all, so maybe in 5years?).

Yea would also not hold my breath on that one. Nothing on the current road map suggests adding generator/macro support.

This is 100% valid code, requires 0 extra tooling, it's all handled by the compiler resolving the macro.

The grass sure looks greener on the other side...

@nicmr
Copy link
Contributor

nicmr commented Oct 23, 2023

This is not about how the grass is greener or how much I like rust, it's about illustrating what I would expect of a JSX-style syntax and if that is possible with the technology at all, which is important to evaluate if early adoption is worth it. It was only an example from a language I'm familiar with - it's hardly the only language with metaprogramming.
What vision do you have of how templ will evolve?

@applejag
Copy link
Member Author

This is not about how the grass is greener or how much I like rust, it's about illustrating what I would expect of a JSX-style syntax and if that is possible with the technology at all, which is important to evaluate if early adoption is worth it. It was only an example from a language I'm familiar with - it's hardly the only language with metaprogramming. What vision do you have of how templ will evolve?

I don't really have a grand vision here. I just thought it was nicer than html/template.

My idea was to keep the HTML part of Jelease simple, and templ fits quite nicely there.

If we want a more advanced frontend, then I suggest we scrap both html/template and templ, and instead go with something like React or Svelte. And then only rely on the Go part as an API.

@applejag
Copy link
Member Author

What if we just went full frontend anyway? And keep the Go code as a backend?

Maybe we could do something like SvelteKit's static generation, and then just host those files from the Go code?

As much as I like endorsing support for "no javascript", it's maybe better to just use a more mature project.

Also, even though I criticized on "grass is greener on the other side", personally I would not be too against changing this to Rust. Maybe we could spend a freeky friday on investigating how this would look like?

@applejag applejag merged commit 8a01468 into main Mar 27, 2024
4 checks passed
@applejag applejag deleted the feature/templ branch March 27, 2024 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants