javascript - 当未加载/被广告拦截器阻止时,firebase_analytics 使 Flutter Web 应用程序崩溃
问题描述
当用户启用了阻止firebase-analytics.js
. 我只剩下一个空白页。
这是我收到的错误:
top_level.dart.lib.js:110 Uncaught (in promise) TypeError: dart.global.firebase.analytics is not a function
at Object.analytics$ [as analytics] (top_level.dart.lib.js:110)
at new firebase_analytics_web.FirebaseAnalyticsWeb.new (:7357/packages/firebase_analytics_web/firebase_analytics_web.dart.lib.js:56)
at Function.registerWith (:7357/packages/firebase_analytics_web/firebase_analytics_web.dart.lib.js:19)
at Object.registerPlugins (:7357/packages/triage/generated_plugin_registrant.dart.lib.js:13)
at main (:7357/web_entrypoint.dart.lib.js:29)
我正在使用以下版本的firebase_analytics
插件:
firebase_analytics: ^7.1.1
解决方案
问题
发生这种情况是因为firebase
包(由 使用firebase_analytics_web
)依赖于 JSfirebase.analytics()
中存在的函数。请参阅相关的代码。
因此,当广告拦截器阻止加载时,这段代码会抛出,进而导致整个 Flutter Web 初始化崩溃。firebase-analytics.js
解决方案
我们可以创建一个mock来firebase.analytics()
解决这个问题。请注意,在 中firebase_analytics_web
,该firebase.analytics()
函数仅被调用一次,然后存储在一个实例中。这就是为什么我们的模拟必须确保以某种方式firebase.analytics()
再次调用 JS,如果我们希望能够firebase-analytics.js
在稍后的时间点加载到库中。
这是一个脚本,您<body>
至少可以在加载后插入firebase-app.js
。例如,如果您遵守 GDPR 并异步加载 Firebase 分析(例如在用户通过 Google 跟踪代码管理器同意之后),这将非常有用。无论如何,这是一个完全解决问题并允许稍后加载 Firebase Analytics 的模拟:
<!--
We need to create a mock for Firebase Analytics that ensures that it *does not matter **when***
the JS library is loaded. This is because Google Tag Manager will load firebase-analytics.js
and this 1. happens asynchronously and 2. only after the user consented.
The firebase.dart Dart library will crash if the firebase.analytics object does not exist,
which is why this is absolutely crucial for starting the app.
https://stackoverflow.com/a/66589887/6509751
-->
<script>
// This mock ensures that if the firebase_analytics Flutter plugin uses this mock as its
// instance (which does not change over time), the plugin will *still* be able to reach out
// to the actual firebase.analytics() instance because the object will be overridden once the
// firebase-analytics.js library is loaded in.
firebase.analytics = function () {
return {
mock: true,
app: function () {
var instance = firebase.analytics()
// Prevent infinite recursion if the real instance has not yet been loaded.
if (instance.mock === true) return
return instance.app
},
logEvent: function () {
var instance = firebase.analytics()
if (instance.mock === true) return
return instance.logEvent(...arguments)
},
setAnalyticsCollectionEnabled: function () {
var instance = firebase.analytics()
if (instance.mock === true) return
return instance.setAnalyticsCollectionEnabled(...arguments)
},
setCurrentScreen: function () {
var instance = firebase.analytics()
if (instance.mock === true) return
return instance.setCurrentScreen(...arguments)
},
setUserId: function () {
var instance = firebase.analytics()
if (instance.mock === true) return
return instance.setUserId(...arguments)
},
setUserProperties: function () {
var instance = firebase.analytics()
if (instance.mock === true) return
return instance.setUserProperties(...arguments)
},
}
}
</script>
推荐阅读
- php - 会话超时卡在循环中
- android - 打开 AVD 管理器时出现 Android Studio 错误
- wpf - Oxyplot:禁用跟踪器
- c - 可以使用指向结构成员的指针来访问同一结构的另一个成员吗?
- reactjs - 在父组件的 ViewStore 中跟踪状态变化
- javascript - HTML 文件调用计算函数
- postgresql - 突变缓存更新不适用于 vue-apollo 和 Hasura
- firebase - Flutter/Firebase - 如何在 Android 上获得“提醒”通知?
- arrays - findOneAndUpdate 导致重复问题
- java - JAVA,棋盘游戏。随机骰子数字不是随机的