【问题标题】:Idiomatic Kotlin2JS Gradle setup惯用的 Kotlin2JS Gradle 设置
【发布时间】:2019-08-09 11:11:06
【问题描述】:

我想在 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 的代码 sn-p 在 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 和它引用的@​​987654325@ 描述了另一种帮助 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 文件并将它们放入我的输出目录。我可以想象这会奏效,但我还不愿意接受这是解决问题的最佳方式,没有更精简的方式来实现这一结果。

【问题讨论】:

    标签: javascript gradle kotlin


    【解决方案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'),
          }
      
      };
      

    【讨论】:

      猜你喜欢
      • 2019-06-26
      • 1970-01-01
      • 1970-01-01
      • 2014-03-12
      • 2016-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多