Kotlin Multiplatform构建JS库发npm后Angular无法引用问题排查
问题根因
一共三个配置/操作错误,导致无法正常调用:
- JS构建配置错误:使用了
binaries.executable()生成可执行程序而非可复用库,webpack的output.libraryTarget = "this"配置不符合前端模块化规范,模块化环境下this不指向全局对象,所有导出内容无法被外部模块识别。 - npm包发布错误:直接上传build目录下的JS开发中间产物,未配置正确的包入口,前端构建工具无法定位到模块导出的内容。
- 调用写法错误:Kotlin导出的类是标准JS构造函数,直接调用而非用
new关键字实例化会抛出类型错误。
正确实现步骤
1. 修改KMP的JS目标构建配置
替换原有JS块配置,使用IR编译器、库产物模式、UMD模块规范兼容所有前端环境,开启TS类型生成方便Angular等TS项目识别:
js(IR) { browser { webpackTask { // 用UMD格式兼容CommonJS、ES Module、全局引入所有场景 output.libraryTarget = "umd" } } // 生成供第三方引用的库产物,不要用binaries.executable() binaries.library() // 自动生成TS类型定义文件,避免TS项目报"无对应类型声明"错误 generateTypeScriptDefinitions() }
注意:必须使用IR编译器后端,旧版LEGACY编译器对@JsExport注解支持存在缺陷,Kotlin 1.8+版本JS目标默认启用IR,低版本需显式指定
2. 构建并发布正确的npm包
执行构建命令:
./gradlew jsBrowserProductionLibraryDistribution
构建完成后,发布产物在build/dist/js/productionLibrary目录下,不要使用build/js下的开发中间产物。在该目录下创建package.json配置包入口:
{ "name": "bf-shared-mw", "version": "1.0.2", "main": "bf-shared-mw.js", "types": "bf-shared-mw.d.ts" }
上述配置中
main和types字段的文件名,和productionLibrary目录下自动生成的JS、d.ts文件名保持一致即可,默认文件名与你的KMP项目名同名。
将该目录下的所有文件发布到npm即可,该产物已经内联了所需的Kotlin JS标准库代码,不需要额外引入依赖。
3. 前端项目正确调用
重新安装更新后的npm包,注意两个要点:
- 若导入时提示找不到导出项,可先打印整个导入对象确认结构,部分Kotlin版本会将所有导出挂在模块的
default字段下 - 类实例化必须加
new关键字
Angular中正确调用示例:
import { Component, OnInit } from '@angular/core'; // 若直接解构拿不到Greeting,可改为import bfSharedMw from 'bf-shared-mw',通过bfSharedMw.Greeting访问 import { Greeting } from 'bf-shared-mw'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { ngOnInit(): void { // 必须加new调用构造函数 const greetings = new Greeting("测试标题", 1); greetings.helloWorld(); } title = 'angular-tour-of-heroes'; }
React、Vue等其他前端框架/库的调用逻辑完全一致,只要导入路径正确、使用new实例化导出类即可正常使用。
额外注意事项
- 所有需要暴露给JS调用的Kotlin类、顶层函数、属性都必须添加
@JsExport注解,且不能引用未添加@JsExport的非公开类型,否则会导出失败 - 注意Kotlin类型在JS侧的映射规则:Kotlin的
List/Set等集合在JS侧会被映射为数组,基础数值类型会被映射为JS原生number,空安全类型在JS侧不会自动做非空校验 - 不要在发布的npm包中包含未压缩的调试产物、webpack运行时代码、测试用例等冗余文件,
productionLibrary目录下的文件已经是优化后的最小可用产物
内容的提问来源于stack exchange,提问作者ALKIN ÇAKIRALAR
相关产品推荐
相关产品推荐

