6.2.2.9 Kotlin/JS 编译器特性

原文链接: https://kotlinlang.org/docs/js-ir-compiler.html

6.2.2.9 Kotlin/JS 编译器特性

Kotlin/JS 包含一些编译器特性,用于在性能、体积和开发速度方面优化代码。这通过编译过程实现:编译器先把 Kotlin 代码转换为中间表示(IR),然后再生成 JavaScript 代码。

顶层属性的惰性初始化

为了获得更好的应用启动性能,Kotlin/JS 编译器会惰性初始化顶层属性。这样,应用加载时不会初始化代码中用到的所有顶层属性,而只初始化启动时需要的那些;其他属性会在实际运行到使用它们的代码时才获得值。

1
2
3
4
5
val a = run {
    val result = // 大量计算
    println(result)
    result
} // 值会在首次使用时才计算

如果由于某种原因你需要在应用启动时就急切地初始化某个属性,请用 @EagerInitialization{nullable=“true”} 注解标记它。

开发用二进制的增量编译

Kotlin/JS 编译器提供了开发用二进制的增量编译模式,可以加快开发过程。在该模式下,编译器会在模块级别缓存 compileDevelopmentExecutableKotlinJs Gradle 任务的结果。在后续编译中,它会为未改动的源文件复用缓存的编译结果,从而让编译更快完成,改动较小时尤其明显。

增量编译默认启用。要禁用开发用二进制的增量编译,请在项目的 gradle.properties 或 local.properties 中添加以下行:

kotlin.incremental.js.ir=false // 默认为 true

注意: 在增量编译模式下,干净构建通常会更慢,因为需要创建并填充缓存。

生产环境中成员名的名称缩短

Kotlin/JS 编译器会利用其内部关于 Kotlin 类和函数关系的信息,实施更高效的名称缩短,缩减函数名、属性名和类名。这会减小最终打包应用的体积。

这种名称缩短会在你以生产模式构建 Kotlin/JS 应用时自动应用,并且默认启用。要禁用成员名缩短,请使用 -Xir-minimized-member-names 编译器选项:

1
2
3
4
5
6
7
8
9
kotlin {
    js {
        compilations.all {
            compileTaskProvider.configure {
                compilerOptions.freeCompilerArgs.add("-Xir-minimized-member-names=false")
            }
        }
    }
}

死代码消除

死代码消除(DCE)通过移除未使用的属性、函数和类来减小生成的 JavaScript 代码体积。

未使用的声明可能出现在以下情况中:

  • 某个函数被内联,且从未被直接调用(除少数情况外,这总会发生)。
  • 某个模块使用了共享库。如果没有 DCE,你不使用的那部分库仍然会被包含在生成的包中。例如,Kotlin 标准库包含用于操作列表、数组、字符序列的函数,以及 DOM 适配器等等。所有这些功能作为 JavaScript 文件大约需要 1.3 MB。而一个简单的 “Hello, world” 应用只需要控制台相关的例程,整个文件只有几 KB。

在 Kotlin/JS 编译器中,DCE 是自动处理的:

  • 在开发打包任务中 DCE 被禁用,这些任务对应以下 Gradle 任务:

  • jsBrowserDevelopmentRun

  • jsBrowserDevelopmentWebpack

  • jsNodeDevelopmentRun

  • compileDevelopmentExecutableKotlinJs

  • compileDevelopmentLibraryKotlinJs

  • 其他名称中包含 “development” 的 Gradle 任务

  • 如果构建的是生产包,则启用 DCE,这对应以下 Gradle 任务:

  • jsBrowserProductionRun

  • jsBrowserProductionWebpack

  • compileProductionExecutableKotlinJs

  • compileProductionLibraryKotlinJs

  • 其他名称中包含 “production” 的 Gradle 任务

使用 @JsExport 注解,你可以指定希望 DCE 视为根的声明。