创建 Kotlin/JS 工程(Project)
Kotlin JavaScript 工程(Project) 使用 Gradle 进行编译. 为了方便开发者管理 Kotlin JavaScript 工程, 我们提供了 kotlin.multiplatform
Gradle 插件, 其中包括工程配置工具, 以及对 JavaScript 开发中常见业务进行自动化处理的帮助性任务.
这个插件会在后台使用 npm 或 Yarn 包管理器下载 npm 依赖项, 并使用 webpack 将 Kotlin 工程编译为 JavaScript bundle . 依赖项管理和配置调整大部分可以直接在 Gradle 构建脚本文件中完成, 还可以通过选项覆盖自动生成的配置, 获得完全的控制能力.
你可以在 Gradle 工程的 build.gradle(.kts)
文件中手动的应用 org.jetbrains.kotlin.multiplatform
插件:
通过 Kotlin Multiplatform Gradle 插件, 你可以在编译脚本的 kotlin
节中管理工程的各方面设置.
在 kotlin {}
代码段中, 你可以管理以下方面:
目标执行环境: 浏览器, 或 Node.js
支持 ES2015 功能: 类, 模块, 和生成器
工程的依赖项目管理: Maven 或 npm
对于浏览器工程的 打包(Bundling) 和 CSS 支持
执行环境
Kotlin/JS 工程可以运行于两种不同的执行环境:
浏览器环境, 用于浏览器内运行的客户端脚本
Node.js, 在浏览器之外运行 JavaScript 代码, 比如, 运行服务器端脚本.
要为 Kotlin/JS 工程定义目标运行环境, 需要添加 js {}
代码段, 其中包含 browser {}
或 nodejs {}
:
binaries.executable()
指令明确的指示 Kotlin 编译器输出可执行的 .js
文件. 使用当前的 Kotlin/JS 编译器时, 这是默认的行为, 但如果你使用 Kotlin/JS IR 编译器, 或者在 gradle.properties
文件中设置过 kotlin.js.generate.executable.default=false
, 则需要明确的指定这条指令. 这些情况下, 省略 binaries.executable()
会导致编译器只生成 Kotlin-internal 库文件, 这些库文件可以被其他项目使用, 但不能独立运行.
Kotlin Multiplatform 插件会针对选定的运行环境, 自动配置它的编译任务. 包括下载并安装应用程序运行和测试所需要的环境和依赖项目, 因此开发者可以编译, 运行, 以及测试简单的工程, 而无需再添加更多配置. 对于编译目标为 Node.js 的项目, 还有一个选项可以使用本地已安装的 Node.js. 详情请参见 使用已安装的 Node.js.
支持 ES2015 功能
Kotlin 对以下 ES2015 功能提供了 实验性 的支持:
模块: 简化你的代码库, 提高可维护性的.
类: 可以结合 OOP 原则, 产生更清晰, 更直观的代码.
用于编译 挂起函数 的生成器: 能够改善最终 bundle 的大小, 并帮助进行调试.
你可以向你的 build.gradle(.kts)
文件添加 es2015
编译目标, 一次性启用所有支持的 ES2015 功能:
依赖项目
与其他 Gradle 工程一样, Kotlin/JS 工程编译脚本的 dependencies {}
代码段内, 支持添加传统的 Gradle 依赖项目声明:
Kotlin Multiplatform Gradle 插件也支持在编译脚本的 kotlin {}
代码段中添加特定源代码集合(source set)的依赖项目声明:
如果你添加的库依赖于 来自 npm 的包, Gradle 也会自动解析这些传递性依赖项.
Kotlin 标准库
对 标准库 的依赖项会自动添加. 标准库的版本与 Kotlin Multiplatform 插件的版本相同.
对于跨平台的测试, 可以使用 kotlin.test
API. 当你创建跨平台项目时, 你可以在 commonTest
中使用一个依赖项, 对所有的源代码集添加测试依赖项:
npm 依赖项目
在 JavaScript 的世界中, 管理依赖项目的最常见方式是 npm. 它提供了各种 JavaScript 模块(module) 的最大的公共仓库(repository).
通过 Kotlin Multiplatform Gradle 插件, 可以在 Gradle 编译脚本中声明 npm 依赖项目, 方法和声明其他依赖项目类似.
要声明一个 npm 依赖项目, 可以在一个依赖项目声明中使用 npm()
函数指定依赖项目的名称和版本. 也可以使用 npm semver 语法, 指定一个或多个版本范围.
默认情况下, 插件会使用 Yarn 包管理器的一个单独的实例, 来下载和安装 npm 依赖项. 不需要额外配置, 默认即可工作, 但你也可以 根据需要对其进行调整.
你也可以通过 npm 包管理器直接使用 npm 依赖项. 要使用 npm 作为你的包管理器, 请在你的 gradle.properties
文件中, 设置以下属性:
除了标准依赖项之外, 在 Gradle DSL 中使用还可以使用 3 种其他类型的依赖项. 关于什么情况下应该选择什么类型的依赖项, 请阅读 npm 提供的官方文档:
devDependencies, 通过
devNpm(...)
使用,optionalDependencies 通过
optionalNpm(...)
使用, 以及peerDependencies 如果
peerNpm(...)
使用.
一个 npm 依赖项目安装完成之后, 你就可以如 在 Kotlin 中调用 JavaScript 中介绍过的那样, 在你的代码中使用它的 API.
run 任务
Kotlin Multiplatform Gradle 插件提供了一个 jsRun
任务, 它可以运行你的纯 Kotlin/JS 工程, 无需额外的配置.
对于在浏览器内运行 Kotlin/JS 工程的情况, 这个是 browserDevelopmentRun
任务的一个别名(在 Kotlin 跨平台项目也可以使用). 它使用 webpack DevServer 来提供你的 JavaScript artifact. 如果你想要自定义 DevServer 的配置, 例如, 改变端口号, 请使用 webpack 配置文件.
对于在 Node.js 平台运行 Kotlin/JS 项目的情况, 请使用 jsRun
任务, 它是 nodeRun
任务的别名.
要运行一个工程, 请执行 Gradle 编译周期(lifecycle)中标准的 jsRun
任务, 或者运行它作为别名对应的真实的任务:
如果要在修改过源代码文件后自动对你的应用程序进行重新构建, 可以使用 Gradle 的 连续构建(continuous build) 功能:
或者
工程构建成功后, webpack-dev-server
会自动刷新浏览器页面.
test 任务
Kotlin Multiplatform Gradle 插件会为工程自动设置测试环境. 对于浏览器工程, 它会下载并安装测试运行器 Karma, 以及相关的依赖项目; 对于 Node.js 项目, 会使用 Mocha 测试框架.
插件还提供了很多有用的测试功能, 比如:
生成源代码文件映射(Source map)
生成测试报告(Test report)
在控制台输出测试运行结果
为了运行浏览器中的测试, 插件会默认使用 Headless Chrome. 你也可以选择其他浏览器来运行测试, 方法是在编译脚本的 useKarma {}
代码段中添加相应的设置:
或者你也可以在 gradle.properties
文件中添加测试的目标浏览器:
通过这种方法, 你可以为所有的模块定义一组浏览器, 然后在某些模块的构建脚本中添加特定的浏览器.
请注意, Kotlin Multiplatform Gradle 插件不会为你自动安装这些浏览器, 而只是使用那些在它的运行环境中可用的浏览器. 比如说, 如果在一个持续集成服务器上运行 Kotlin/JS 测试, 请注意确保安装了你需要测试的浏览器.
如果想要跳过测试, 可以在 testTask {}
代码段中添加 enabled = false
设置.
要运行测试, 请执行 Gradle 编译周期(lifecycle)中标准的 check
任务:
如果要指定你的 Node.js 测试运行器使用的环境变量 (比如, 向你的测试代码传递外部信息, 或对包的解析进行微调), 可以在你的构建脚本的 testTask {}
代码段中使用 environment()
函数, 参数是键-值对:
配置 Karma
Kotlin Multiplatform Gradle 插件会在构建时自动生成 Karma 配置文件, 其中包括你的 build.gradle(.kts)
文件中的 kotlin.js.browser.testTask.useKarma {}
代码段 中的设置. 你可以在 build/js/packages/projectName-test/karma.conf.js
找到这个文件. 要调整 Karma 所使用的配置, 请将你的额外配置文件 放在你的项目根目录的 karma.config.d
目录之下. 在构建时, 这个目录下的所有 .js
配置文件都会被读取, 并自动合并到生成的 karma.conf.js
文件中.
Karma 配置的详细功能请参见 Karma 的 文档.
webpack 打包(Bundling)
如果编译目标为浏览器环境, Kotlin Multiplatform Gradle 插件使用大家都熟悉的 webpack 来打包模块.
webpack 版本
Kotlin Multiplatform 插件使用 webpack 5.
如果你的项目通过 plugin 1.5.0 以前版本创建, 那么可以在你的项目的 gradle.properties
文件中添加以下设置, 临时切换回这些版本使用的 webpack 4:
webpack 任务
在 Gradle 编译脚本的 kotlin.js.browser.webpackTask {}
配置代码段中, 可以直接调整最常见的 webpack 配置:
outputFileName
- webpack 的输出文件名称. 执行webpack 任务之后, 这个文件将生成在<projectDir>/build/dist/<targetName>
文件夹内. 默认值是工程名称.output.libraryTarget
- 用于 webpack 输出文件的模块系统. 详情请参见 Kotlin/JS 工程可用的模块系统. 默认值是umd
.
还可以在 commonWebpackConfig {}
代码段中配置 webpack 的共通设置, 用于打包(bundling), 运行, 以及测试任务.
webpack 配置文件
Kotlin Multiplatform Gradle plugin 在构建时会自动生成一个标准的 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
中:
关于 webpack 的所有配置项目, 请参见它的 文档.
构建可执行文件
要通过 webpack 编译可执行的 JavaScript artifact, Kotlin Multiplatform Gradle 插件包含 Gradle 任务 browserDevelopmentWebpack
和 browserProductionWebpack
.
browserDevelopmentWebpack
创建开发模式的 artifact, 文件尺寸会比较大, 但构建时间比较短. 因此, 在活跃开发阶段请使用browserDevelopmentWebpack
任务.browserProductionWebpack
会执行死代码消除, 生成 artifact 文件, 并对输出结果的 JavaScript 文件最小化, 构建时间更长, 但生成的可执行文件尺寸更小. 因此, 在构建你的项目用于生成目的时, 请使用browserProductionWebpack
任务.
执行这两个任务可以分别得到开发模式和生产模式的 artifact 文件. 生成的文件会在 build/dist
目录下, 除非 另有设置.
注意, 只有在你的编译目标设置为生成可执行文件 (通过 binaries.executable()
) 时, 这些任务才可用.
CSS
Kotlin Multiplatform Gradle 创建还支持 webpack 的 CSS 和 style 装载器. 虽然所有的选项都可以直接修改构建你的项目的 webpack 配置文件, 但最常用的方法是使用 build.gradle(.kts)
中直接可用的设定.
要在你的项目中打开 CSS 支持, 请在 Gradle 构建文件的 commonWebpackConfig {}
代码段中设置 cssSupport.enabled
选项. 通过 IDE 向导创建新工程时, 这个配置也会默认启用.
或者, 也可以单独对 webpackTask {}
, runTask {}
, 和 testTask {}
添加 CSS 支持:
对你的项目打开 CSS 支持, 有助于防止在未配置的项目中使用样式表时发生的常见错误, 比如 Module parse failed: Unexpected character '@' (14:0)
.
可以使用 cssSupport.mode
来指定 CSS 应该如何处理. 可选的设定值如下:
"inline"
(默认值): 样式添加到全局的<style>
tag."extract"
: 样式抽取为单独的文件. 然后通过 HTML 页面来添加."import"
: 样式作为字符串处理. 如果你需要在你的代码中访问 CSS, 这会很有用 (比如,val styles = require("main.css")
).
如果要对同一个项目使用不同的模式, 请使用 cssSupport.rules
. 这里, 你可以指定一组 KotlinWebpackCssRules
, 其中每一项定义一个 mode, 以及 include 和 exclude pattern.
Node.js
对于编译到 Node.js 的 Kotlin/JS 项目, plugin 会在主机上自动下载并安装 Node.js 环境. 如果已经安装过 Node.js, 你也可以使用已经存在的 Node.js.
使用已安装的 Node.js
如果在构建 Kotlin/JS 项目的主机上已经安装了 Node.js, 你可以配置 Kotlin Multiplatform Gradle 插件, 让它使用已安装的 Node.js, 而不要安装另外的 Node.js 实例.
要使用已安装的 Node.js, 请向 build.gradle(.kts)
文件添加以下内容:
Yarn
默认情况下, 为了在构建时下载并安装你声明的依赖项, plugin 会管理它自己的 Yarn 包管理器实例. 不需要额外配置, 默认即可工作, 但你也可以对其进行调整, 或者使用你的主机上已经安装的 Yarn.
Yarn 的更多功能: .yarnrc
如果要配置 Yarn 的更多功能, 请将一个 .yarnrc
文件放在你的工程根目录. 编译时, 会自动使用它.
比如, 如果要对 npm 包使用一个自定义的仓库, 请将以下内容添加到工程根目录下的一个 .yarnrc
文件中:
关于 .yarnrc
文件的更多信息, 请参见 Yarn 官方文档.
使用已安装的 Yarn
如果在构建 Kotlin/JS 项目的主机上已经安装了 Yarn, 你可以配置 Kotlin Multiplatform Gradle 插件, 让它使用已安装的 Yarn, 而不要安装另外的 Yarn 实例.
要使用已安装的 Yarn, 请向 build.gradle(.kts)
文件添加以下内容:
通过 kotlin-js-store 锁定版本
项目根目录下的 kotlin-js-store
目录 由 Kotlin Multiplatform Gradle 插件自动生成, 存储 yarn.lock
文件, 这个文件用来锁定版本. lock 文件完全由 Yarn plugin 管理, 并在 Gradle 任务 kotlinNpmInstall
执行时被更新.
为了遵循 Yarn 推荐的最佳实践, 请将 kotlin-js-store
和其中的内容提交到你的版本管理系统. 这样可以保证你的应用程序在所有的机器上都使用完全相同的依赖项目树来进行构建.
如果需要, 你可以在 build.gradle(.kts)
文件修改目录和 lock 文件名称:
关于 .yarnrc
文件的更多信息, 请参见 Yarn 官方文档.
报告 yarn.lock 的变更
Kotlin/JS 提供了 Gradle 设置, 可以通知你 yarn.lock
文件是否发生变更. 如果你想要在 CI 构建过程中 yarn.lock
发生变更时收到通知, 你可以使用这些设置:
YarnLockMismatchReport
, 指定对yarn.lock
文件的变更如何进行报告. 你可以使用以下值之一:FAIL
让对应的 Gradle task 失败. 这是默认设置.WARNING
将变更信息写入警告日志.NONE
禁用报告.
reportNewYarnLock
, 会明确的对最近创建的yarn.lock
文件进行报告. 默认情况下, 这个选项是禁用的: 常见的做法是在最开始生成一个新的yarn.lock
文件. 你可以使用这个选项, 来确保yarn.lock
文件已经提交到了你的代码仓库.yarnLockAutoReplace
, 会在 Gradle task 每次运行时自动替换yarn.lock
.
要使用这些选项, 请更新 build.gradle(.kts)
文件:
默认使用 --ignore-scripts 安装 npm 依赖项
如果 npm 包被攻击, 其中可能包含恶意代码, 为了减少执行这种恶意代码的可能性, Kotlin Multiplatform Gradle 插件在安装 npm 依赖项时默认会禁止执行 Life Cycle 脚本.
你可以明确的允许 Life Cycle 脚本执行, 方法是在 build.gradle(.kts)
中添加以下设定:
设置发布目录
默认设置下, Kotlin/JS 工程编译的输出在工程根目录下的 /build/dist/<targetName>/<binaryName>
目录内.
如果要为工程设置另外的发布位置, 请在编译脚本的 browser {}
代码段内, 添加 distribution {}
代码段, 在这里使用 set()
方法为 outputDirectory
属性设置一个值. 当你运行工程的构建任务时, Gradle 会将输出的 bundle 文件和工程的资源文件一起, 保存到这个位置.
模块名称
如果要调整 JavaScript 模块(module) 名称 (模块将被生成在 build/js/packages/myModuleName
路径), 包括对应的 .js
和 .d.ts
文件名称, 请使用 moduleName
选项:
注意, 这个设置不会影响位于 build/dist
的 webpacked 输出.
自定义 package.json 文件
package.json
文件包含 JavaScript 包的元数据(metadata). 常用的包登记系统, 比如 npm, 要求所有发布的包带有这个文件. 包登记系统会使用这个文件来追踪和管理包的发布.
对 Kotlin/JS 工程, Kotlin Multiplatform Gradle 插件在构建时会自动生成 package.json
. 这个文件默认会包含最基本的数据: 名称, 版本, 许可证, 依赖项目, 以及包的一些其他属性.
除了基本的包属性之外, package.json
还可以定义 JavaScript 包应该如何动作, 比如, 标识可以运行的脚本.
你可以通过 Gradle DSL 向工程的 package.json
文件添加自定义的内容. 要添加自定义的项目到你的 package.json
文件, 可以在编译任务的 packageJson
代码段中使用 customField()
函数:
构建工程时, 这段代码会向 package.json
文件添加以下内容:
关于如何为 npm 登记项目编写 package.json
文件, 详情请参见 npm 文档.