6.2.2.3 搭建 Kotlin/JS 项目
14 分钟阅读
6.2.2.3 搭建 Kotlin/JS 项目
Kotlin/JS 项目使用 Gradle 作为构建系统。为了让开发者轻松管理 Kotlin/JS 项目,我们提供了 kotlin.multiplatform Gradle 插件,它提供项目配置工具,以及用于自动化 JavaScript 开发常见例行工作的辅助任务。
该插件使用 npm 或 Yarn 包管理器在后台下载 npm 依赖,并使用 webpack 从 Kotlin 项目构建 JavaScript 包。依赖管理和配置调整大部分可以直接在 Gradle 构建文件中完成,同时也可以覆盖自动生成的配置以获得完全控制。
你可以在 build.gradle(.kts) 文件中手动把 org.jetbrains.kotlin.multiplatform 插件应用到 Gradle 项目:
Kotlin
| |
Groovy
| |
Kotlin Multiplatform Gradle 插件让你可以在构建脚本的 kotlin {} 块中管理项目的各个方面:
| |
在 kotlin {} 块中,你可以管理以下方面:
- 目标执行环境:浏览器或 Node.js
- 对 ES2015 特性的支持:类、模块和生成器
- 配置输出粒度
- 生成 TypeScript 声明文件
- 项目依赖:Maven 和 npm
- 运行配置
- 测试配置
- 浏览器项目的打包和 CSS 支持
- 目标目录和模块名
- 项目的
package.json文件
执行环境
Kotlin/JS 项目可以面向两种不同的执行环境:
- 浏览器,用于浏览器中的客户端脚本
- Node.js,用于在浏览器之外运行 JavaScript 代码,例如服务端脚本。
要为 Kotlin/JS 项目定义目标执行环境,请添加 js {} 块,并在其中放入 browser {} 或 nodejs {}:
| |
binaries.executable() 这条指令显式要求 Kotlin 编译器生成可执行的 .js 文件。省略 binaries.executable() 会让编译器只生成 Kotlin 内部库文件,这些文件可被其他项目使用,但无法单独运行。
提示: 这通常比创建可执行文件更快,在处理项目的非叶子模块时可能是一种优化。
Kotlin Multiplatform 插件会自动为所选环境配置相应的任务。这包括下载并安装运行和测试应用所需的环境与依赖。这让开发者无需额外配置就能构建、运行和测试简单项目。也可以选择使用已有的安装。了解如何使用预装的 Node.js。
对 ES2015 特性的支持
Kotlin 提供对 ES2015 特性的支持,包括:
- 模块,可简化代码库并提升可维护性。
- 类,可引入面向对象原则,从而得到更清晰、更直观的代码。
- 用于编译挂起函数的生成器,可改善最终包体积并有助于调试。
- JavaScript 代码内联。
你可以在 build.gradle(.kts) 文件中添加 es2015 编译目标,一次性启用所有受支持的 ES2015 特性:
| |
在官方文档中进一步了解 ES2015(ECMAScript 2015、ES6)。
配置输出粒度
你可以选择编译器在项目中如何输出 .js 文件:
- 每个模块一个文件。默认情况下,JS 编译器会为每个项目模块输出单独的
.js文件作为编译结果。 - 整个项目一个文件。你可以通过在
gradle.properties文件中添加以下行,把整个项目编译为单个.js文件:
kotlin.js.ir.output.granularity=whole-program // 'per-module' 是默认值
- 每个文件一个。你可以设置更细粒度的输出,为每个 Kotlin 文件生成一个(如果该文件包含导出声明,则为两个)JavaScript 文件。要启用按文件编译模式:
- 把
es2015设置为编译目标,以支持项目中的 ES2015 特性。 - 在
gradle.properties文件中添加以下行:
kotlin.js.ir.output.granularity=per-file // 'per-module' 是默认值
生成 TypeScript 声明文件(d.ts)
实验性
Kotlin/JS 编译器可以从你的 Kotlin 代码生成 TypeScript 定义。JavaScript 工具和 IDE 在处理混合应用时可以使用这些定义来:
- 提供自动补全
- 支持静态分析器
- 简化在 JavaScript 和 TypeScript 项目中添加 Kotlin 代码的过程
生成 TypeScript 定义对业务逻辑共享用例尤其有价值。
编译器会收集所有带 @JsExport 标记的顶层声明,并自动在 .d.ts 文件中生成 TypeScript 定义。
要生成 TypeScript 定义,请在 Gradle 构建文件中显式配置。把 generateTypeScriptDefinitions() 函数添加到 build.gradle.kts 文件的 js {} 块中:
| |
你可以在 build/js/packages/<package_name>/kotlin 目录中找到这些定义,它们与相应的未经过 webpack 处理的 JavaScript 代码放在一起。
依赖
要声明依赖,请在 build.gradle(.kts) 文件中 jsMain 源集的 dependencies {} 块里进行:
Kotlin
| |
Groovy
| |
只有包含 Kotlin/JS 产物的库才能作为依赖使用。要解析依赖,请在 build.gradle(.kts) 文件的 repositories {} 块中声明 Gradle 应查找它们的仓库。例如:
| |
如果你添加的库依赖来自 npm 的包,Gradle 也会自动解析这些传递依赖。
Kotlin 标准库
对标准库的依赖会自动添加。标准库的版本与 Kotlin Multiplatform 插件的版本相同。
对于多平台测试,可以使用 kotlin.test API。创建多平台项目时,你可以在 commonTest 中使用单个依赖为所有源集添加测试依赖:
Kotlin
| |
Groovy
| |
npm 依赖
在 JavaScript 世界中,管理依赖最常见的方式是 npm。它提供了最大的 JavaScript 模块公共仓库。
Kotlin Multiplatform Gradle 插件让你可以像声明其他依赖一样在 Gradle 构建脚本中声明 npm 依赖。
要声明 npm 依赖,请把它的名称和版本传给依赖声明中的 npm() 函数。你也可以基于 npm 的 semver 语法指定一个或多个版本范围。
Kotlin
| |
Groovy
| |
默认情况下,该插件使用一个独立的 Yarn 包管理器实例来下载和安装 npm 依赖。它无需额外配置即可工作,但你可以按需调整它。
你也可以改用 npm 包管理器直接处理 npm 依赖。要使用 npm 作为包管理器,请在 gradle.properties 文件中设置以下属性:
kotlin.js.yarn=false
除常规依赖之外,还可以从 Gradle DSL 使用另外三种依赖类型。要了解每种依赖类型最合适的使用场景,请查看 npm 链接的官方文档:
- devDependencies,通过
devNpm(...), - optionalDependencies,通过
optionalNpm(...),以及 - peerDependencies,通过
peerNpm(...)。
npm 依赖安装完成后,你就可以按照从 Kotlin 调用 JS中所述在代码中使用它的 API。
run 任务
Kotlin Multiplatform Gradle 插件提供了一个 jsBrowserDevelopmentRun 任务,让你无需额外配置就能运行纯 Kotlin/JS 项目。
要在浏览器中运行 Kotlin/JS 项目,该任务是 browserDevelopmentRun 任务的别名(后者在 Kotlin 多平台项目中也可用)。它使用 webpack-dev-server 来提供你的 JavaScript 产物。如果你想要自定义 webpack-dev-server 使用的配置(例如调整服务器运行的端口),请使用 webpack 配置文件。
要运行面向 Node.js 的 Kotlin/JS 项目,请使用 jsNodeDevelopmentRun 任务,它是 nodeRun 任务的别名。
要运行项目,请执行标准的生命周期任务 jsBrowserDevelopmentRun,或与之对应的别名:
| |
要在修改源文件后自动触发应用重新构建,请使用 Gradle 的持续构建特性:
| |
或者
| |
项目构建成功后,webpack-dev-server 会自动刷新浏览器页面。
test 任务
Kotlin Multiplatform Gradle 插件会自动为项目搭建测试基础设施。它会下载并安装所需的测试运行器和其他依赖。
对于浏览器项目,你可以在 Karma 测试运行器和新的浏览器测试 DSL 之间选择。对于 Node.js 项目,可以使用 Mocha 测试框架。
该插件还提供实用的测试特性,例如:
- Source map 生成
- 测试报告生成
- 在控制台中显示测试运行结果
Karma
要配置 Karma 测试运行器,请在 build.gradle(.kts) 文件中浏览器目标的 testTask 内添加 useKarma {} 块。例如,要针对特定浏览器运行测试,请使用:
| |
或者,你也可以在 gradle.properties 文件中添加浏览器测试目标:
| |
这让你可以为所有模块定义浏览器列表,然后在特定模块的构建文件中添加特定浏览器。
Kotlin Multiplatform Gradle 插件会在构建时自动在 build/js/packages/projectName-test/karma.conf.js 生成 Karma 配置文件。该文件包含你在构建文件 useKarma {} 块中设置的配置。
你也可以把额外的配置文件放在项目根目录的 karma.config.d 目录中。构建时,该目录下所有 .js 配置文件都会被收集并自动合并到生成的 karma.conf.js 中。
关于 Karma 配置的更多信息,请参阅 Karma 文档。
用于浏览器测试的 DSL
实验性
Kotlin 提供了一个实验性 DSL,用于在浏览器环境中运行 Kotlin/JS 测试。它被设计为与技术无关。当前实现在底层包含以下工具:
- Playwright 充当浏览器驱动和分发管理器,支持 Chromium、Firefox 和 WebKit(Safari)浏览器引擎。
- Mocha 充当测试运行器。
- webpack 充当打包器(将在未来的版本中被 Vite 取代)。
要试用新的浏览器测试 DSL,请在你的 Kotlin/JS 目标的 browser {} 内添加需要选择启用的 test {} 块:
| |
关于新浏览器测试 DSL 配置的更多信息,请参阅在 Kotlin/JS 中运行测试。
Node.js
对于 Node.js 项目,Kotlin Multiplatform Gradle 插件会自动搭建 Mocha 测试框架。
要指定 Node.js 测试运行器使用的环境变量(例如向测试传递外部信息,或微调包解析),请在构建文件的 testTask {} 块中使用带键值对的 environment() 函数:
| |
运行测试
默认情况下,Kotlin Multiplatform Gradle 插件使用 Headless Chrome 来运行浏览器测试。插件不捆绑任何浏览器;测试运行器对缺失浏览器的处理方式不同:
- 使用 Karma 时,你的机器上应已安装其他浏览器,以便插件用它运行测试。如果你在持续集成服务器上执行 Kotlin/JS 测试,请确保那里也安装了你想测试的浏览器。
- 使用新的浏览器测试 DSL 时,插件会在首次运行时通过
playwright install命令安装必要的浏览器。Playwright 管理这些浏览器的位置,不使用本地已安装的浏览器。
要运行测试,请执行标准的生命周期任务 check:
| |
如果你想跳过测试,请在构建文件的 testTask {} 块中禁用它们:
| |
webpack 打包
对于浏览器目标,Kotlin Multiplatform Gradle 插件使用广为人知的 webpack 模块打包器。
webpack 任务
最常见的 webpack 调整可以通过 Gradle 构建文件中的 kotlin.js.browser.webpackTask {} 配置块直接完成:
mainOutputFileName—— webpack 输出文件的名称。它会在 webpack 任务执行后生成到<projectDir>/build/kotlin-webpack/<targetName>/<binaryName>。默认值是项目名。output.libraryTarget—— webpack 输出的模块系统。进一步了解 Kotlin/JS 项目可用的模块系统。默认值是umd。
| |
你也可以在 commonWebpackConfig {} 块中配置用于打包、运行和测试任务的通用 webpack 设置。
webpack 配置文件
Kotlin Multiplatform Gradle 插件会在构建时自动生成标准的 webpack 配置文件。它位于 build/js/packages/projectName/webpack.config.js。
如果你想对 webpack 配置做进一步调整,请把额外的配置文件放在项目根目录下一个名为 webpack.config.d 的目录中。构建项目时,所有 .js 配置文件都会自动合并到 build/js/packages/projectName/webpack.config.js 中。例如,要添加新的 webpack loader,请在 webpack.config.d 目录中的某个 .js 文件里添加以下内容:
注意: 在这种情况下,配置对象是全局对象
config。你需要在脚本中修改它。
| |
所有 webpack 配置能力在其文档中都有很好的描述。
构建可执行文件
为了通过 webpack 构建可执行的 JavaScript 产物,Kotlin Multiplatform Gradle 插件包含 jsBrowserDevelopmentWebpack 和 jsBrowserProductionWebpack 这两个 Gradle 任务。
jsBrowserDevelopmentWebpack创建开发产物,它们体积更大但创建耗时更少。因此,在积极开发期间请使用jsBrowserDevelopmentWebpack任务。jsBrowserProductionWebpack会对生成的产物应用无用代码消除,并压缩得到的 JavaScript 文件,耗时更长但生成的可执行文件更小。因此,在准备把项目用于生产时请使用jsBrowserProductionWebpack任务。
执行其中任一任务即可获得用于开发或生产的相应产物。除非另有指定,生成的文件会位于 build/kotlin-webpack。
| |
请注意,只有当你的目标被配置为生成可执行文件(通过 binaries.executable())时,这些任务才可用。
要在 build/dist/<targetName>/<binaryName> 目录中生成分发产物,请改为运行 jsBrowserDistribution 任务:
| |
该任务会生成包含项目资源的、可直接使用的分发产物。
CSS
Kotlin Multiplatform Gradle 插件还支持 webpack 的 CSS 和 style loader。虽然所有选项都可以通过直接修改用于构建项目的 webpack 配置文件来更改,但最常用的设置可以直接在 build.gradle(.kts) 文件中配置。
要在项目中启用 CSS 支持,请在 Gradle 构建文件的 commonWebpackConfig {} 块中设置 cssSupport.enabled 选项。使用向导创建新项目时,该配置也默认启用。
Kotlin
| |
Groovy
| |
或者,你也可以分别为 webpackTask {}、runTask {} 和 testTask {} 添加 CSS 支持:
Kotlin
| |
Groovy
| |
在项目中启用 CSS 支持有助于避免未配置项目尝试使用样式表时出现的常见错误,例如 Module parse failed: Unexpected character '@' (14:0)。
你可以使用 cssSupport.mode 指定应如何处理遇到的 CSS。可用的值有:
"inline"(默认):样式会被添加到全局<style>标签中。"extract":样式会被提取到单独的文件中。之后可以从 HTML 页面引入它们。"import":样式会作为字符串处理。如果你需要从代码中访问 CSS(例如val styles = require("main.css")),这会很有用。
要在同一个项目中使用不同的模式,请使用 cssSupport.rules。在这里你可以指定 KotlinWebpackCssRules 列表,每一项都定义一种模式以及 include 和 exclude 模式。
Node.js
对于面向 Node.js 的 Kotlin/JS 项目,该插件会自动在宿主机上下载并安装 Node.js 环境。如果你已有 Node.js 实例,也可以使用它。
你可以为每个子项目配置 Node.js 设置,也可以为整个项目统一设置。
修改 Node.js 版本
默认的 Node.js 版本目前是 24.16.0,但你可以为特定子项目使用不同的版本。请把以下几行添加到子项目的 build.gradle(.kts) 文件中。例如:
Kotlin
| |
Groovy
| |
要为整个项目(包括所有子项目)设置版本,请把相同的代码应用到 allprojects {} 块。例如:
Kotlin
| |
Groovy
| |
使用预装的 Node.js
如果构建 Kotlin/JS 项目的宿主机上已安装 Node.js,你可以配置 Kotlin Multiplatform Gradle 插件使用它,而不是安装自己的 Node.js 实例。
要使用预装的 Node.js 实例,请把以下几行添加到 build.gradle(.kts) 文件中:
Kotlin
| |
Groovy
| |
Yarn
默认情况下,为了在构建时下载并安装你声明的依赖,该插件管理自己的 Yarn 包管理器实例。它无需额外配置即可工作,但你可以调整它,或使用宿主机上已安装的 Yarn。
额外的 Yarn 特性:.yarnrc
要配置额外的 Yarn 特性,请在项目根目录放置一个 .yarnrc 文件。构建时它会被自动读取。
例如,要为 npm 包使用自定义仓库,请在项目根目录名为 .yarnrc 的文件中添加以下行:
| |
要进一步了解 .yarnrc,请访问官方 Yarn 文档。
使用预装的 Yarn
如果构建 Kotlin/JS 项目的宿主机上已安装 Yarn,你可以配置 Kotlin Multiplatform Gradle 插件使用它,而不是安装自己的 Yarn 实例。
要使用预装的 Yarn 实例,请把以下几行添加到 build.gradle(.kts):
Kotlin
| |
Groovy
| |
通过 kotlin-js-store 进行版本锁定
项目根目录中的 kotlin-js-store 目录由 Kotlin Multiplatform Gradle 插件自动生成,用于存放版本锁定所需的 yarn.lock 文件。该锁文件完全由 Yarn 插件管理,并会在 kotlinNpmInstall Gradle 任务执行期间更新。
按照推荐做法,请把 kotlin-js-store 及其内容提交到你的版本控制系统。这能确保你的应用在所有机器上都使用完全相同的依赖树构建。
如有需要,你可以在 build.gradle(.kts) 中同时修改目录名和锁文件名:
Kotlin
| |
Groovy
| |
警告: 修改锁文件名可能导致依赖检查工具不再读取该文件。
要进一步了解 yarn.lock,请访问官方 Yarn 文档。
报告 yarn.lock 已更新
Kotlin/JS 提供了一些 Gradle 设置,可以在 yarn.lock 文件被更新时通知你。当你想在 CI 构建过程中 yarn.lock 被静默更改时得到通知,可以使用这些设置:
YarnLockMismatchReport,指定如何报告yarn.lock文件的更改。你可以使用以下值之一:FAIL让相应的 Gradle 任务失败。这是默认值。WARNING把更改信息写入警告日志。NONE禁用报告。reportNewYarnLock,显式报告最近创建的yarn.lock文件。默认情况下该选项是禁用的:在首次启动时生成新的yarn.lock文件是常见做法。你可以用该选项确保该文件已被提交到仓库。yarnLockAutoReplace,在每次运行 Gradle 任务时自动替换yarn.lock。
要使用这些选项,请按如下方式更新 build.gradle(.kts):
Kotlin
| |
Groovy
| |
默认使用 –ignore-scripts 安装 npm 依赖
为降低执行来自被入侵的 npm 包中恶意代码的可能性,Kotlin Multiplatform Gradle 插件默认会在安装 npm 依赖时阻止执行生命周期脚本。
你可以通过在 build.gradle(.kts) 中添加以下几行来显式启用生命周期脚本的执行:
Kotlin
| |
Groovy
| |
分发目标目录
默认情况下,Kotlin/JS 项目构建结果位于项目根目录下的 /build/dist/<targetName>/<binaryName> 目录中。
要设置项目分发文件的另一个位置,请在构建脚本的 browser {} 块中添加 distribution {} 块,并使用 set() 方法为 outputDirectory 属性赋值。一旦你运行项目构建任务,Gradle 会把输出包和项目资源一起保存到该位置。
Kotlin
| |
Groovy
| |
模块名
要调整 JavaScript 模块(生成在 build/js/packages/myModuleName 中)的名称,包括相应的 .js 和 .d.ts 文件,请使用 outputModuleName 选项:
| |
请注意,这不会影响 build/dist 中经过 webpack 处理的输出。
自定义 package.json
package.json 文件保存 JavaScript 包的元数据。npm 等流行的包注册中心要求所有发布的包都有这样的文件。它们用它来跟踪和管理包的发布。
Kotlin Multiplatform Gradle 插件会在构建时为 Kotlin/JS 项目自动生成 package.json。默认情况下,该文件包含必要数据:名称、版本、许可证、依赖以及一些其他包属性。
除基本包属性之外,package.json 还可以定义 JavaScript 项目的行为,例如标识可运行的脚本。
你可以通过 Gradle DSL 向项目的 package.json 添加自定义条目。要添加自定义字段,请在编译的 packageJson 块中使用 customField() 函数:
| |
构建项目时,这段代码会把以下块添加到 package.json 文件中:
| |
在 npm 文档中进一步了解如何为 npm 注册中心编写 package.json 文件。