Flutter集成Pi Network JavaScript SDK遇require.js匹配错误求助
解决Flutter Web集成Pi Network JS SDK时的require.js匹配错误
我在为Pi Network黑客松开发Flutter Web应用,需要集成Pi官方提供的JS SDK,但直接用js.context.callMethod("eval")加载require.js模块时,遇到了以下错误:
Error: Mismatched anonymous define() module: function() { return CanvasKitInit; }
错误原因
Flutter Web默认使用CanvasKit渲染引擎,它内部通过AMD规范的define()定义了匿名模块。而用require.js加载Pi SDK时,require.js会扫描页面中所有的define模块,导致与CanvasKit的匿名模块冲突,触发匹配错误。
解决方案
放弃使用require.js加载SDK,改用直接注入script标签的方式加载Pi SDK,直接访问全局的Pi对象。
方法1:提前在web/index.html中加载SDK
修改web/index.html,在<body>标签内(Flutter脚本之前)添加Pi SDK的script引用:
<body> <!-- 添加Pi SDK引用 --> <script src="https://sdk.minepi.com/pi-sdk.js"></script> <script> var serviceWorkerVersion = null; 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); } </script> <!-- 其他Flutter默认代码 --> </body>
然后修改Dart代码,直接调用全局Pi对象:
import 'dart:js' as js; class Test2 extends StatelessWidget { const Test2({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: TextButton( child: const Text("click"), onPressed: () { // 获取全局Pi对象 final pi = js.context['Pi']; if (pi == null) { print("Pi SDK未加载完成,请检查网络或加载顺序"); return; } // 初始化SDK pi.callMethod('init', [js.JsObject.jsify({'version': '2.0'})]); // 定义认证需要的回调 void onIncompletePaymentFound(js.JsObject payment) { // 处理未完成支付逻辑 print('发现未完成支付:${payment.toString()}'); } // 发起认证 pi.callMethod('authenticate', [ ['payments'], js.allowInterop(onIncompletePaymentFound) ]).then((authResult) { print('认证成功!可以发起支付了'); }).catchError((error) { print('认证失败:$error'); }); }, ), ), ); } }
方法2:在Dart中动态注入script标签
如果不想修改index.html,可以在Dart代码中动态创建script标签加载SDK:
import 'dart:js' as js; import 'package:flutter/material.dart'; void loadPiSdk(VoidCallback onLoaded) { final script = js.context['document'].callMethod('createElement', ['script']); script['src'] = 'https://sdk.minepi.com/pi-sdk.js'; script['onload'] = js.allowInterop(onLoaded); script['async'] = true; // 将script插入到head中 js.context['document'].callMethod('getElementsByTagName', ['head'])[0] .callMethod('appendChild', [script]); } // 在StatefulWidget的initState中调用加载 class Test2 extends StatefulWidget { const Test2({super.key}); @override State<Test2> createState() => _Test2State(); } class _Test2State extends State<Test2> { bool _piLoaded = false; @override void initState() { super.initState(); loadPiSdk(() { setState(() { _piLoaded = true; }); }); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: _piLoaded ? TextButton( child: const Text("click"), onPressed: () { // 认证逻辑与方法1一致 final pi = js.context['Pi']; pi.callMethod('init', [js.JsObject.jsify({'version': '2.0'})]); void onIncompletePaymentFound(js.JsObject payment) { print('发现未完成支付:${payment.toString()}'); } pi.callMethod('authenticate', [ ['payments'], js.allowInterop(onIncompletePaymentFound) ]).then((_) { print('认证成功!'); }).catchError((e) => print('认证失败:$e')); }, ) : const CircularProgressIndicator(), ), ); } }
关键注意点
- 必须使用
js.allowInterop()包装Dart回调函数,否则JS无法正确调用Dart方法。 - 确保SDK加载完成后再调用Pi的API,避免出现
Pi is undefined的错误。 - 如果你是开发Flutter移动端(而非Web),这种JS集成方式不适用,移动端需要考虑WebView嵌套等方案。
内容的提问来源于stack exchange,提问作者Open Alkw
相关产品推荐
相关产品推荐

