Kotlin 1.3.20搭配Gradle 5.1.1如何用compileKotlin2Js.execute()实现JS热重载?
这个问题我在升级Gradle版本时也碰到过,核心原因是Gradle 5.x开始对任务执行的API做了严格规范,直接调用任务的execute()方法已经不再是推荐做法——它会绕过Gradle的任务依赖管理和输入输出初始化流程,导致AbstractKotlinCompile任务要求的非空inputs参数为null,从而抛出异常。
下面给你两种可行的解决方案,都是符合Gradle 5.x规范的:
方案一:使用Gradle官方的连续构建(推荐)
Gradle本身提供了连续构建功能,完全可以替代你自定义的watch任务,而且更稳定可靠。你只需要在命令行执行:
./gradlew compileKotlin2Js --continuous
这条命令会让Gradle自动监听compileKotlin2Js任务的所有输入文件(也就是src/main下的Kotlin源码),一旦文件发生变化,就会自动触发重新编译,完美实现JS热重载的效果。
这种方式不需要编写任何自定义任务,完全利用Gradle内置机制,不会有任何兼容性问题。
方案二:自定义watch任务(如需额外逻辑)
如果你确实需要在watch过程中添加自定义逻辑(比如编译后复制文件到特定目录),可以通过任务依赖的方式实现,绝对不要直接调用execute():
task watch { // 让watch任务依赖compileKotlin2Js,Gradle会自动处理任务的输入输出初始化 dependsOn(tasks.compileKotlin2Js) // 让watch任务监听compileKotlin2Js的输入文件,确保文件变化时触发执行 inputs.files(tasks.compileKotlin2Js.inputs.files) doLast { // 这里可以添加你的自定义逻辑,比如: // copy { from(tasks.compileKotlin2Js.outputs.files) into("dist/js") } println("JS重新编译完成!") } }
然后执行命令启动watch:
./gradlew watch --continuous
这样Gradle会正确管理任务的生命周期,初始化所有必要的参数,不会再出现inputs为null的报错,同时也能实现文件变化时自动编译的效果。
为什么之前的方式在Gradle 4.x能运行?
Gradle 4.x对任务execute()方法的参数校验没有那么严格,即使inputs未初始化也能勉强执行,但这其实是不符合Gradle设计规范的“hack”写法,Gradle 5.x修复了这个漏洞,强制要求任务执行前必须完成输入输出的初始化,所以旧代码就报错了。
内容的提问来源于stack exchange,提问作者AlexO

