scala-dom-types
scala-dom-types copied to clipboard
Server Side Rendering
How can scala-dom-types api be used to render html on the server side (non js) ? eg,
val indexhtml = div("hello world")
val indexhtmlstr = indexhtml.toString
// then serve indexhtmlstr, eg, via http server.
though one other way would be to use the Laminar api .L._ , to build html and then render it via scala.js on node/graal on server side.
If you wanted to use Laminar for this, then yes, in principle you can use node with jsdom / graal / headless browser / etc. to render the HTML on the backend. Here's one approach using headless browser.
All of the above is useful if you want to share your HTML-generating code between frontend and backend, but it's overkill if you only want to generate some HTML on the backend. If that's the only thing you need, if you don't also need access to indexHtml variable from your scala.js code, then there's a simple way:
Instantiate the html tags and properties that you need, implementing def apply and def :=, an implicit conversion from String to Modifier, a toHtmlString method, etc. You don't need any JS environment for this, just keep track of element children and prop-value pairs yourself, and recursively compile all that into an HTML string when requested. To get started, you might want to look at some code from https://github.com/raquo/scala-dom-builder, although it does not contain a full solution to this, and it's burdened by a cross-platform setup which you don't need.
Also you might want to add some document-level tags like html, body and head if you need them.
Implementing any kind of rendering is out of scope for Scala DOM Types, but anyone so inclined could potentially make a library that would do this using the types defined here. This would be a nice addition.
Also if you implement toHtmlString yourself, be careful to encode the data correctly – quotes, angle brackets, etc. Otherwise the user data you render might end up breaking your website layout or giving you XSS.
Implementing any kind of rendering is out of scope for Scala DOM Types, but anyone so inclined could potentially make a library that would do this using the types defined here. This would be a nice addition.
Would there be some code to this end in Laminar already?
No, because Laminar does not compile HTML strings – it creates and updates DOM elements using JS DOM APIs which differentiate between structure and data, avoiding the problem.
See https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html for a quick cheatsheet, especially the Output Encoding section. It's not very instructive though, there are probably more comprehensive pages out there.
I should have mentioned it from the start but I forgot – ScalaTags already knows how to output HTML in a similar manner to what you want, so you might want to either use it instead, or look at its implementation – not just of how they do data encoding, but also the compilation of HTML in general. The data encoding method def escape is defined in Escaping.scala, see how it's used in their code.