GoogleChrome / lighthouse

Automated auditing, performance metrics, and best practices for the web.
https://developer.chrome.com/docs/lighthouse/overview/
Apache License 2.0
28.22k stars 9.35k forks source link

Need some advice for test mobile page which contains custom protocol request #10161

Closed kkdev163 closed 4 years ago

kkdev163 commented 4 years ago

Recently I find a page's performance varied a lot, from 40 to 90. And I find when the score is 40, there is no load event fired in the trace log, so the lighthouse will wait for page load utils max-wait-for-load(in my case is 10s). In the waiting time, page's timer fired, this timer will load an SDK, this will impact the metrics of CPU-idle and interactive.

Now we find the main reason that cased this page not fire load event, is this page was designed for hosting in the mobile app, so it uses a custom protocol to invoke native ability. Code example like below:

    function invokeNative(method) {
         location.href = `orpheus://${method}`;
    }

In the native app, it may rewrite the webView' shouldOverrideUrlLoading method, to provide native ability。

But in our Lighthouse test, this function call will trigger frame navigation, then trigger a network request, but this request will be canceled(by chrome?)soon. I guess this is the main reason that the load event not fired. (we had confirmed this by removing the code of native call, then the load event will normal fired.)

To let the load event fired normally, I tried blocked-url-patterns to block requests starts with custom protocol, but it not work.

Then, in the gather/driver.js I try to add this logic:


async beginTrace() {
    ...
    await this.sendCommand('Fetch.enable', {
          urlPattern: 'orpheus://*'
    };
    this.on('Fetch.requestPaused', (event) => {
      const {requestId, request} = event;
      if (!request.url.startsWith('orpheus')) {
        return this.sendCommand('Fetch.continueRequest', {
          requestId
        });
      }
      this.sendCommand('Fetch.fulfillRequest', {
        requestId: event.requestId,
        responseCode: 200
      })
    });
}

but this still not work.

So is there any other API provided by devtools to intercept the custom protocol request or intercept the frame navigation?

load event not fired can test in this page

Thanks for your advice.

connorjclark commented 4 years ago

Here's my understanding: you've (properly) setup Fetch interception, you're redirecting the page to a custom scheme, the interception works (right? can you confirm that Fetch.requestPaused is hit), the document redirection is committed but load never fires. Does that sound correct?

I'd expect this protocol method to work for arbitrary URL schemes. Don't see anything wrong with your usage of Fetch. You'll find more knowledgeable people on this mailing list.

connorjclark commented 4 years ago

image

I think it's related to this prompt. LH hung for me at this point. Suggests that Chrome isn't intercepting custom schemes on redirect.

kkdev163 commented 4 years ago

Here's my understanding: you've (properly) setup Fetch interception, you're redirecting the page to a custom scheme, the interception works (right? can you confirm that Fetch.requestPaused is hit), the document redirection is committed but load never fires. Does that sound correct?

It seems the location.href='orphues://method' cause the 'load' not fire , so I am trying to intercept this request by Fetch. enable , but Fetch.requestPaused not hit the request starts of 'orphues'.

kkdev163 commented 4 years ago

image

I think it's related to this prompt. LH hung for me at this point. Suggests that Chrome isn't intercepting custom schemes on redirect.

Thanks for finding this, it related to OS? In my macOS, it haven't prompted this. if this is related to this prompt, can you give me some advice about how to avoid this? It seems lighthouse driver has already called dismissJavaScriptDialogs, is this prompt invoked by chrome? Can we use some chrome flag to avoid system prompt?

Thanks.

paulirish commented 4 years ago

hi @kkdev163

SO just to back up.. setting location.href= will navigate to a brand new page. Lighthouse doesn't really handle this case.

But moreover... location.href='orphues://method' basically is exiting the browser session and going into the native app. At this point, Lighthouse has no idea because Lighthouse can only audit what Chrome sees.

If you care about the Lighthouse report, I would disable that location.href setter entirely. :)

(Also it's really cool that you dug into the internals to try to get blocked urls to work, but we didn't intend that feature to handle new navigations)