You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web部署GitHub Pages后Dart-JS interop外部函数无法识别问题

成因
  • 编译优化导致绑定失效:本地测试使用的是Flutter Web的debug模式,dart2js不会执行代码压缩和tree shaking优化,JS interop绑定可以正常识别。部署到GitHub Pages使用的是release编译产物,dart2js会对未做规范注解的JS interop类执行激进的裁剪、名称混淆,导致你定义的isPhantomInstalled等external方法绑定丢失,触发不存在的报错。
  • 成员定义不匹配隐患:Dart侧将address定义为getter属性,但JS侧同时声明了address实例属性和同名address()方法,存在命名冲突风险,虽然本次报错不直接来源于此,但会引发后续取值异常。
  • 加载顺序问题:GitHub Pages网络加载延迟高于本地环境,如果你的自定义JS文件加载时机晚于Flutter main.dart.js初始化,会导致walletModule全局对象未挂载就被Dart调用,绑定失效。
解决方案
  1. 修正Dart JS interop注解,符合官方规范
    Dart 2.17+ 要求绑定JS类必须搭配@staticInterop注解,且实例方法通过扩展类声明,避免release编译优化裁剪绑定,需要先在pubspec.yaml中引入js依赖:
dependencies:
  js: ^0.6.7

修正后的Dart代码如下:

import 'package:js/js.dart';
import 'package:js/js_util.dart';

@JS('walletModule.ClientWallet')
@staticInterop
class ClientWallet {
  external factory ClientWallet();
}

extension ClientWalletExt on ClientWallet {
  external Future<void> connect();
  external void disconnect();
  external String get address;
  external Future<void> signTransaction();
  external bool isPhantomInstalled();
}

class WalletController extends GetxController {
  Future<void> connectWallet(context) async {
    ClientWallet wallet = ClientWallet();
    if (wallet.isPhantomInstalled()) {
      await promiseToFuture(wallet.connect());
      createSnackbar('success', 'Wallet Connected');
    } else {
      createSnackbar('error', 'No Phantom wallet detected');
    }
  }
}
  1. 清理JS侧冗余定义
    删除JS侧和实例属性重名的address()方法,避免命名冲突:
class ClientWallet {
    constructor() {
        this.address = '';
    }

    async connect() {
        const resp = await window.solana.connect();
        this.address = resp.publicKey.toString();
    }

    isPhantomInstalled() {
        return window.solana && window.solana.isPhantom;
    }

    disconnect() {
        window.solana.disconnect();
    }
}

var walletModule = { ClientWallet: ClientWallet };
  1. 调整JS加载顺序
    将你的自定义JS文件放在web/index.html的main.dart.js加载之前,确保全局对象提前挂载:
<head>
  <!-- 其他头部配置 -->
  <script src="你的自定义JS文件路径.js"></script>
  <script src="main.dart.js" type="application/javascript"></script>
</head>
  1. 可选兜底方案
    如果仍存在绑定问题,可以改用js_util的动态调用方法,避免编译优化导致的方法名丢失:
// 把wallet.isPhantomInstalled()替换为下面的写法
bool isInstalled = callMethod(wallet, 'isPhantomInstalled', []);

内容的提问来源于stack exchange,提问作者ggiurca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 05:54:03