Js output bloat
Summary
Remove dead code from the JS output.
Description
import std/dom
document.getElementById("foo").value = "bar"
expected:
document.getElementById("foo").value = "bar";
got: 720 lines of JS
tried adding {.nodecl.} to the definition of getElementById
import std/dom except getElementById
proc getElementById*(d: Document, id: cstring): Element {.importcpp, nodecl.}
document.getElementById("foo").value = "bar"
this saves 80 lines (function definitions)
but remains 640 lines of unused object definitions
var NTI587202750 = {size: 0,kind: 25,base: null,node: null,finalizer: null};
var NTI587202747 = {size: 0,kind: 25,base: null,node: null,finalizer: null};
var NTI587202746 = {size: 0, kind: 18, base: null, node: null, finalizer: null};
var NTI587202657 = {size: 0, kind: 22, base: null, node: null, finalizer: null};
var NTI587202749 = {size: 0, kind: 18, base: null, node: null, finalizer: null};
...
Why is nim producing this bloat ? I can imagine people being pushed away by this. Whether this is rational or not is debatable.
Alternatives
No response
Standard Output Examples
No response
Backwards Compatibility
No response
Links
No response
Why is nim producing this bloat ?
They are type infos kept for inheritance.
I didn't ask for them.
I cannot reproduce.
import std/dom
document.getElementById("foo").value = "bar"
with -d:release, it generates
/* Generated by the Nim Compiler v1.7.1 */
var framePtr = null;
var excHandler = 0;
var lastJSError = null;
document.getElementById("foo").value = "bar";
Sorry I was using a build system where -d:nodejs was set.
Still you can see the same problem in dochack.js. I don't understand the need for these type definitions to be kept in the final output.
They are actually type infos kept for copying, to emulate Nim value type semantics.
The compiler generally doesn't generate code it doesn't use, but I don't know if this is true for type information.
These type definitions are supposed to be equivalent to those of the Javascript API, don't they ? Nim has the types defined (e.g in dom.nim), can it use them for generating code without actually keeping them in the final output ?
The resulting output (specialized function for each type) could be larger than just using type information.
https://github.com/nim-lang/Nim/issues/16144#issuecomment-734202467
You would get much better JS output by making the JS codegen use
injectdestructors.nimand replacing the NimCopy calls by the moves it instead produces. Nim's move semantics are very nice for the JS codegen too.
Is this planned for v2 ?
if you want to remove dead JS code in the output then just use Google's closure compiler
I'm aware of Google's closure compiler, I could as well just write js by hand or using typescript. The issue is about nim's js output.
making the JS codegen use injectdestructors.nim
It seems to already do this specifically, unsure if it uses move semantics in general as much as it can.
I could as well just write js by hand or using typescript.
Well yeah, Nim isn't meant to be a drop-in replacement for JS. It's just a demonstration in this repo. The main use of compiling to JS is using the same code on multiple platforms. If people can find JS output optimizations that don't impede on compiler performance and can be done, then great, but it's not really a priority otherwise, and it won't really help that much.
My 400 kb game script with -d:release goes down to 166 kb with basic minification (mostly whitespace removed) and 20 kb when gzipped. Stuff like obfuscation would bring it down even more (mangled names are long). It goes down this much because Nim doesn't do much wrong other than add redundancy to the JS output for its own benefit, and that redundancy can be removed by using tools for optimizing regular JS. Trying to get rid of the redundancy through the compiler will just hinder it.
Also:
I can imagine people being pushed away by this.
Are there alternatives (i.e. languages that compile to more than just JS) that do better?
The output is not particularly "bloated".