Sean Keane
02/18/2020, 3:07 PMrequire("kotlin")
spierce7
02/18/2020, 3:55 PMspierce7
02/18/2020, 3:58 PMSean Keane
02/18/2020, 4:13 PMrequire(kotlin)
in the gradle dependency. If I add that I might strip everything and only bundle what is needed. This is a MPP project BTW.audriusk
02/18/2020, 5:45 PMSean Keane
02/18/2020, 5:50 PMSean Keane
02/18/2020, 6:20 PMModule not found: Can't resolve 'kotlin' in '/Users/seankeane/Development/test-dce-js/test-dce-js/node_modules/dce-test'
Eivind Nilsbakken
02/20/2020, 7:39 AM1.3.70-eap-184
, and it seems to only be available for the browser target. Granted, I'm not sure how it would work, since building a nodejs target doesn't actually seem to include the kotlin js library in the produced build, minified or not. ๐คEivind Nilsbakken
02/20/2020, 8:07 AMkotlin.js
in build/js/packages/my-package/kotlin-dce/kotlin.js
, if I add a browser target with dce (eg. browser { dceTask { ... } }
), which is significantly lighter. I could probably just bundle that with my npm module to make this work.Sean Keane
02/20/2020, 10:20 AMSean Keane
02/20/2020, 4:11 PMKotlin.js
. But your approach sounds exactly like what I need. Could you look over this and see if I am missing anything?
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.multiplatform")
id("org.jetbrains.kotlin.native.cocoapods")
id("kotlin-dce-js")
}
version = Versions.cocoapodVersion
kotlin {
cocoapods {
summary = "Shared Code for Android and iOS"
homepage = "Link to a Kotlin/Native module homepage"
}
android()
js() {
browser() {
@Suppress("EXPERIMENTAL_API_USAGE")
dceTask {}
}
}
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iOSTarget("ios") {
compilations {
val main by getting {
kotlinOptions.freeCompilerArgs = listOf("-Xobjc-generics")
}
}
}
sourceSets["commonMain"].dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:${Versions.coroutinesCore}")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:${Versions.serializationCommon}")
implementation("io.ktor:ktor-client-core:${Versions.ktor}")
implementation("io.ktor:ktor-client-json:${Versions.ktor}")
implementation("io.ktor:ktor-client-serialization:${Versions.ktor}")
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
}
sourceSets["iosMain"].dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:${Versions.coroutinesCore}")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:${Versions.serializationCommon}")
implementation("io.ktor:ktor-client-ios:${Versions.ktor}")
implementation("io.ktor:ktor-client-json-native:${Versions.ktor}")
implementation("io.ktor:ktor-client-serialization-native:${Versions.ktor}")
implementation("org.jetbrains.kotlin:kotlin-stdlib")
}
sourceSets["jsMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-js:${Versions.kotlin}")
implementation(kotlin("stdlib-js"))
}
}
android {
compileSdkVersion(App.compileSdk)
sourceSets {
getByName("main") {
manifest.srcFile("src/androidMain/AndroidManifest.xml")
java.srcDirs("src/androidMain/kotlin")
res.srcDirs("src/androidMain/res")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.coroutinesCore}")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:${Versions.serializationCommon}")
implementation("io.ktor:ktor-client-android:${Versions.ktor}")
implementation("io.ktor:ktor-client-json-jvm:${Versions.ktor}")
implementation("io.ktor:ktor-client-serialization-jvm:${Versions.ktor}")
implementation("androidx.lifecycle:lifecycle-extensions:${Versions.lifecycleVersion}")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.lifecycleVersion}")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}
Eivind Nilsbakken
02/20/2020, 11:15 PMclean build
should produce (what looks like) a dce-d kotlin.js
in build/js/packages/tabletop-enums/kotlin-dce/kotlin.js
(at 109k without adding anything to dceTask { keep() } }
). I don't actually utilize it yet (and I also removed the kotlin dependency in my src/jsMain/resources/package.json
, so the generated code doesn't actually work at the moment.Eivind Nilsbakken
02/21/2020, 7:32 AMprocessDceJsKotlinJs
and jsJar
, which unzips the jar made by the nodejs
task into $buildDir
and copies the dce-d kotlin.js
into it. That way, it's easy to clean
, and easy to test locally with npm link
.
Something like this perhaps:
tasks {
register("buildNpm") {
doLast {
copy {
from(zipTree("$buildDir/libs/${rootProject.name}-js-$version.jar"))
into("$buildDir/npm")
}
copy {
from("$buildDir/js/packages/${rootProject.name}/kotlin-dce/kotlin.js")
into("$buildDir/npm")
}
}
}
named("buildNpm") {
dependsOn("jsJar", "processDceJsKotlinJs")
}
named("build") {
dependsOn("buildNpm")
}
}
Sean Keane
02/21/2020, 9:56 AMEivind Nilsbakken
02/21/2020, 10:48 AM@zeit/ncc
a couple of days ago, and that seemed to work with kotlin as a dependency (but of course still 2MB large). I guess I'd probably just have to include const kotlin = require("./kotlin.js");
in index.js
for it to work with generated kotlin DCE.Eivind Nilsbakken
02/21/2020, 10:52 AMSean Keane
02/21/2020, 10:56 AMEivind Nilsbakken
02/21/2020, 11:09 AMdceTask { keep(...) }
to see if that makes any difference. I'm just guessing though. It would be nice to hear from someone with greater knowledge of how DCE works.
I think there's syntax to import external libraries into kotlin code, but even if you use that on kotlin.js, I guess that would be dead code, and would probably be removed?
EDIT: I was thinking of `@JsModule`: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.js/-js-module/index.htmlSean Keane
02/21/2020, 11:13 AM(function (root, factory) {
if (typeof define === 'function' && define.amd)
define(['exports', 'kotlin'], factory);
else if (typeof exports === 'object')
factory(module.exports, require('kotlin'));
else {
if (typeof kotlin === 'undefined') {
throw new Error("Error loading module 'common'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'common'.");
}root['common'] = factory(typeof this['common'] === 'undefined' ? {} : this['common'], kotlin);
}
}(this, function (_, Kotlin) {
'use strict';
var hello;
Object.defineProperty(_, 'hello', {
get: function () {
return hello;
},
set: function (value) {
hello = value;
}
});
hello = 'HELLO WORLD';
Kotlin.defineModule('common', _);
return _;
}));
When DCE is applied it then becomes this, the variable hello is no longer able to be accessed through JS.
(function (root, factory) {
if (typeof define === 'function' && define.amd)
define(['exports', 'kotlin'], factory);
else if (typeof exports === 'object')
factory(module.exports, require('kotlin'));
else {
if (typeof kotlin === 'undefined') {
throw new Error("Error loading module 'common'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'common'.");
}root['common'] = factory(typeof this['common'] === 'undefined' ? {} : this['common'], kotlin);
}
}(this, function (_, Kotlin) {
'use strict';
var hello;
hello = 'HELLO WORLD';
}));
Sean Keane
02/21/2020, 11:18 AMI think there's syntax to import external libraries into kotlin code, but even if you use that on kotlin.js, I guess that would be dead code, and would probably be removed?
EDIT: I was thinking of `@JsModule`: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.js/-js-module/index.htmlย (edited)I was thinking of this also. Even if it just pulled the require(kotlin.js). Then when it comes to bundling that it should use the DCE'd version that we have but it would naturally pull the remote version. My JS understanding is sketchy but im making the break from the mobile world. So bear with me. ๐ I'm looking to create a shared lib across all 3 platforms, this is the last hurdle for me to build a POC
Eivind Nilsbakken
02/21/2020, 11:19 AMkotlin.js
from build/.../kotlin-dce.Sean Keane
02/21/2020, 11:21 AMEivind Nilsbakken
02/21/2020, 11:23 AMSean Keane
02/21/2020, 11:25 AMEivind Nilsbakken
02/21/2020, 11:27 AMtypeof exports === 'object'
to true
, and then tries to run require('kotlin')
, which is not your local kotlin DCE, but if that evaluation ran through to that else
, it would try to use the kotlin
variable that you already declared in your index.js
, I think.Eivind Nilsbakken
02/21/2020, 11:27 AMSean Keane
02/21/2020, 11:29 AMSean Keane
02/21/2020, 11:29 AMEivind Nilsbakken
02/21/2020, 11:36 AM.mjs
script and node --experimental-modules
to test imports.Eivind Nilsbakken
02/21/2020, 11:37 AM1.4.x
, which will hopefully solve this use-case properly.Sean Keane
02/21/2020, 11:41 AMSean Keane
02/21/2020, 11:44 AMEivind Nilsbakken
02/21/2020, 11:48 AMkotlin
to the dependencies in package.json
, but it kind of sucks that it makes it a 2MB dependency in a Javascript project that otherwise isn't using kotlin.Sean Keane
02/21/2020, 11:50 AMEivind Nilsbakken
02/21/2020, 11:50 AMrequire('kotlin')
to `require('./kotlin.js')`in the generated code, but that throws a new error TypeError: Kotlin.defineModule is not a function
, so that is apparently removed by DCE. Might work to add it to keep
.Eivind Nilsbakken
02/21/2020, 11:51 AMbuild/npm/tabletop-enums.js
manually.Sean Keane
02/21/2020, 11:53 AMEivind Nilsbakken
02/21/2020, 11:57 AMdceTask {
keep("kotlin.defineModule")
}
That actually works for me in my test branch now, except that I have to manually change kotlin
to ./kotlin.js
on line 5 in build/npm/tabletop-enums.js
. I can push my changes, so that you can take a look, if you want.Sean Keane
02/21/2020, 11:59 AMEivind Nilsbakken
02/21/2020, 12:02 PMSean Keane
02/21/2020, 12:03 PMEivind Nilsbakken
02/21/2020, 12:03 PM./link.sh
to build and npm link the project, then edit the aforementioned file, then run ./test.sh
to test it.Sean Keane
02/21/2020, 12:04 PMEivind Nilsbakken
02/21/2020, 12:04 PMEivind Nilsbakken
02/21/2020, 12:20 PMpackage.json
in a sub-directory of src/jsMain/resources
for that to work though, as I don't think you can point directly at the js-file.Sean Keane
02/21/2020, 12:21 PMSean Keane
02/21/2020, 4:34 PMSean Keane
02/21/2020, 6:03 PMtasks {
register("buildNpm") {
doLast {
copy {
from(zipTree("$buildDir/libs/YOUR_JAR"))
eachFile {
filter { line ->
line.replace("require('kotlin')", "require('./kotlin.js')")
}
}
into("$buildDir/npm")
}
copy {
from("${rootProject.buildDir}/js/packages/common/kotlin-dce/kotlin.js")
into("$buildDir/npm")
}
}
}
named("buildNpm") {
dependsOn("jsJar", "processDceJsKotlinJs")
}
named("build") {
dependsOn("buildNpm")
}
}
Eivind Nilsbakken
02/21/2020, 6:18 PMSean Keane
02/21/2020, 6:42 PMEivind Nilsbakken
02/22/2020, 7:21 AMEivind Nilsbakken
02/22/2020, 8:03 AMpublishToNpmLocal
, which is sort of an equivalent to the `publishToMavenLocal`task available from the maven-publish
plugin. Might be a good idea to add a publishToLocal
task to trigger both.Sean Keane
02/22/2020, 8:28 AMEivind Nilsbakken
02/22/2020, 8:36 AMpublishToMavenLocal
though, since it will be invalidated on a gradle clean
, but maybe that's not a big deal. ๐คSean Keane
02/22/2020, 8:38 AMEivind Nilsbakken
02/22/2020, 8:44 AMnpm unlink
or by rm
-ing the link, you only really need to execute buildNpm
on consecutive builds to see your changes immediately in projects that use that link.Eivind Nilsbakken
02/22/2020, 8:48 AMnpm link your-module
from other projects. More akin to the maven publish task. ๐ค I would have to read up on that though.Eivind Nilsbakken
02/22/2020, 8:53 AMSean Keane
02/22/2020, 9:02 AMEivind Nilsbakken
02/22/2020, 12:38 PMSean Keane
02/24/2020, 3:29 PMEivind Nilsbakken
02/24/2020, 10:55 PM