Hello, I have noticed that its possible to build c...
# compose-web
d
Hello, I have noticed that its possible to build compose multiplatform applications also on the html canvas. Given this answer from a while ago https://kotlinlang.slack.com/archives/CDFP59223/p1711475155817799?thread_ts=1711468799.065149&cid=CDFP59223 Is it correct that we can just drop the wasmJs target using js instead? Is
Copy code
fun main() {
    onWasmReady {
        CanvasBasedWindow("App Name") {
            // ...
        }
    }
}
still the current valid approach and do I understand correctly that it will run wasm when possible and js otherwise? Given, quote from above thread:
With current Kotlin versions you no longer need separate build configurations for JS and Wasm, so much easier now.
p
They are separate artifacts. You need to make logic for checking browser wasm support and if not fallback to js version by yourself in html page.
This is how i made it (replace 'app' (app.js and app.wasm.js) with your file name):
Copy code
<script type="text/javascript">
    const s=(s)=>{const e=document.createElement("script");e.src=s;e.type="text/javascript";e.defer=true;document.body.appendChild(e)}
    const w=WebAssembly;if(typeof w!=="undefined"&&typeof w?.validate==="function"&&
    w.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,8,2,95,1,120,0,96,0,0,3,3,2,1,1,10,14,2,6,0,6,64,25,11,11,5,0,208,112,26,11,0,45,4,110,97,109,101,1,15,2,0,5,102,117,110,99,48,1,5,102,117,110,99,49,4,8,1,0,5,116,121,112,101,48,10,11,1,0,1,0,6,102,105,101,108,100,48]))
    ){s("app.wasm.js")}else{s("skiko.js");s("app.js")}
</script>
Also add to gradle.properties this line:
Copy code
org.jetbrains.compose.experimental.jscanvas.enabled=true
o
Is it correct that we can just drop the wasmJs target using js instead?
No, as Paul said,
wasmJs
is an additional target.
do I understand correctly that it will run wasm when possible and js otherwise
No, there is no automatic fallback. The quote
With current Kotlin versions you no longer need separate build configurations for JS and Wasm, so much easier now.
was referring to the situation that in the old days, there was no way to have Compose UI (canvas) with the
js
and
wasmJs
targets in a uniform build configuration. As you can see in this diff there is lots of conditional configuration (
if (useJs) {
) in the older version of
build.gradle.kts
.
d
Alright, thanks. Why is
onWasmReady { ... }
necessary on js side?
o
Because the underlying Skia/Skiko graphics library always runs as a Wasm executable.
d
Now I'm a bit confused. Does that mean wasm is run on a js build as well?
o
With Compose UI on the Js target, yes, one thing still runs on Wasm: The low-level graphics layer of Skia. All composing, measuring, layout, drawing runs on Js. Your code using Compose also runs on Js.
d
Okay, but in this case it works on browsers like safari. While whole app in wasm currently wont. Right?
o
Yes, Skia has a different set of Wasm requirements, which makes it suitable for running on Safari. E.g. it doesn't depend on the Wasm/GC (garbage collector) feature.
👍 1
d
I'm currently trying to port a wasm js compose application to js and getting a
onWasmReady is not defined
error.
Copy code
Uncaught ReferenceError: onWasmReady is not defined
    at main (main.kt:23:6)
    at mainWrapper (shared.js:378:5)
    at Object.eval (shared.js:388:3)
    at eval (shared.js:5:35)
    at eval (shared.js:8:2)
    at ./kotlin/shared.js (shared.js:808:1)
    at __webpack_require__ (shared.js:887:32)
    at shared.js:1957:37
    at shared.js:1960:12
    at webpackUniversalModuleDefinition (shared.js:17:20)
I'm using the following gradle config for js:
Copy code
js(IR) {
        moduleName = "shared"
        binaries.executable()
        browser {
            commonWebpackConfig {
                outputFileName = "shared.js"
                cssSupport {
                    enabled.set(true)
                }
            }
        }
    }
p
What if you change to this:
Copy code
window.onload = {
            onWasmReady {...}
}
?
d
works, thanks