Hi everyone! I have a multiplatform app that uses ...
# multiplatform
s
Hi everyone! I have a multiplatform app that uses Compose Multiplatform for all targets, including web. Obviously, this come at the drawback of long loading times, and suboptimal accessibility and browser support. The app's UI is relatively simple, and has a well defined design system, so building the UI layer should be relatively easy to accurately remake and keep in sync. However, the bulk of the complexity is in the data layer and view models, but they're all built in a way that's agnostic to the UI implementation (e.g. exposing StateFlows) and do work on web without issues. Ideally, I'd like to use JS/TS with a mainstream framework to build it (Svelte/SvelteKit is a personal favorite), but still use all the underlying code through Kotlin/JS. This sounds pretty doable, but I'm a bit confused where to start. I've generated my project using the official KMP generator. On iOS for example, this is pretty trivial, just use the Kotlin code from the Swift side (in the
iosApp
folder) and it just works. Any help would be appreciated!
👀 1
1
n
If you started with the wizard it'll have everything in
composeApp
. You'll want to make a
shared
module with virtually all the same platform folders, code, and build.gradle. Make sure you see
include(":shared")
in
settings.gradle.kts
. If everything is green you should be able to build a JS module with the kotlin browser task
jsBrowserProductionWebpack
. There's some more tweaking you'll have to do but that should get you started. Your js block should look something like this:
Copy code
kotlin {
    js(IR) {
        moduleName = "shared"
        useEsModules()
        browser {
            commonWebpackConfig {
                outputFileName = "shared.js"
            }
            testTask {
                useKarma {
                    useChromeHeadless()
                }
            }
        }
        compilations["main"].packageJson {
            customField("types", "kotlin/shared.d.ts")
        }
        generateTypeScriptDefinitions()
        binaries.executable()
    }
If you do not plan on using WASM I would remove it from the project completely or it will cause you tons of headaches when pulling in dependencies. If you get it working you could publish your lib as an npm dependency and consume it in your web project.
One thing I just thought of; If you're not planning to use WASM at all, just remove it from
composeApp
. Check this out.
s
Thank you very much!! I've already replaced Wasm with JS (using Compose/Web with CanvasJS instead) since I use SQLDelight.
Now what I'm wondering about, is where to put all the regular, web-specific code (just a folder anywhere?), and how to make it aware of the shared code (as a local npm dependency). That's where I'm a bit unclear. Anyhoo, I'll muck around with it and report how it goes.
n
Run `./gradlew composeApp:jsBrowserProductionWebpack -Pversion={whatever-version}-mpm`then
npm i ~/your-proj/build/js/packages/composeApp
gratitude thank you 1
s
That clears it all up for me. Thanks a lot!
🙌 1
Spun up a little demo project to try this out, and it works like a charm:
K 1
The only problem is that I need to annotate literally every single file with
@file:JsExport
, but thankfully I noticed this post on #C0BJ0GTE2, where these guys automated that with a Compiler plugin! https://kotlinlang.slack.com/archives/C0BJ0GTE2/p1728813912690449
🧐 2
K 1
n
@Skaldebane thanks for sharing, that's an awesome plugin!
😄 1
💜 1