一、背景
最近用KMP尝试运行在Android、iOS、desktop都成功了,网络数据访问也正常。
可是当运行wasmJs的时候遇到了2个较大的问题。
-
中文字体出现乱码。
-
出现了跨域问题。
首先贴一下每个平台的运行截图:
Android
iOS
Desktop
二、问题
当web跑起来的时候,令人震惊的事情发生了😭
2.1 乱码问题
除了数字,其他的文字都不显示。猜测是字体的问题,wasmJs可能还没有内置默认字体,导致字体显示乱码。
2.2 跨域问题
观察浏览器控制台api访问的数据都成功拿到,但所有图片资源被跨域拦截。
目前没有找到关于wasm提供像Vue一样的本地代理跨域的方案。
三、解决
2.1 乱码问题解决方案
既然是字体导致的,那就找一个免费字体内置进去,尝试后,果然有效,效果如下
只需要在wasmJsMain中的main入口处,添加主题默认字体即可。
fun main() {ComposeViewport(document.body!!) {MaterialTheme(typography = HTypography()) {App()}}
}
使用MeterialTheme主题,赋值参数typography,值为自定义集成Typography的函数,如下
@Composable
fun HTypography(): Typography {val defaultFontFamily = FontFamily(org.jetbrains.compose.resources.Font(Res.font.DouyinSansBold))return Typography(bodySmall = MaterialTheme.typography.bodySmall.copy(fontFamily = defaultFontFamily,),bodyMedium = MaterialTheme.typography.bodyMedium.copy(fontFamily = defaultFontFamily,),bodyLarge = MaterialTheme.typography.bodyLarge.copy(fontFamily = defaultFontFamily,//fontWeight = FontWeight.Bold,),titleSmall = MaterialTheme.typography.titleSmall.copy(fontFamily = defaultFontFamily,),titleMedium = MaterialTheme.typography.titleMedium.copy(fontFamily = defaultFontFamily,),titleLarge = MaterialTheme.typography.titleLarge.copy(fontFamily = defaultFontFamily,),headlineSmall = MaterialTheme.typography.headlineSmall.copy(fontFamily = defaultFontFamily,),headlineMedium = MaterialTheme.typography.headlineMedium.copy(fontFamily = defaultFontFamily,),headlineLarge = MaterialTheme.typography.headlineLarge.copy(fontFamily = defaultFontFamily,),)
}
声明FontFamily字体,其中DouyinSansBold为网络上找的免费字体,放入composeApp/commonMain/composeResources/font文件夹。
在返回的Typography中,把所有字体都换成自定义的字体。
2.2 跨域问题解决方案
跨域问题比较好解决,最快和彻底的方式就是告诉服务端或者API网关管理人员,把要访问的IP配置进去。如果是开发测试环境没有很强的安全性要求,只需要在服务Nginx添加Access-Control-Allow-Origin "*"即可。如果是直接访问的Java服务,在SpringBoot上也可以加跨域的注解。
本次使用的方式不借助他人,自己搞定。方式也是通过Nginx来实现。
在本地通过docker搭建Nginx服务做中转,详细参考另一篇文章《本地Nginx解决跨域问题》。
在项目中,把所有Wasm平台图片的访问中转到localhost下,因为nginx的配置端口是80,只需要把图片url路径添加localhost即可访问到本地nginx服务,由nginx服务反向代理资源。
fun String.proxyAliOss(): String {return if (getPlatform().type.contentEquals("Wasm")) {this.replaceFirst("https://", "http://localhost/")} else {this}
}
如此成功显示图片资源,效果上和Android、iOS、Desktop保持一致。