Is there any documentation on working with Webpack...
# javascript
s
Is there any documentation on working with Webpack in Kotlin 1.3.70?
s
Could you specify what exactly you mean by “working with webpack”? 🙂
s
In 1.3.70 there is a webpack task where you can give the webpack plugin some details, but a lot of the variables are
val
and cannot be reassigned. Im trying to point it to my webpack.config.d but not sure where to place it or how to even override its location. At the moment my webpack file is located in
src -> jsMain -> resources
This is the method im using to update the dir, but I think I should be using the
Entry
var instead
Copy code
open val configDirectory: File?
        @Optional @InputDirectory get() = project.projectDir.resolve("webpack.config.d").takeIf { it.isDirectory }
s
For pure Kotlin/JS projects, the
webpack.config.d
folder goes into the root of your project, with the additions you want to have for your target, with a file called
01.projectname.js
– you could try if it works the same for multiplatform (as I infer from your
jsMain
. @Ilya Goncharov [JB] – is it possible to set the
webpack.config.d
location via Gradle DSL already?
i
No, unfortunately
webpack.config.d
is hardcoded yet
s
Ill find the location and place the
webpack.config.d
file there for now
t
@Sean Keane Do you have duplicated script logic?
s
Not that I know of. I was looking to bundle everything with webpack since the npm script I have made seems to not be scalable. Also, since all the libs are jars on maven then it requires the building and treeshaking to be done in the creation of the lib, so everything needs to be bundled inclusive into the
common.js
lib. What I have noticed since, is webpack seems to be creating its own config and ignoreing the one I have placed in the path. I would like to know how I can override it so I can then point webpack to use the unpack’d jar libs and then treeshake those or use the DCE’d version.
What I am trying to achieve at the moment, is to use Webpack to bundle the lib. I’m following this guide from Webpack https://webpack.js.org/guides/author-libraries/ But what I’m finding is that the Webpack DSL plugin isn’t really happy to use my file. Not sure how to resolve but im reading over the code to see how it works.
t
For libraries it will be useful - (
commonjs
by default) https://github.com/turansky/kfc-plugins#library
💪 2
s
Hmmmmm…. this is interesting. Will it work with a multiplatform project?
👌 1
t
Webpack will be useful only for final stage when you will create
distribution
for npm.
s
Let me try it
t
Plugin will be more useful with
1.3.70
s
I’m currently running on 1.3.70
t
🙂
Do you use
maven-publish
for publication?
s
I do for Android and iOS
But we are looking to build client libs
@turansky Have you a webpack sample?
t
i
@Sean Keane Just note, that since 1.3.70 default webpack configuration includes
umd
library target, so you may not need some additional configuration to use it as JavaScript library. It is consistent with webpack atricle about
Authoring libraries
s
@Ilya Goncharov [JB] I was looking over it, but just cant seem to be able to build the lib. Am I missing something? Where do I put the config to point to the DCE’d
.js
files?
i
Since 1.3.70 by default webpack bundle dce’d js files, so it provide bundle js in
build/distributions
and it is compatible to run as an application, and as using as js library
s
So I can just npm publish what is in the
build/distributions
block? When I tried that I was getting issues earlier. I will retry
@turansky Seem to be having this issue when trying your approach
t
library
extension now enabled for
js
plugin only
s
Ok, so I cant use it with multiplatform just yet?
i
So I can just npm publish
You need add some kind of
package.json
and another npm stuff, but js is compatible to be npm package, yes
t
If you use
1.3.70
, than DCE plugin is redundant in your example
s
Ok. I have 4 files @Ilya Goncharov [JB]. When packaged, it says they are 6mb
t
js.map
is biggest?
s
Yep, comes in at 4.9mb
t
Do you need it?
s
No 😂 but even 1mb is very sizable
t
Do you need all library content?
s
This lib is only making 1 network request
t
Looks like nonconfigured DCE
s
Thats why I am a bit lost with how to point webpack to use the DCE’d version
t
It is default behaviour
i
Do you have sample of project? Or just gradle script? And do you use ktor?
s
@Ilya Goncharov [JB] As it stands, when I bundle the code into a npm module and use it in another project, I end up with this error
Copy code
Uncaught TypeError: m is not a function
    at Object.l (WebSocketSession.kt:24)
    at Object.<anonymous> (Chars.kt:35)
    at e (bootstrap:19)
    at Object.<anonymous> (collections.kt:15)
    at e (bootstrap:19)
    at Object.<anonymous> (_Collections.kt:1408)
    at e (bootstrap:19)
    at Object.<anonymous> (_Collections.kt:1408)
    at e (bootstrap:19)
    at bootstrap:83
i
Seems like this issue There is WA inside https://youtrack.jetbrains.com/issue/KT-36484
s
Copy code
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget

plugins {
    id("com.android.library")
    id("org.jetbrains.kotlin.multiplatform")
    id("org.jetbrains.kotlin.native.cocoapods")
}

kotlin {

    cocoapods {
        summary = "Shared Code for Android and iOS"
        homepage = "Link to a Kotlin/Native module homepage"
    }

    android()

    js() {
        targets {
            browser {
                @Suppress("EXPERIMENTAL_API_USAGE")
                dceTask {
                    keep("kotlin.defineModule")
                }
            }
        }
    }

    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(kotlin("stdlib-js"))
        implementation("io.ktor:ktor-client-js:${Versions.ktor}")
        implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:${Versions.coroutinesCore}")
        implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:${Versions.serializationCommon}")
        implementation(npm("text-encoding"))
    }
}

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")
    implementation("androidx.core:core-ktx:+")
}
i
If you use ktor, unfortunately it is known issue with ktor+dce
s
I just applied your Keep to the DCE part of my browser
2 minutes and ill let you know how the new lib looks
Ok, nothing can be accesses still.
I think I can see why. The common code that is used with everything bundled and DCE'd doesn't have the accessors for the variables. This is what caused myself and @Eivind Nilsbakken to come up with the script to merge the DCE'd libs and pull the unDCE'd common.js from our projects.
Copy code
/*!*****************************************!*\
  !*** ./kotlin-dce/common.js ***!
  \*****************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (root, factory) {
  if (true)
    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports, __webpack_require__(/*! kotlin */ "./kotlin-dce/kotlin.js"), __webpack_require__(/*! ktor-ktor-client-core */ "./kotlin-dce/ktor-ktor-client-core.js"), __webpack_require__(/*! kotlinx-coroutines-core */ "./kotlin-dce/kotlinx-coroutines-core.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
				__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
				(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  else {}
}(this, function (_, Kotlin, $module$ktor_ktor_client_core, $module$kotlinx_coroutines_core) {
  'use strict';
  var $$importsForInline$$ = _.$$importsForInline$$ || (_.$$importsForInline$$ = {});
  var Kind_CLASS = Kotlin.Kind.CLASS;
  var Kind_INTERFACE = Kotlin.Kind.INTERFACE;
  var getKClass = Kotlin.getKClass;
  var createKType = Kotlin.createKType;
  var Unit = Kotlin.kotlin.Unit;
  var COROUTINE_SUSPENDED = Kotlin.kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED;
  var CoroutineImpl = Kotlin.kotlin.coroutines.CoroutineImpl;
  var coroutines = $module$kotlinx_coroutines_core.kotlinx.coroutines;
  var lazy = Kotlin.kotlin.lazy_klfg04$;
  var takeFrom = $module$ktor_ktor_client_core.$$importsForInline$$['ktor-ktor-http'].io.ktor.http.takeFrom_jl1sg7$;
  var utils = $module$ktor_ktor_client_<http://core.io|core.io>.ktor.client.utils;
  var url = $module$ktor_ktor_client_<http://core.io|core.io>.ktor.client.request.url_3rzbk2$;
  var HttpMethod = $module$ktor_ktor_client_core.$$importsForInline$$['ktor-ktor-http'].io.ktor.http.HttpMethod;
  var HttpRequestBuilder_init = $module$ktor_ktor_client_<http://core.io|core.io>.ktor.client.request.HttpRequestBuilder;
  var HttpStatement_init = $module$ktor_ktor_client_<http://core.io|core.io>.ktor.client.statement.HttpStatement;
  var throwCCE = Kotlin.throwCCE;
  var equals = Kotlin.equals;
  var HttpResponse = $module$ktor_ktor_client_<http://core.io|core.io>.ktor.client.statement.HttpResponse;
  var complete = $module$ktor_ktor_client_<http://core.io|core.io>.ktor.client.statement.complete_abn2de$;
  var call = $module$ktor_ktor_client_core.io.ktor.client.call;
  var TypeInfo_init = $module$ktor_ktor_client_core.io.ktor.client.call.TypeInfo;
  var to = Kotlin.kotlin.to_ujzrz7$;
  var mapOf = Kotlin.kotlin.collections.mapOf_qfcya0$;
  var listOf = Kotlin.kotlin.collections.listOf_i5x0yv$;
  var copyToArray = Kotlin.kotlin.collections.copyToArray;
  var hello;
  var testMap;
  var testList;
  var testType;
  $$importsForInline$$['ktor-ktor-client-core'] = $module$ktor_ktor_client_core;
  hello = 'HELLO WORLD';
  testMap = mapOf([to('char', 'x'), to('char2', 'y'), to('string', 'zz')]);
  testList = listOf(['Hello', 'World']);
  testType = ['hello', 'javascript'];
  return _;
}));
t
DCE configuration required in any case. Otherwise DCE remove all (like in your example)
s
Ill set it up and see how it works out
@Ilya Goncharov [JB] I set up a really simple sample project with just JS. Im trying to export a variable called hello. But it cannot be used from JS when published with npm from the distribution section. Here it is. https://github.com/seank90/test-multiplatform-lib/tree/master
e
You need to replace
keep("kotlin.defineModule")
with
keep("multiplatform-lib.hello")
.
Just
keep("multiplatform-lib")
will work too. They updated the docs on this now: https://kotlinlang.org/docs/reference/javascript-dce.html#excluding-declarations-from-dce
i
Yes, maybe even
keep(“test-multiplatform-lib.hello”)
In usual case, you don’t need to keep
<http://Kotlin.de|Kotlin.de>fineModule
It can be safely removed by DCE
s
This worked. Thank you both. Tomorrow I will try it with a network request. 🙂
🤞 1
I have made it all work with a simple network request. But, the library is 2.8mb post production DCE. Is this expected? You can check it out in this project. https://github.com/seank90/test-multiplatform-lib/tree/master Branch is test-dce. If you just build you will get the output in distribution.
e
My guess is the size is due to these imports in the DCE-ed build referenced by webpack:
factory(module.exports, require('kotlin'), require('kotlinx-serialization-kotlinx-serialization-runtime'), require('ktor-ktor-client-core'), require('kotlinx-coroutines-core'), require('ktor-ktor-client-json'), require('ktor-ktor-client-serialization'));
DCE-ed versions of those libraries are in the same directory, but not used at all, it seems.
s
I wonder how we might get them towards using the DCE version of the libs. Do they needs to be referenced anywhere to use the DCE version. Its way too large to be viable at the moment
e
On second thought, the generated
webpack.config.js
adds the
kotlin-dce
directory to
config.resolve.modules
. In theory, that should work. 🤔
Or maybe it actually does. Looking at those js-files, they are pretty big, so they might not all have been DCE-ed.
i
By default it does. DCE works over JS, so it can be not so effective. DCE over Kotlin code is in progress in New compiler (since 1.4)
s
But that webpack file is generated automatically. Ill try placing a
webpack.config.js
file in the root and override the methods from there.
Is it possible to trial 1.4? are there any steps to test the reduction further