Replies: 5 comments 3 replies
-
Hot module reloading / fast refresh is certainly a nice feature to have, but to be honest I have no idea how to even approach implementing it. Webpack's documentation on this appears inscrutable, although it could be just me, I'm not strong in tooling. Intuitively, I suspect that it's either very hard or impossible to implement true and correct HMR for Laminar because
Some people use Laminar with live reload, i.e. have the whole page reload on code changes. I hear that Vite is a lot faster than Webpack for this. Personally I don't even use live reload on my own Laminar code. I used to swear by HMR when I was coding in Javascript, because there isn't any other way to be sure what your code is doing, but with Scala's strict type system, 90% of the time it's the compiler telling me what's wrong, not the browser. The one place where this approach does not work is CSS – pixel pushing requires many iterative visual checks pretty much by definition. So I do hot-reload CSS. Mine is generated by LESS CSS, and is a completely separate pipeline from Scala.js compilation / bundling, so changes are applied lightning fast. I think realistically this plus live reloading the code is the best we can have, unless I am gravely mistaken about what's needed to implement HMR. |
Beta Was this translation helpful? Give feedback.
-
feel like I could give working on this a shot, package Main
import com.raquo.laminar.api.L.{*, given}
import org.scalajs.dom
import scala.scalajs.js
import js.JSConverters.*
import scala.scalajs.js.annotation.*
import util.control.Exception.*
import com.raquo.laminar.nodes.ParentNode
import com.raquo.airstream.state.Var
object Element {
@JSExportTopLevel("nameVar")
val nameVar: Var[String] = {
js.`import`.meta.hot.accept(() => {})
Var(initial = "Wellm")
}
@JSExportTopLevel("element")
val element: HtmlElement = {
val elNode = div(
label("Your name: "),
input(
onMountFocus,
placeholder := "Enter your name here",
onInput.mapToValue --> nameVar,
value <-- nameVar
),
span(
"Hello, ",
child.text <-- nameVar.signal.map(_.toUpperCase)
)
)
js.`import`.meta.hot.accept((newModule: js.Dynamic) => {
val newElNode: HtmlElement =
newModule.$t_LMain_Element$__element.asInstanceOf
elNode.maybeParent.map(p =>
ParentNode.replaceChild(
p,
elNode,
newElNode
)
)
val newNameVar: Var[String] =
newModule.$t_LMain_Element$__nameVar.asInstanceOf
newNameVar.set(
allCatch
.opt(js.`import`.meta.hot.data.namedVar.asInstanceOf[String])
.getOrElse("123")
)
})
js.`import`.meta.hot.dispose(() => {
js.`import`.meta.hot.data.namedVar = nameVar.now()
})
elNode
}
}
object App {
@JSExportTopLevel("mount")
def mount(): Unit = {
val appContainer = dom.document.querySelector("#app")
render(appContainer, div(Element.element))
}
} it ended up taking me around 10 hours to navigate Laminar/Vite/Rollup/Scalajs documentation and build that example, but it works |
Beta Was this translation helpful? Give feedback.
-
surely keeping all state would be nice, but just replacing the modified components is 90% of the experience you get with React, since only the module you're editing will update and loose state |
Beta Was this translation helpful? Give feedback.
-
Whoa that's just RAD! Never thought I'd see this working with Laminar, even if a PoC. My thoughts, looking at this, and having read the very good svelte HMR doc:
Am I thinking about this right? |
Beta Was this translation helpful? Give feedback.
-
One of the nicest things about UI development in the Clojure and Javascript world is a feature that is usually called "fast refresh", and that is the ability to change the source code without losing the state on the page, this is specially useful when editing heavily nested components, removing the need to refresh the page and repeat every step to get into that component and see how it changed.
I would love to see some feature akin to that in laminar, this feature would also require some work on the bundler/devServer side.
https://www.snowpack.dev/concepts/hot-module-replacement
https://reactnative.dev/docs/fast-refresh
facebook/react#16604 (comment)
Beta Was this translation helpful? Give feedback.
All reactions