component specific css and js #171
Replies: 6 comments
-
Hi @niklasgrewe. I'm currently on paternity leave and will have a proper look at this in a few weeks. 😊 |
Beta Was this translation helpful? Give feedback.
-
Subscribed to this it because I'm very interested in how or if this lib would like to handle this. Keep in mind, this lib iirc is stateless. It processes the function calls sequentially, so it would have no way of knowing that a component was including a stylesheet or script tag further down the tree when it renders the head tag. I will say, you can just include the style and script tags in the component like you're already doing. In a previous project, I included a script tag that pulled down some JavaScript every time it was rendered. That was probably a bad design since the component would not be able to be reused but in my case it wasn't going to be so it was okay. I only made it a component for organization purposes. I'm curious if there are other ways to handle this without introducing some sort of map to keep track these types of calls. |
Beta Was this translation helpful? Give feedback.
-
Hi @niklasgrewe . Thank you for your patience! I'm now back from paternity leave. I think the way I would solve it would be to pass some sort of context around to your components, which would have methods to add style and script information to a parent component. E.g.: func Page(title string) g.Node {
var ctx &Context{}
return Doctype(
HTML(
Lang("en"),
Head(
TitleEl(g.Text(title)),
ctx,
),
Body(
ComponentA(ctx),
ComponentB(ctx),
),
),
),
}
func ComponentA(ctx *Context) g.Node {
ctx.AddStyle("h2 { color: green; }")
ctx.AddScript(`alert("Component A")`)
return Group(
H2(g.Text("Component A")),
),
}
func ComponentB(ctx *Context) g.Node {
ctx.AddStyle("h3 { color: red; }")
ctx.AddScript(`console.log("Component B")`)
return Group(
H3(g.Text("Component B")),
),
}
type Context struct {
script string
style string
}
func (c *Context) AddStyle(s string) {…}
func (c *Context) AddScript(s string) {…}
func (c *Context) Render(w io.Writer) error {…} You could put this into a separate library for convenience and then use that together with gomponents. I don't think this is something I would add to the core library, since it's for a very specific use case, but I'd be happy to showcase such a library on gomponents.com. 😊 What do you think of this approach? Would that work? |
Beta Was this translation helpful? Give feedback.
-
We have recently started using Gomponents in our next gen of production code (migrating from TS+React). We chose Go for speed and simplicity and Gomponents because they are a simple, elegant and infinitely maintainable abstraction over html. It also avoids dropping in and out of templates (yuk). Kudos @markuswustenberg for this beautiful and alternative solution! Coming from a react world, @niklasgrewe, we also thought: Wouldn't it be nice if we could still use a component based approach and co-locate rendering logic, HTML, CSS and JSS? So, our solution has been to co-locate CSS and JS files amongst our Go component (Gomponent!) code and render the relevant CSS/JS at the top of each component. This gives the benefits of language support when editing without the need for specialised editor plugins to figure out what strings in our Go code are actually CSS/JS. We feel our approach achieves a nice common ground between Separation of Concerns and Locality of Behaviour. We have a dev build script that monitors for file changes and uses go-assets-builder to create several Sure, our approach means that JS and CSS is repeated throughout the mark-up if several of the same components are rendered on the page. However, we feel this is a small cost to pay vs the benefit of being able to see the JS and CSS directly next to the html when inspecting with dev tools. In order to ensure our CSS and JS is only acting on the html we intend it to, we use Surreal and its CSS companion script css-scope-inline which are also super minimal and infinitely maintainable! In the case where a script or style tag is global (but specific to only the page we are looking to serve) and, therefore, better appended to the head or end of body, we have taken a similar approach to @markuswustenberg's comment above but we simply pass it as an argument to our page layout wrapper component. |
Beta Was this translation helpful? Give feedback.
-
In order to achieve exactly what you are looking to do @niklasgrewe, you could possibly combine the approach of adding separate scripts/style tags to the head/end of body and then post-process the resulting markup to concatenate the contents of the separate tags and send the result as the response. However, I am unsure whether having multiple script/style tags actually impacts browser performance to a noticeable extent (bearing in mind there is already only a tiny amount of JS compared to complex JS frameworks) and therefore whether this would even be worth doing? Interested to hear opinions/evidence on this. |
Beta Was this translation helpful? Give feedback.
-
@wworrall thank you for the kind words! 😊 I'm very happy gomponents fits your needs so well, and is flexible enough to accommodate your workflow. That's everything I was hoping it would. You've got quite an interesting solution, and one I haven't seen together with gomponents before. I hope it works out well for you! Let me know if you find any quirks or surprising behaviour in the library while doing this. |
Beta Was this translation helpful? Give feedback.
-
Hi @markuswustenberg
thank you very much for creating this library. It's an intuitive, easy and fast way to write html in go. I come from js-world and i really love the declarative syntax to describe user interfaces. Has a little bit of SwiftUI when I think about it 😄
Right now I'm thinking about making a switch to go + gomponents for my project. I want to create a dynamic website with HTMX. Since gomponents are ultimately functions, I see no problems here. I have done exactly the same approach in JS so far. Instead of using bloated frameworks, I used ES6 template strings.
The only problem I have now is handling css and js. Basically I love the component approach. You have one component that consists of HTML, CSS and JS. When I use multiple components on a page, all the css and js code is merged into the head element. This is so handy and performant at the same time, because the css and js code is not always that big and therefore can be better inserted directly into the html document, instead of just referring to external files, so that a new request has to be made.
Hence my consideration: Would it be possible to extend the render function so that all components
<style />
and<script />
tags are automatically merged and inserted into the head element, maybe like this?this would be rendered to:
Perhaps some of this can be implemented. I am curious about your feedback.
Beta Was this translation helpful? Give feedback.
All reactions