Open Jipok opened 1 day ago
So theres a few different options here:
htmgo does a bit of code gen to allow the auto wiring of partials and routing. You mentioned you're comfortable doing your own page routing, but I would assume you don't want to also register the partials.
To still have the codegen, you can do
htmgo setup
go build .
If you want none of that and don't want to use the htmgo cli at all, you'll end up having to do a lot of manual wiring, as well as setting up your own things to recompile tailwind / do hot reloading, which I don't recommend.
But yes after those warnings, if you still want to, it should be possible to just run go build .
as long as you remove the __htmgo.Register in the main
You can register a Page or Partial manually like so:
router.Get("/mypage", func(writer http.ResponseWriter, request *http.Request) {
cc := request.Context().Value(h.RequestContextKey).(*h.RequestContext)
h.HtmlView(writer, pages.MyPage(cc))
})
router.Handle("/paas/pages/servers.ServerListPartial", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cc := r.Context().Value(h.RequestContextKey).(*h.RequestContext)
partial := servers.ServerListPartial(cc)
if partial == nil {
w.WriteHeader(404)
return
}
h.PartialView(w, partial)
}))
(this is from the code in the generated __htmgo folder)
My main complaint is that htmgo is too intrusive. Instead of being a simple library like other template engines, it creates main.go and takes over the main application management. I understand that I can rewrite the main code (I hope the preprocessor won't erase it), but the point is that the documentation doesn't even suggest other ways of using it. I don't like the hidden behavior. I think many other users don't either. Maybe this is how it's done in frontend development. But it's not in the spirit of go. For example, you wrote about recompiling tailwind. I thought you were just downloading the minified version. I think the user should know about this. It also initiates git internally. These are not bad things in themselves, but it's too intrusive. Maybe modern freshly baked developers are used to the idea that IDE and other tools do all the "magic" for them. But we are still not discussing a project on ts, but go. It seems to me that this is very much not in the spirit of established norms of development for go.
I think this could spark a holy war. Not what I want. Can you at least add a description to the documentation on how to make the project easy to build by random people without installing htmgo? Well, so that it can be posted on github and not create difficulties for people.
It seems that the entire appearance of the code suffers because there is no dsl in go. Have you thought about doing something like how templ works?
The project is something I've wanted to create for a long time. Only you went further and added calls to basic needs on js without writing js code. This is a cool idea. And it integrates well with the code.
My main complaint is that htmgo is too intrusive. Instead of being a simple library like other template engines, it creates main.go and takes over the main application management.
I agree that it's not really the 'go' way, but the main issue is that if htmgo was more like a simple library that you integrate with an existing system, a lot of the nice things that people enjoy about it really aren't possible without a little bit of preprocessing.
This includes the code gen, tailwind, live reload, js scripting, etc.
If you remove all of the preprocessing, then you end up with just an html generator similar to https://github.com/maragudk/gomponents
For example, you wrote about recompiling tailwind. I thought you were just downloading the minified version. I think the user should know about this.
Since tailwind uses a JIT compiler, it must be run as a process to recompile the css once the classes change in your go code. This is how tailwind is able to allow arbitrary classes such as width-[300px] and still give you as minimal css generated as possible.
Outside of the page/partial registration, there really isn't too much that htmgo forces on you, it uses std http handlers, so you can register any other routes you want. It doesn't force any sort of paradigm other than pages must be in the pages folder if you want to use that functionality.
I do agree that the h.App may be unnecessary and there might be alternatives to that.
It seems that the entire appearance of the code suffers because there is no dsl in go. Have you thought about doing something like how templ works?
This is actually one of the main reasons I built htmgo, I didn't like the templ DSL + it did not work well in jetbrains at all, so I likely will continue keeping it as just pure go code, since building the tooling to support a custom DSL is too much
Overall this was built because I wanted a nice way (similar to rails) to quickly build web apps in go without having to mess too much with tooling/config.
But I am open to making it less intrusive if there are good options on how that can be done without sacrificing functionality.
For what its worth, I'm in the process of building a pretty complex app right now using htmgo, https://github.com/maddalax/paas, and I'm not really being restricted by it at all. Over time I've gotten very use to the syntax and how it looks, it reads like regular HTML to me.
Thank you for your detailed answer.
gomponents looks interesting at first glance. The html tags themselves are declared shorter, no need to write h.
. And they even declare support for htmx and even alpine. But it seems that this is only formally just so that it is there. I do not see how this can be used. For example, with htmgo I can do this:
func MyForm() *h.Element {
return h.Form(
h.Button(
h.Text("Submit"),
h.HxBeforeRequest(
js.SetDisabled(true),
js.SetText("Submitting..."),
),
h.HxAfterRequest(
js.SetDisabled(false),
js.SetText("Submit"),
),
),
)
}
It's short, beautiful, readable and most importantly easy to change. It seems such a thing is impossible to do with gomponents.
Is it possible to use your project as a library only for html rendering?
This includes the code gen, tailwind, live reload, js scripting, etc.
1) I can and prefer to write the main
program and all the routes myself
2) I can use tailwind from cdn or download it and give it myself. I use predefined w-[X]
which works out of the box, no compilation is needed for this. If I want, I will simply compile it upon release.
3) I think that live reload can be done by a third-party tool. You know, the unix way, not combine utilities.
4) But about js scripting in more detail, please. Why does h.HxAfterRequest(js.SetDisabled((...)
require a preprocessor if these are the same functions?
5) etc?
I think I got it, you only think about web services. Your paas is an interesting project (now I'm studying nats). However, now I understand why you create a Dockerfile and adhere to certain approaches. This is the problem, you impose your ecosystem.
Just imagine I want to make a telegram bot. A complex bot. And it has a small part of the code where html is used - this is the settings menu. For example, this is 5% of the code from the entire bot logic. And I want to use such a convenient library as htmgo. Which imposes too much that I do not need.
Or imagine I want to add an optional simple gui for configuration to some utility. htmgo as a library would again be a very convenient option. But not in the form in which it imposes itself now.
And these are obviously not the only examples. It seems to me that you are too fixated on the idea of web microservices, which is why you nailed the library to this format.
gomponents looks interesting at first glance. The html tags themselves are declared shorter, no need to write h..
fwiw you do can that with htmgo too, you just have to do the 'dot' import the same way
import . "github.com/maddalax/htmgo/framework/h"
func MyComponent() *Element {
return Div(
Text("Hello, World!"),
)
}
But about js scripting in more detail, please. Why does h.HxAfterRequest(js.SetDisabled((...) require a preprocessor if these are the same functions?
You're right, the JS part doesn't need preprocessing, It should just work by default since it renders the valid JS within go code in the renderer
@Jipok I made a very minimal example of using htmgo for your use case, just pushed it, see here: https://github.com/maddalax/htmgo/tree/master/examples/minimal-htmgo
(added it to the docs as well under getting started)
It is completely usable without the htmgo cli, go build .
will work fine.
You will have to add your own
Let me know if something like this works for you.
fwiw you do can that with htmgo too, you just have to do the 'dot' import the same way
Indeed. Why don't you offer this as the default?
It is completely usable without the htmgo cli, go build . will work fine. Let me know if something like this works for you.
This is really what I needed. Thank you!
Why don't you add embedding public
in the example? I just don't understand why point 4 is needed.
And you need to add an explanation of what kind of script is there. And how you can reproduce it yourself. As I understand it, this is htmx, but why is it called htmgo.js then?
And I think the functionality that is in render.go
needs to be added to the library itself. I don't see what changes can theoretically be made there. It turns out that users will copy the same code from project to project, without which the library cannot be used.
I have nothing against chi
. But if you call the example minimal, maybe it's worth using go's built-in routing?
this is htmx, but why is it called htmgo.js then?
htmgo adds additional things on top of htmx to support extra built in extensions, see: https://htmgo.dev/docs/htmx-extensions/overview
If you don't want those extensions, you can remove h.BaseExtensions() from the page and use the htmx js file directly, that should still work fine.
Indeed. Why don't you offer this as the default?
I don't like that syntax / and it takes up a lot of symbols that I may want to use otherwise
I have nothing against chi. But if you call the example minimal, maybe it's worth using go's built-in routing?
I'm not too worried about it in this example, if someone wants to take it and make it even leaner with only std lib use, they can. This is just to show that it can be done with htmgo
I removed the embedded fs because it requires a special arg on go build
, the -tags prod
arg, and I didn't do embedded by default without special tags because it then requires a full rebuild if assets in the public folder change, which is not ideal in development
If you don't want those extensions, you can remove h.BaseExtensions()
I don't quite understand what it does now. After all, I have some htmgo.js
compiled by you. Doesn't it contain htmx with extensions?
I'd like to suggest making the example less minimal. I was able to reproduce examples/form but had trouble with examples/click-to-edit.
If you don't want those extensions, you can remove h.BaseExtensions()
I don't quite understand what it does now. After all, I have some
htmgo.js
compiled by you. Doesn't it contain htmx with extensions?
Correct yes, see here: https://github.com/maddalax/htmgo/tree/master/framework/assets/js
I was able to reproduce examples/form but had trouble with examples/click-to-edit.
I would assume this is because the click to edit example uses partials, so you'd have to register each one of them manually and change the code to use that new route instead of 'h.GetPartial'. It will only work by default if the htmgo cli is run to generate the routes
Imagine I made some project. And posted it on GitHub. It seems to me that people are used to the fact that if the project is not complicated and it is on Go, then you just download it and build it with
go build
or run it withgo run
. But with htmlgo, some kind of vague layer is added for a third-party user. This causes frustration. You also create some Taskfile.yml just for the sake of the preprocessor. This seems unnecessary and intrusive. And it creates the feeling that I created a project for some fat nodejs.I have a strong aversion to preprocessors since my experience with C. I even stopped using templ because of this. Your project seemed very interesting to me, but I only noticed the use of a preprocessor after reading through the entire documentation. It appears that your project isn't as dependent on preprocessors as templ is. Since I'm comfortable writing routes manually, would it be possible to use htmlgo without the preprocessor?