Serve Kotlin/JS distribution as static assets in Kotlin/JVM project with Ktor

I have the following project structure:

MyProjectBuiltWithGradle
|- MyClientKotlinJSModule
|- MyServerKotlinJVMModuleWithKtor

What is the best way to take the assets produced by MyClientKotlinJSModule (resources + compiled JS file which includes my code and the Kotlin/JS runtime) and serve them as static content using Ktor as part of the MyServerKotlinJVMModuleWithKtor with either Kotlin 1.3.71 or 1.4-M1?

I do something similar with Kotlin 1.3.71 in a multiplatform project with a JS frontend and a JVM backend with Ktor. During development I just run the backend on its own using a JavaExec task:

register<JavaExec>("jvmServerRun") {
    classpath = output.allOutputs + configurations["jvmRuntimeClasspath"]
    main = "io.ktor.server.netty.EngineMain"
}

and serve the frontend using Webpack DevServer with a proxy:

browser {
    runTask {
        devServer = devServer?.copy(
            port = 8088,
            proxy = mapOf("/api" to "http://localhost:8080")
        )
    }
}

When I want to deploy everything I want to serve the frontend from the Ktor server. To achieve this I copy the generated JS bundle and resources (index.html + source map) to a sub folder of the processed resources of the JVM distribution before I build the fat jar for the server:

    register<Copy>("copyJsBundleToKtor") {
        from("$distsDir")
        into("$buildDir/processedResources/jvm/main/web")
    }

    register("stage") {
        dependsOn("jsBrowserProductionWebpack", "copyJsBundleToKtor", "fatJar")
    }

    named("copyJsBundleToKtor") {
        mustRunAfter("jsBrowserProductionWebpack")
    }

    named("fatJar") {
        mustRunAfter("copyJsBundleToKtor")
    }

And then Ktor serves the JS parts using a static route:

routing {
    static("/") {
        resources("web")
        defaultResource("web/index.html")
    }

Sorry for bumping an old topic here, but this thread is surfaced by Google when searching for this topic, and I feel like an updated response would be useful.

An example of doing this is here: GitHub - Kotlin/full-stack-web-jetbrains-night-sample: Full-stack demo application written with Kotlin MPP.

See specifically these lines in the client build:

And these lines in the server build:

and

and

However before using this as-is, note this issue I just created: Security: Static client resources are loaded from the root package, giving access to the entire backend jar · Issue #15 · Kotlin/full-stack-web-jetbrains-night-sample · GitHub.

1 Like