一、背景
最近用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保持一致。