如题,我使用 expo 开发 react native 应用时,使用 react-native-webview 作为 RN 中的 Webview 组件。希望能够使用如 ghostery/adblocker 这样的第三方库来完成广告拦截。但是发现这个 Webview 组件没有开放什么接口可以拦截或者获取一个网页中所有的资源请求,如各种 js 文件,css 文件,这些资源请求没法拦截,所以没法使用 adblocker 完成相应的拦截。
我有一个想法能不能使用原生开发,替换 android 、ios 底层的 webview 组件,然后开放几个函数用于 onLoadStart 、onLoadEnd ,这几个函数可以在 RN 层级中作为参数传给 Webview 组件。这个方案是否可行呢?如果可行的话我的顾虑是:RN 中使用的 react-native-webview 的 webview 组件会不会是自己在底层替换的 webview 组件呢?如果不是,这个应该怎么解决呢?
如果解决思路有问题,非常想请教大家有没有更好的思路呢?
1
mxT52CRuqR6o5 13 天前
用 injectedJavaScriptBeforeContentLoaded 注入 js 代码,hook 会导致资源加载的 api 并 MutationObserver 监视资源加载,进行阻止,不知道行不行
|
2
Mistsink OP @mxT52CRuqR6o5 MutationObserver 只能监听 dom 变化吧,不能监听网络请求呢,这个应该没法做到广告拦截的效果呢,我看主流的那些方案都是拦截网络请求+注入 css+注入 js 来实现的。现在的难点就是怎么拦截所有的网络请求。
|
3
mxT52CRuqR6o5 13 天前
@Mistsink #2 加载 css 、js 通常需要把 link 、script 标签加载到 html 里(但我不清楚 html 首屏的 script 标签 MutationObserver 能不能监听到)
|
4
Mistsink OP @mxT52CRuqR6o5 这里感觉不好控制呢,一旦 MutationObserver 创建的慢了就会漏掉很多,而且可能也会造成性能压力。你觉得呢?
|
7
ltaoo1o 13 天前
没用过 react-native-webview ,用过 flutter-inappwebivew ,思路应该类似。
1. FlutterInAppWebivew 2. Windows Webview2 (原生组件) 在 flutter 端调用 webview 组件并传入 shouldInterceptRequest 属性,此时原生代码调用 Webiview2 ,Webview2 调用 add_WebResourceRequestd 方法可以监听所有网络请求 https://github.com/pichillilorenzo/flutter_inappwebview/blob/master/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp#L874 并调用 flutter 传入的 shouldInterceptRequest https://github.com/pichillilorenzo/flutter_inappwebview/blob/master/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp#L945 在回调中判断 shouldInterceptRequest 是否有返回值,如果没有就不响应(等于拦截了请求),也可以修改响应(返回自定义结果) 上面是 Windows 代码,它还有 ios 和 android 不过我没用上,你可以参考他的原生代码那块。 另外 flutter-inappwebivew 内置了 ad block 功能,也可以参考他是怎么实现的 https://github.com/pichillilorenzo/flutter_inappwebview_examples/tree/main/webview_ad_blocker |
9
Mistsink OP @br_wang 明白,也可以实现,但有的情况,就比如一个 script 标签,我应该拦截他,不能让他加载,但是这种方案不能保证我在他加载运行之前就把他删掉吧?
|
10
Mistsink OP @li1218040201 是,我记得好像 flutter 是开放了这种细粒度的接口,可以针对每个资源的网络请求决定是否拦截,但是 RN 的 webview 没有这种细粒度的,就只有这个网页要不要加载。
我是不是还得像题目里说的那样去改 rn 的 webview 源码,用原生去写呐😂 |
11
daysv 12 天前
注入 service worker , 然后统一拦截
|
13
Mistsink OP |
14
Mistsink OP @br_wang 破案了,根据 html 中的 dom 标签,然后注入相应的 css 和 js 行不通呢,我是拿 https://adblock-tester.com/测试的,分数没变
|
15
ltaoo1o 12 天前
我看了下 API 文档,有个 onShouldStartLoadWithRequest ,具体说明就是可以决定是否继续某个请求,看 issue 也有人问 https://github.com/react-native-webview/react-native-webview/issues/286 ,也是说用这个 API ,这个试试看呢?
|
16
Mistsink OP @li1218040201 hh 就是这个不行呢,只有网页加载时候执行一次,里面的 js 等资源请求时不会触发
|