likes
comments
collection
share

Flutter web 开发实践分享

作者站长头像
站长
· 阅读数 7

Flutter web 开发实践分享

目录:

1.开发调试流程

2.插件添加流程

3.打包流程

4.常见问题

开发调试流程

支持Web

开启web支持

使用命令来开启web 支持:

flutter config --enable-web

已有工程支持web

在已有工程目录下执行命令:

flutter create .

新工程支持web

因为已经开启了web支持,所以直接创建Flutter 工程就支持 web

flutter create myapp

设置工程支持web后就可以按照之前开发Flutter的方式来开发了,如果有针对web的特殊处理可以在工程中使用kIsWeb来做判断

调试

flutter web 工程的调试流程和其他 Flutter 工程一样,有两种方式

IDE 方式

在IDE设备选择那里选择Chrome(web),再点击Debug调试按钮就可以了

Flutter web 开发实践分享

命令行方式

通过终端在在工程所在目录执行以下命令

flutter run -d chrome

开启本地服务调试

也可以在本地开启web服务,从浏览器中访问来调试

  1. flutter packages pub global activate webdev
  2. flutter packages pub global run webdev serve
  3. 打开任何浏览器,然后输入 `http://127.0.0.1:8080/

插件添加流程

添加插件工程

如果没有插件工程需要重新创建一个插件工程,执行命令:

flutter create --template=plugin --platforms=web /path/to/yourProject

增加web插件依赖后,可发现生成了一个同名插件增加web后缀的文件:xxx_web.dart

我们在web平台的插件实现就需要在xxx_web.dart中实现

添加插件文件

如果已有插件工程则只需要在插件工程的pubspec.yaml增加web配置

flutter:
  plugin:
    platforms:
      android:
        package: com.aa.bb.tt_flutter_business_plugin
        pluginClass: TTFlutterBusinessPlugin
      ios:
        pluginClass: TTFlutterBusinessPlugin
      web:
        pluginClass: TTFlutterBusinessPluginWeb
        fileName: plugin_web/tt_flutter_business_plugin_web.dart

在插件文件中首先导入import 'dart:html' as html;,然后注册插件、实现插件。

class TTFlutterBusinessPluginWeb {
  static void registerWith(Registrar registrar) {
    final MethodChannel channel = MethodChannel(
      'com.aa.bb/tt_flutter_business_plugin',
      const StandardMethodCodec(),
      registrar,
    );

    final pluginInstance = TTFlutterBusinessPluginWeb();
    channel.setMethodCallHandler(pluginInstance.handleMethodCall);
  }
  
  Future<dynamic> handler(MethodCall call) {
    if (call.method == 'getPlatformVersion') {
      return Future.value(html.window.navigator.appVersion);
    }
    return null;
  }
 }

上面直接调用html.window.navigator.appVersion,

还可以通过js.context.callMethod();调用。

callMethod

 callMethod(Object method, [List? args]);

method 支持String 或 num ,是用来确定调用的js方法的,args为给方法传递的参数数组。

同步方法调用

如果js方法为同步方法,callMethod的返回值就是js方法的返回值。

异步方法调用

如果js方法为异步方法,可以在callMethod的args中传递一个block, 在js中通过block将异步返回的结果返回过来

Function responseCall = (dynamic dataStr){
      print('= flutter web plugin = shareCollaboration web call back:$dataStr');
      Map responseMap = json.decode(dataStr);
      bool success = responseMap['success'] as bool;
      Map content = responseMap['content'] as Map;
      if (success) {
        callBack('$success');
      } else {
        callBack(content['errorMsg']);
      }
    };

    js.context.callMethod("callWindowFunction",[json.encode(params),responseCall]);

全局注册方法调用

在实际开发过程中遇到有些插件实现是需要调用全局注册方法,如果直接使用js.context.callMethod无法调到。

需要在js中做一个桥接

1.在工程的web文件夹下创建js文件夹

2.在js文件夹中创建一个js文件

3.在js文件中实现一个方法来调用全局注册方法

function callWindowFunction(param, callback)
{
      window.TTCefWebFunction(param,callback);
}

我这里要调用的全局注册方法是window.TTCefWebFunction

打包流程

正常web打包只需要执行flutter build web,就可以了。

但这意味着渲染器使用了audo参数,即在移动端浏览器使用html,在桌面端使用convaskit

渲染器选择

flutter web 运行和打包涉及到渲染器的选择,有html 和 canvaskit 可以选择,区别如下:

使用 HTML 渲染 使用 HTML,CSS,Canvas 和 SVG 元素来渲染,应用的大小相对较小。

使用 CanvasKit 渲染 将 Skia 编译成 WebAssembly 格式,并使用 WebGL 渲染。应用在移动和桌面端保持一致,有更好的性能,以及降低不同浏览器渲染效果不一致的风险。但是应用的大小会增加大约 2MB。

默认情况下在移动端浏览器使用html,在桌面端使用convaskit

如果想手动设置也是可以的,

命令行方式为:

在命令后增加--web-renderer html

//使用 HTML 渲染
flutter run -d chrome --web-renderer html

//使用 CanvasKit 渲染
flutter run -d chrome --web-renderer canvaskit

在工程中配置为:

1.使用auto参数构建或不使用设置参数

2.在 web/index.html 文件的 main.dart.js 前插入 <script> 标签。

  <script type="text/javascript">
    let useHtml = // ...
    if(useHtml) {
      window.flutterWebRenderer = "html";
    } else {
      window.flutterWebRenderer = "canvaskit";
    }
  </script>
  <script src="main.dart.js" type="application/javascript"></script>

PS:如果使用canvaskit有两点需要注意

1.在国内由于墙的原因,需要更换canvaskit源

可以通过--dart-define=FLUTTER_WEB_CANVASKIT_URL="https://unpkg.zhimg.com/canvaskit-wasm@0.24.0/bin/" 来更改源地址

2.目前看使用canvaskit在页面文字刚显现是会显示成[X],稍后会自动刷新回来,文字中有省略号的地方也会展示为[X]且不能自动刷新回来。

目前纪要管理平台打包命令是

flutter build web --web-renderer html -- release

遇见的问题

联调跨域问题

OS: macOS Catalina

  1. ~/.bash_profile增加(如果你使用的是zsh,则是~/.zshrc):

    export CHROME_EXECUTABLE="/Applications/Google Chrome.app/Contents/MacOS/google-chrome-unsafe"
    
  2. 创建一个google-chrome-unsafe的shell-script并放在原来的chrome可执行文件同一目录下,文件内容如下:

    google-chrome-unsafe

    #!/bin/bash``/Applications/Google``\ Chrome.app``/Contents/MacOS/Google``\ Chrome --disable-web-security --user-data-``dir``=``"your-tmp-dir" $*

    ps:

    • 划重点,文件路径得是:/Applications/Google Chrome.app/Contents/MacOS/google-chrome-unsafe

    • 别忘了可执行权限:chmod +x

  3. 环境变量生效后,ide debug启动的chrome默认就是上述命令启动的,即关闭了安全模式(允许跨域)的

注意::IDE记得重启让环境变量生效!

非安全模式偶尔失效

需要重新开启

插件无法调用全局注册方法

增加一个js桥接

文本刚出现时显示[X]

暂时使用 html 渲染器

部署后报错提示main.dart.js找不到

原因是路径不对,因为部署时是部署到了xx.sit.tt.com/static-meet…

而运行时直接找的就是xx.sit.tt.com/main.dart.j…

修复方案:

在index.html中更改<base href="/"><base href="/static-meeting-manager/">