Trying to create a NPM package with kotlin multiplatform plugin

Hello,

I’ve been trying to establish a Gadle build that’s using kotlin multiplatform plugin as it seems to be the newest and “the right” way (at least at the time of writing) of doing it.

So my goal is simple: create a NPM package from within the Kotlin sources with the multiplatform plugin. So far my build.gradle looks like that:

buildscript {
    ext.kotlin_version = '1.3.40'
    ext.spek_version = '2.1.0-alpha.0.10+cc4a596'

    repositories {
        jcenter()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.3.40'
}

group 'com.test'
version '0.0.1'

sourceCompatibility = 1.8

repositories {
    jcenter()
    mavenCentral()
    maven { url "https://dl.bintray.com/spekframework/spek-dev" }
}

repositories {
    mavenCentral()
}

kotlin {
    jvm()
    js {
    }.compilations.all {
        kotlinOptions.moduleKind = "commonjs"
        kotlinOptions.sourceMap = false
        kotlinOptions.outputFile = "$project.buildDir.path/js/packages/${project.name}/lib/my_lib.js"
        kotlinOptions.main = "noCall"
        kotlinOptions.metaInfo = true
    }

sourceSets {
        commonMain {
            dependencies {
                implementation kotlin('stdlib')
                implementation kotlin('stdlib-common')
            }
        }
        commonTest {
            dependencies {
                implementation kotlin('test-common')
                implementation kotlin('test-annotations-common')
                implementation "org.spekframework.spek2:spek-dsl-metadata:$spek_version"
            }
        }

        jvmMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
            }
        }

        jvmTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test'
                implementation "org.spekframework.spek2:spek-dsl-jvm:$spek_version"

                runtimeOnly "org.spekframework.spek2:spek-runner-junit5:$spek_version"
                runtimeOnly 'org.jetbrains.kotlin:kotlin-reflect'
            }
        }

        jsMain() {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-js'
            }
        }

        jsTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test-js'
                implementation "org.spekframework.spek2:spek-dsl-js:$spek_version"
            }
        }
    }
}

jvmTest {
    useJUnitPlatform {
        includeEngines 'spek2'
    }
}

task packageJSON(){
    doLast {
        new File("$buildDir/js/packages/${project.name}", "package.json").text = """{
  "name": "my lib",
  "version": "$version",
  "main": "./lib/my_lib",
  "dependencies": {
    "kotlin": "^$kotlin_version"
  }
}
"""
    }
}

I feel there’s a lot of hacks in this file, but I’m completely unaware of how to improve them. It seems the best source of truth is the Kotlin repository, but I’m not yet so proficient to learn straight from the source code. It is difficult to find any information regarding this issue, so I’m wondering:

  • Is it the right approach of building a NPM package? In the future I’m also planning other supported platforms, hence the multiplatform plugin.
  • I’m creating package.json manually. Is there a better way of doing it?

Hello. The documentation is not ready yet, we’re working on it: https://youtrack.jetbrains.com/issue/KT-32137

I just tried it myself with the latest Kotlin plugin EAP: Kotlin 1.3.60 Early Access Preview (New project → Multiplatform Library):

3:26:48 PM: Executing task 'compileKotlinJs'...


> Configure project :
Kotlin Multiplatform Projects are an experimental feature.

> Task :jsPackageJson UP-TO-DATE
> Task :kotlinNodeJsSetup SKIPPED
Download https://github.com/yarnpkg/yarn/releases/download/v1.15.2/yarn-v1.15.2.tar.gz
> Task :kotlinNpmInstall
> Task :compileKotlinJs

BUILD SUCCESSFUL in 17s

Then look in build/js/packages/mpp-js: the package.json file is generated automatically. Does it work for you?

Connected to this question and the automatically generated package.json.

I have a library and an application project, two separated git repositories, both multiplatform, JS and JVM.

I’ve declared the lib as a dependency in the app, but the automatically generated package.json contained the lib project as “lib-js”, not as “lib”, so I’ve got all kind of strange errors about missing module from webpack. In IDEA everything looked fine, but jsBrowserRun failed.

Also, interestingly, the packages_imported had a “lib-js” directory instead of simple “lib”.

By adding a package.json to the “jsMain/resources” in the library project and setting the appropriate parameters manually I’ve been able to solve the dependency issue.

It is still not 100% because the resources are extracted into “packages_imported” without the directories they are in, but I’ve added a copy tasks to gradle to copy them from the lib project directly. It is really hackish, but works for now.

I think a kind of “cookbook” would be very useful for multiplatform as the resources are scarce and it takes a lot of time to figure out how to go on. Not a proper documentation, but something to give pointers where to look.