You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello, a while back I promised to check back with findings on trying out templ inside a Wasm environment. So here are my findings:
Preface
Use Cases
Most of us coming from Go have the notion of Go as a backend language but when using Wasm things are totally different.
We now have a backend and platform agnostic frontend language and as such we can in theory use Go as a type safe compiled language in all browser environments with a few considerations. So the most viable use cases are as a web frontend for a fully fledged computer application, since in a localhost environment bundle sizes of 10MB+ do not matter. Also if your Go Wasm Application brings something powerful to the table you might get away with a load screen of a few seconds.
Examples
So I mentioned Wasm being agnostic of the backend means that you can use it inside a QT web view, Wails, possibly even Tauri or Electron if you wanted since with the net/http package and encoding/json you can communicate with all backends amicably. This opens up a wide array of possibilities, since the only real integration with the backend that your Wasm frontend needs is the same definition of the data model.
Workflow
While experimenting I used wails as a backend but found that while developing your frontend this is not the best approach since you don't want the extra overhead on the turnaround times that wails introduces, but simply using vite or any other capable development server is preferable, since the only thing we need is something that will give us access to our assets and data.
Problems
Event Handling
Build tags
Event Handling
In wasm you basically have two choices for event handling:
You can wrap a go function call so it can be called from Javascript
or you can call javascript to handle events there.
templ
Assumptions
in templ it is assumed that the html is created by the server which means that all the scripts that we create and special constructs like the script directive in templ templates are correctly evaluated and executed.
Reality
Component wide the html gets delivered in a string builder and then set to the components html element with a snippet like this:
This way the containing script will not be evaluated which renders most JS examples in templ.guide useless.
So the only way to make it work is by applying the script separately like so:
htmlString:=stringBuilder.String()
// 1. Get the container element (assuming it has id "myContainer")container:=js.Global().Get("document").Call("getElementById", "myContainer")
// 2. Set the main HTML structure using innerHTMLcontainer.Set("innerHTML", htmlString)
// 3. Create and append <script> elementsfor_, script:=rangescripts {
scriptElem:=js.Global().Get("document").Call("createElement", "script")
scriptElem.Set("textContent", script) // The script contentcontainer.Call("appendChild", scriptElem)
}
Issue
I have not found a way to construct a javascript call dynamically like
The quotation marks keep the variable from being evaluated and single quotes don't work either. I could be wrong but I don't see any way how to dynamically create parameters to give context to an event besides looking for custom attributes in the event target element.
If that is by design and intended forgive my ignorance but since JS conversions are costly I thought a string based approach would be much more practical especially when you consider that the receiver might be a fantastic javascript library that does not know anything about your custom data attributes.
Build Tags
To be able to use syscall/js package one has to specify build tags like so.
//go:build js && wasm
In a wasm environment it is totally acceptable and even a crucial feature to use other go files in the same package space as the generated template files to host utility functions and generally not pollute the template with lengthy code.
But this is only possible when they both share the same build tags also imports won't work if they don't share compatible build tags.
So when generating the go file build tags must either must be respected or if that is a problem at least there should be a command line flag like
that prepends the build tag separated with a newline from the "Do not edit" comment.
tldr;
Go, traditionally a backend language, takes on a new role in the WASM environment. It becomes a platform-agnostic frontend language capable of powering rich web applications. This shift opens possibilities for using Go in various contexts, including:
Web frontends: For complex applications where performance and type safety are crucial.
Desktop applications: Integration with frameworks like QT Webview, Wails, Tauri, and Electron.
Hybrid environments: Combining Go's strengths with existing JavaScript ecosystems.
Development Workflow
While frameworks like Wails offer integrated development, a simpler setup with tools like vite can be more efficient for frontend development. This approach focuses on rapid iteration and asset management.
Dynamic JavaScript Calls
Constructing dynamic JavaScript calls with templ is problematic due to quotation mark escaping issues. This limits the ability to pass context to event handlers, potentially hindering integration with JavaScript libraries.
Finding a way to manage javascript in a centralized way would be beneficial for everyone using templ since that would solve innerHTML issues and improve JS Code organization. I will not propose a solution since this is out of scope of this writeup.
Build Tags
Using the syscall/js package requires specific build tags: //go:build js && wasm
This poses challenges when:
Sharing utility functions: Go files containing utility functions used by templates need identical build tags.
Managing imports: Imports require compatible build tags. An added benefit is future proofing for tags not yet introduced by the Go Team.
Proposed Solution
Introduce a command-line flag to templ for specifying build tags in generated files:
This would prepend the specified build tag to the generated Go files, ensuring compatibility and code organization.
Conclusion
Addressing these issues will enable templ's usability in WASM environments, allow developers to leverage its strengths for building complex and interactive applications, with the added benefit of not having to deal with javascript focused build steps (node modules, dependency issues)
P.S. Apologies you were right about the watch flag causing the problems in my last issue :)
The text was updated successfully, but these errors were encountered:
Thanks for compiling your research into such a well written report. I'll take a read through, but want to give it the proper thinking time rather than rushing it, so won't be in the next couple of days.
Hello, a while back I promised to check back with findings on trying out templ inside a Wasm environment. So here are my findings:
Preface
Use Cases
Most of us coming from Go have the notion of Go as a backend language but when using Wasm things are totally different.
We now have a backend and platform agnostic frontend language and as such we can in theory use Go as a type safe compiled language in all browser environments with a few considerations. So the most viable use cases are as a web frontend for a fully fledged computer application, since in a localhost environment bundle sizes of 10MB+ do not matter. Also if your Go Wasm Application brings something powerful to the table you might get away with a load screen of a few seconds.
Examples
So I mentioned Wasm being agnostic of the backend means that you can use it inside a QT web view, Wails, possibly even Tauri or Electron if you wanted since with the net/http package and encoding/json you can communicate with all backends amicably. This opens up a wide array of possibilities, since the only real integration with the backend that your Wasm frontend needs is the same definition of the data model.
Workflow
While experimenting I used wails as a backend but found that while developing your frontend this is not the best approach since you don't want the extra overhead on the turnaround times that wails introduces, but simply using vite or any other capable development server is preferable, since the only thing we need is something that will give us access to our assets and data.
Problems
Event Handling
In wasm you basically have two choices for event handling:
templ
Assumptions
in templ it is assumed that the html is created by the server which means that all the scripts that we create and special constructs like the script directive in templ templates are correctly evaluated and executed.
Reality
Component wide the html gets delivered in a string builder and then set to the components html element with a snippet like this:
This way the containing script will not be evaluated which renders most JS examples in templ.guide useless.
So the only way to make it work is by applying the script separately like so:
Issue
I have not found a way to construct a javascript call dynamically like
The quotation marks keep the variable from being evaluated and single quotes don't work either. I could be wrong but I don't see any way how to dynamically create parameters to give context to an event besides looking for custom attributes in the event target element.
If that is by design and intended forgive my ignorance but since JS conversions are costly I thought a string based approach would be much more practical especially when you consider that the receiver might be a fantastic javascript library that does not know anything about your custom data attributes.
Build Tags
To be able to use syscall/js package one has to specify build tags like so.
//go:build js && wasm
In a wasm environment it is totally acceptable and even a crucial feature to use other go files in the same package space as the generated template files to host utility functions and generally not pollute the template with lengthy code.
But this is only possible when they both share the same build tags also imports won't work if they don't share compatible build tags.
So when generating the go file build tags must either must be respected or if that is a problem at least there should be a command line flag like
that prepends the build tag separated with a newline from the "Do not edit" comment.
tldr;
Go, traditionally a backend language, takes on a new role in the WASM environment. It becomes a platform-agnostic frontend language capable of powering rich web applications. This shift opens possibilities for using Go in various contexts, including:
Development Workflow
While frameworks like Wails offer integrated development, a simpler setup with tools like
vite
can be more efficient for frontend development. This approach focuses on rapid iteration and asset management.Dynamic JavaScript Calls
Constructing dynamic JavaScript calls with
templ
is problematic due to quotation mark escaping issues. This limits the ability to pass context to event handlers, potentially hindering integration with JavaScript libraries.Finding a way to manage javascript in a centralized way would be beneficial for everyone using templ since that would solve innerHTML issues and improve JS Code organization. I will not propose a solution since this is out of scope of this writeup.
Build Tags
Using the
syscall/js
package requires specific build tags://go:build js && wasm
This poses challenges when:
Proposed Solution
Introduce a command-line flag to templ for specifying build tags in generated files:
This would prepend the specified build tag to the generated Go files, ensuring compatibility and code organization.
Conclusion
Addressing these issues will enable templ's usability in WASM environments, allow developers to leverage its strengths for building complex and interactive applications, with the added benefit of not having to deal with javascript focused build steps (node modules, dependency issues)
P.S. Apologies you were right about the watch flag causing the problems in my last issue :)
The text was updated successfully, but these errors were encountered: