Hello, could you please explain me, why is the js file after compilition with -d:release so big?
Example: nim about 60 loc (2 kb) makes js of about 1.200 loc (75 kb). The compiler offers already static typing and the generation of one file (no npm tool), what is really helpful. A compiled typescript code is almost the same as js code.
Is the execution of the js code faster?
Are there runtime checks in js code? If so why is this necessary?
This has been talked about to death so it would be better if you gave concrete code https://forum.nim-lang.org/search?q=js%20kb
Yes there are runtime checks because JS barely has them (as with C), JS hides errors behind undefined and NaN and Nim checks for overflows and Nim has types like range that need runtime checks etc etc. You can get rid of runtime checks with -d:danger.
Also the Nim string type is represented differently from the JS string type so there is code to convert between the two (you can still use the JS string type with cstring). Same applies to many native types in Nim.
On top of all of these, the JS generated by Nim is mangled and has a lot of redundancy for good measure, it shrinks down by a lot if you minify it or gzip it or whatever 500 things you can do. And yes the redundancy actually makes it faster sometimes because it avoids JS's dynamic typing mechanisms (for example, var tmp = a; if (!b) tmp = false instead of a && b which ends up being faster)
The reason the JS backend works in Nim is that it has the best and most comfortable conditional compilation/metaprogramming of any language I know. Not to mention other languages that compile to JS are designed to run on a VM and won't have nearly the same native performance.
Thank you the base information.
My code:
File: renlite_core.nim
import dom
type
ListenerFunc = proc (e: Event) {.closure.}
proc createEventBus*(eventName: cstring) {.exportc.} =
document.appendChild(document.createComment(eventName))
proc eventGet*(eventName: cstring): Node {.exportc.} =
var nodes: seq[Node] = document.childNodes
for node in nodes:
if node.nodeValue == eventName:
result = node
proc eventOn*(eventName: cstring, eventType: cstring, eventListener: ListenerFunc) {.exportc.} =
var eventTarget: EventTarget = eventGet(eventName)
if eventTarget != nil:
eventTarget.addEventListener(eventType, eventListener)
proc eventEmit*(eventName: cstring, eventType: cstring, detail: Node) {.exportc.} =
var eventTarget: EventTarget = eventGet(eventName)
if eventTarget != nil:
let event = newEvent(eventType)
eventTarget.dispatchEvent(event)
window.emit = eventEmit
File: app.nim
import dom
import strformat
import renlite_core
## import sugar
proc update(e: Event) {.exportc.} =
echo "hello"
echo e.type
proc init() {.exportc.} =
## EventBus
createEventBus("app");
eventOn("app", "Save", update);
eventOn("app", "Clear", update);
proc App(): cstring {.exportc.} =
var html = fmt"""
<div>
<button id="010" onclick="emit('app', 'Save', this);" aria-label="button"
class="button button--emphasized button--compact">Save
</button>
</div>
<div>
<button id="011" onclick="emit('app', 'Clear', this);" aria-label="button"
class="button button--transparent button--compact">Clear
</button>
</div>
"""
result = cstring(html)
proc createApp(ev: Event) {.exportc.} =
document.body.innerHTML = App()
## init and load app
init()
window.onload = createApp
Replace the std/strformat with std/strutils or just add. Replace the echo with std/jsconsole and use console.log. Compile with -d:danger.
A compiled typescript code is almost the same as js code.
Nim is not the same as Typescript, Nim has run-time safety in the generated JS by default, TS has no such features, and is therefore more unsafe at run-time.
Give a try to https://github.com/juancarlospaco/nodejs#documentation we got https://juancarlospaco.github.io/nodejs/nodejs/jsstrformat.html
echo is only debuging and can be replaced with std/jsconsole.
I am not sure if I can use std/strutils instead of std/strformat. What I try to do is to use the declarativ way of html and need interpolation in the multiline string to include a page or component. Like template literals and ${expressions} in js. I have a working prototype in js but would prefer a static typed multi purpose lang for the browser, like Nim. Thanks for the hints and explenation.
Like template literals and ${expressions} in js.
Literally this https://juancarlospaco.github.io/nodejs/nodejs/jsstrformat.html
Why would you use something optimized for JS in your backend...? Just do something like this if you really want, but also ew.
template withJsFmt(def: untyped, body: untyped): untyped =
when defined(def):
jsfmt: body
else:
body
withJsFmt(javascript): doAsesert fmt "" == ""
And that is completely unrelated to your original question.
The native target is different from the browser target, in native target you do not get more performance for less LOC.
And in browser target this whole discussion is kinda pointless too, because Nim can compile to WASM, thats probably faster than JS.