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">