惯用的Kotlin2JS Gradle设置

时间:2019-03-19 01:12:04

标签: javascript gradle kotlin

我也想在Kotlin中编写一个JavaScript库,使用Gradle作为构建工具,并以Kotlin作为其配置语言。最后,我想得到一个可以用作独立库的JS文件,即将Kotlin库(其中的所有必需部分)捆绑到其中。

要使这项工作看起来像什么最少的设置?特别是,如何将Kotlin库捆绑在一起?


这是我到目前为止所拥有的。

https://kotlinlang.org/docs/tutorials/javascript/getting-started-gradle/getting-started-with-gradle.html
仅使用Groovy来配置Gradle。它还将buildscriptapply plugin语句结合使用,在这种情况下,我给人的总体印象是,这被认为是传统方法,而plugins部分将是首选方法。

https://kotlinlang.org/docs/reference/using-gradle.html#targeting-javascript
有Kotlin脚本。 settings.gradle的代码片段在Groovy和Kotlin之间没有切换,但是在我的settings.gradle.kts中无需修改就可以正常工作。这样会创建一个文件js/build/classes/kotlin/main/${project.name}.js,如下所示(带有moduleKind = "commonjs"):

(function (_, Kotlin) { … }(module.exports, require('kotlin')));

因此,我可以看到它包含我的源代码的转译版本,但它不会单独运行;它需要标准库的副本。我可以使用

将其添加为依赖项
dependencies {
    compile("org.jetbrains.kotlin:kotlin-stdlib-js")
    testImplementation("org.jetbrains.kotlin:kotlin-test-js")
}

,但是仅凭这一点还不足以使标准库最终出现在输出中。我想我也许可以使用kotlin npm package,但我更愿意将这些资源自动组合成一个。

我还尝试使用禁用noStdlib设置

tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile> {
    kotlinOptions {
        noStdlib = false
    }
}

包含相当多的猜测,因为执行此类操作的示例倾向于使用Groovy表示法和compileKotlin2Js块,如果我的构建脚本位于Kotlin中,则会导致语法错误。因此,有了上面的代码,我得到了一个编译器错误:

w: Unable to find kotlin-stdlib-js.jar in the Kotlin home directory.
Pass either '-no-stdlib' to prevent adding it to the classpath, or
the correct '-kotlin-home'

那么我该如何使用依赖项提供的标准库呢?这甚至是正确的方法吗?

https://blog.kotlin-academy.com/kotlin-js-configuration-made-simple-ef0e361fcd4和它引用的https://github.com/Kotlin/kotlin-frontend-plugin描述了另一种有助于Web开发的插件,但是同样,所有示例仅是Groovy的,我什至无法解决该插件。我尝试过类似的事情

plugins {
    id("org.jetbrains.kotlin.frontend").version("0.0.45")
}

repositories {
    jcenter()
    maven {
        url = java.net.URI("https://dl.bintray.com/kotlin/kotlin-eap")
    }
}

Another blog post建议使用一些Gist命令,据称这些命令将从依赖项中提取JavaScript文件并将其放入我的输出目录中。我可以想象这会起作用,但是我还不愿意接受这是解决问题的最佳方法,没有其他简化方法可以实现此结果。

1 个答案:

答案 0 :(得分:1)

可以使用Webpack来创建包含所有依赖项的单个JS。

https://github.com/eggeral/kotlin-single-js-file-lib显示了完整的示例

  1. 确保KotlinJS编译器使用webpack可以理解的模块系统。

    tasks.withType<Kotlin2JsCompile> {
        kotlinOptions {
            moduleKind = "umd"
        }
    }
    
  2. 将所有依赖项复制到构建目录中的某个位置

    task<Copy>("assembleJsLib") {
        configurations.compile.get().resolve().forEach { file: File ->
            from(zipTree(file.absolutePath), {
                includeEmptyDirs = false
                include { fileTreeElement ->
                    val path = fileTreeElement.path
                    (path.endsWith(".js") || path.endsWith(".js.map")) && (path.startsWith("META-INF/resources/") ||
                            !path.startsWith("META-INF/"))
                }
            })
        }
        from(tasks.withType<ProcessResources>().map { it.destinationDir })
        into("$buildDir/js")
    
        dependsOn("classes")
    }
    
  3. 使用com.moowork.node插件运行Webpack。

    import com.moowork.gradle.node.task.NodeTask
    
    plugins {
        id("kotlin2js") version "1.3.21"
        id("com.moowork.node") version "1.2.0"
    }
    
    node {
        download = true
    }
    
    task<NodeTask>("webpack") {
        dependsOn("npm_install")
        setScript(File("$projectDir/node_modules/webpack/bin/webpack"))
    }
    
  4. 确保在gradle build上执行所有操作

    tasks {
        named("webpack") { dependsOn("assembleJsLib") }
        assemble { dependsOn("webpack") }
    }
    
  5. 为Npm创建最小的package.json

    {
        "devDependencies": {
            "webpack": "^4.29.0",
            "webpack-cli": "^3.2.1"
        }
    }
    
  6. 创建最小的webpack.config.js

    const path = require('path');
    
    module.exports = {
        mode: 'development',
        devtool: 'source-map',
        entry: path.resolve(__dirname, 'build/classes/kotlin/main/kotlin-lib.js'),
        resolve: {
            "modules": [
                path.resolve(__dirname, 'build/js'),
                "node_modules"
            ]
        },
        output: {
            filename: "kotlin-lib.js",
            libraryTarget: "umd",
            path: path.resolve(__dirname, 'build/webpack'),
        }
    
    };