惯用的 Kotlin2JS Gradle 设置
Posted
技术标签:
【中文标题】惯用的 Kotlin2JS Gradle 设置【英文标题】:Idiomatic Kotlin2JS Gradle setup 【发布时间】: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。它还将buildscript
与apply 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 文件并将它们放入我的输出目录。我可以想象这会奏效,但我还不愿意接受这是解决问题的最佳方式,没有更精简的方式来实现这一结果。
【问题讨论】:
【参考方案1】:可以使用 Webpack 来创建包含所有依赖项的单个 JS。
https://github.com/eggeral/kotlin-single-js-file-lib 展示了一个完整的例子
确保 KotlinJS 编译器使用 webpack 可以理解的模块系统。
tasks.withType<Kotlin2JsCompile>
kotlinOptions
moduleKind = "umd"
将所有依赖复制到构建目录中的某个位置
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")
使用 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"))
确保一切都在gradle build
上执行
tasks
named("webpack") dependsOn("assembleJsLib")
assemble dependsOn("webpack")
为 Npm 创建一个最小的package.json
。
"devDependencies":
"webpack": "^4.29.0",
"webpack-cli": "^3.2.1"
创建一个最小的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'),
;
【讨论】:
以上是关于惯用的 Kotlin2JS Gradle 设置的主要内容,如果未能解决你的问题,请参考以下文章
Android开发:《Gradle Recipes for Android》阅读笔记(翻译)6.1——推荐配置