如何基于Kotlin/MP的commonMain构建Web Worker专用JS库?
问题:Kotlin多平台项目中Web Worker按需引入commonMain类避免代码重复
我有一个Kotlin多平台项目,支持Java后端和Angular前端,commonMain里的代码能同时构建给两个目标,已经在两边正常运行,项目还依赖一个叫melange的Kotlin/MP子模块库。
现在我要给Angular应用加Web Worker线程,已经创建了my.worker.ts模板文件并成功启动。我知道Worker里没法访问主应用加载的所有库代码,但需要从commonMain引入几个类。不过按主应用的方式导入会导致库代码完全重复(大概400KiB)。
想请教怎么只包含Web Worker需要的类,而不是完整的common构建产物?我想到两个方向:1. 在Gradle里创建单独的库构建目标,只包含必要类;2. 对生成的.js文件做死代码消除,移除未使用的内容,但不知道具体怎么实现。
解决方案
思路1:创建Gradle单独构建目标
- 在Kotlin多平台模块的
build.gradle.kts里新增一个专门的JS目标,命名为workerJs,配置它只关联Web Worker需要的代码和依赖:
kotlin { js(IR) { browser() binaries.executable() } // 新增Web Worker专用JS目标 js(IR) { name = "workerJs" binaries.executable() // 指定输出目录,方便Angular后续引用 compilations.main.outputDirectory.set(project.layout.buildDirectory.dir("js/worker")) } sourceSets { val workerMain by creating { dependsOn(commonMain) // 存放Worker专属代码的目录,把需要的类移到这里或者只引入指定包 kotlin.srcDir("src/workerMain/kotlin") // 按需引入melange库,排除不需要的子模块 dependencies { implementation(project(":melange")) { exclude(module = "melange-unused-module") } } } // 把workerJs目标和workerMain源码集关联起来 getByName("workerJsMain").dependsOn(workerMain) } }
- 把Web Worker需要的类从commonMain拆分到
src/workerMain/kotlin目录,或者用expect/actual语法区分主应用和Worker的代码逻辑,确保workerMain只包含必要代码。 - 构建完成后,在Angular的Web Worker文件里通过
importScripts引用这个专用构建产物:
// my.worker.ts importScripts('../path/to/workerJs/build/output.js'); // 直接使用需要的类即可
思路2:通过死代码消除(Tree Shaking)优化
- 先确认Kotlin JS用的是IR编译器(目前默认就是),旧编译器对Tree Shaking支持很差。在
build.gradle.kts里确认配置:
kotlin { js(IR) { browser { commonWebpackConfig { optimize = true // 开启Webpack优化,包含Tree Shaking } } binaries.executable() } }
- 在Web Worker里精准导入需要的类,不要导入整个common包:
// my.worker.ts // 不要全量导入 // import * as common from '../path/to/common/build/output.js'; // 精准导入所需类 import { MyNeededClass, MyAnotherNeededClass } from '../path/to/common/build/output.js';
- 确保依赖的melange库支持Tree Shaking:如果是自己的子模块,在它的
build.gradle.kts里配置输出ES模块:
kotlin { js(IR) { binaries.library() compilations.main.output.jsTarget.dir = "esm" // 输出ES模块格式 } }
- 最后开启Angular生产构建的优化,Angular会配合Webpack自动完成Tree Shaking:
// angular.json { "projects": { "your-app": { "architect": { "build": { "configurations": { "production": { "optimization": true, "buildOptimizer": true, "vendorChunk": false } } } } } } }
内容的提问来源于stack exchange,提问作者Brian White
相关产品推荐
相关产品推荐

