flutter web 开发
(1)局域网调试:
flutter run -d web-server --web-hostname 192.168.2.70 --web-port 64578
# 修改ip和端口
(2)FlutterWeb 与 原生app中webview交互,包括flutter app
①FlutterWeb调用原生
//创建一个 native_channel.dart ,定义一个外部函数通过 @JS("调用的channel和函数名") 注解指定调用的原生函数(JavascriptChannel固定名称为postMessage)
import 'package:js/js.dart';
// JS调用原生函数
@JS("toast_channel.postMessage")
external String showToast(String msg);
//需要使用的地方直接调用
showToast("Increment");
②原生调用FlutterWeb
import 'dart:js' as js;
void _callJs(a){
print(a)
}
void initState() {
js.context['callJs'] = _callJs;
}
③如果调用失败(主要是加载先后顺序导致,app无法调用flutter方法)
解决办法,可以写一个html中间页面,再利用中间页面跳转flutter页面
(3)打包流程
打包: yaml注释没用的:cupertino_icons flutter build web --release --web-renderer html flutter build web --release --no-tree-shake-icons --web-renderer html 提示空安全: flutter build web --no-sound-null-safety --release --web-renderer html 关闭pwa打包 flutter build web --pwa-strategy none --release --no-tree-shake-icons --web-renderer html 生成gzip: find . \( -name "*.js" -o -name "*.html" -o -name "*.css" -o -name "*.svg" -o -name "*.json" \) -exec gzip -k -f {} \; 打包后生成gzip,然后删除canvaskit文件夹,然后复制Materialicons-Regular.otf到web/assets/fonts中
(4)拖拽文件及上传
①拖拽文件
desktop_drop: ^0.4.3
②上传文件
上边拖拽文件返回的是XFile,用到readAsBytes()方法返回Uint8List格式,后端获取
// 从请求中读取文件数据
file, _, err := c.Request.FormFile("image")
if err != nil {
c.JSON(200, gin.H{
"code": 0,
"msg": "文件上传失败",
})
return
}
defer file.Close()
client := &http.Client{}
var requestBody bytes.Buffer
writer := multipart.NewWriter(&requestBody)
// 创建一个form字段,用于包装文件内容
filePart, err := writer.CreateFormFile("image", "1.png")
if err != nil {
c.JSON(200, gin.H{
"code": 0,
"msg": err.Error(),
})
return
}
// 将文件内容拷贝到form字段中
if _, err = io.Copy(filePart, file); err != nil {
c.JSON(200, gin.H{
"code": 0,
"msg": err.Error(),
})
return
}
// 关闭writer,以便写入结尾的boundary
writer.Close()
// 创建一个POST请求
req, err := http.NewRequest("POST", "xxxx/uploadImg", &requestBody)
if err != nil {
c.JSON(200, gin.H{
"code": 0,
"msg": err.Error(),
})
return
}
// 设置请求头中的Content-Type为multipart/form-data
req.Header.Set("Content-Type", writer.FormDataContentType())
// 发送请求
resp, err := client.Do(req)
if err != nil {
c.JSON(200, gin.H{
"code": 0,
"msg": err.Error(),
})
return
}
defer resp.Body.Close()
// 读取响应体
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
c.JSON(200, gin.H{
"code": 0,
"msg": err.Error(),
})
return
}
// 打印响应结果
fmt.Println(string(body))
var result map[string]interface{}
err = json.Unmarshal(body, &result)
if err != nil {
c.JSON(200, gin.H{
"code": 0,
"msg": err.Error(),
})
return
}
if result["code"].(float64) == 1 {
c.JSON(200, gin.H{
"code": 1,
"msg": "成功",
"data": result["data"],
})
return
}
c.JSON(200, gin.H{
"code": 0,
"msg": "上传失败",
})
(5)优化加载流程及速度(去掉service worker)
关闭service worker的pwa打包命令:
flutter build web --pwa-strategy none --release --no-tree-shake-icons --web-renderer html
修改flutter中index.html文件javascript代码为:
<script>
var scriptLoaded = false;
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
var scriptTag = document.createElement('script');
scriptTag.src = 'main.dart.js';
scriptTag.type = 'application/javascript';
document.body.append(scriptTag);
}
loadMainDartJs();
</script>
注:其实就是直接加载main.dart.js文件。如果进行版本控制也可以改版该js文件的名称进行浏览器的缓存更新
(6)clip web 配置
//状态栏颜色
<meta name="theme-color" content="#fff">
<meta name="apple-mobile-web-app-capable" content="yes">
//状态栏字体颜色
<meta name="apple-mobile-web-app-status-bar-style" content="black">