-
Notifications
You must be signed in to change notification settings - Fork 9.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core: special case AppManifest as baseArtifact #6957
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this :)
types/artifacts.d.ts
Outdated
@@ -29,6 +29,8 @@ declare global { | |||
NetworkUserAgent: string; | |||
/** The benchmark index that indicates rough device class. */ | |||
BenchmarkIndex: number; | |||
/** The application manifest if one was fetched. */ | |||
AppManifest: Artifacts.Manifest | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to me this makes me question if it's actually related to an appcache manifest :) If we want to be more precise, how do you feel about WebAppManifest
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
someone should tell driver and the devtools protocol then 😛
that wfm 👍
* @param {LH.Gatherer.PassContext} passContext | ||
* @return {Promise<LH.Artifacts['Manifest']>} | ||
*/ | ||
static async getAppManifest(passContext) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we merge most of this into driver.getAppManifest()
? Not the baseArtifacts
check, of course, and probably not the parse step(?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah good idea 👍
|
||
const manifestPromise = passContext.driver.getAppManifest(); | ||
/** @type {Promise<void>} */ | ||
const timeoutPromise = new Promise(resolve => setTimeout(resolve, 3000)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can remove this with the default timeouts now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of keeping it short though, I'll set it to 3s 👍
* Uses the debugger protocol to fetch the manifest from within the context of | ||
* the target page, reusing any credentials, emulation, etc, already established | ||
* there. The artifact produced is the fetched string, if any, passed through | ||
* The artifact produced is the fetched manifest string, if any, passed through | ||
* the manifest parser. | ||
*/ | ||
class Manifest extends Gatherer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason to keep this? TODO for followup to split up the changes nicely? Or is it worth keeping for some reason?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
meh, I'll just do it now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
boy am I regretting that 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I'm gonna make this a TODO
@@ -20,6 +20,7 @@ declare global { | |||
options?: object; | |||
/** Push to this array to add top-level warnings to the LHR. */ | |||
LighthouseRunWarnings: Array<string>; | |||
baseArtifacts: BaseArtifacts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we might want to play around with Readonly
for this, but that can be something for another day :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@@ -61,7 +54,7 @@ class StartUrl extends Gatherer { | |||
* @param {string} startUrl | |||
* @return {Promise<{statusCode: number, explanation: string}>} | |||
*/ | |||
_attemptManifestFetch(driver, startUrl) { | |||
_attemptStartURLFetch(driver, startUrl) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ha, whoops
looks like some fragile mocks broke :S |
@brendankenny this is ready for a second look now btw |
types/artifacts.d.ts
Outdated
@@ -29,6 +29,8 @@ declare global { | |||
NetworkUserAgent: string; | |||
/** The benchmark index that indicates rough device class. */ | |||
BenchmarkIndex: number; | |||
/** Parsed version of the page's Web App Manifest, or null if none found.. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no double .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
describe('.getAppManifest', () => { | ||
it('should return null when no manifest', async () => { | ||
const sendCommand = jest.spyOn(connection, 'sendCommand'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spyOn
is a little hard to read to me because I expect it to be spied upon at that point. How do you feel about just doing the plain connection.sendCommand = jest.fn().mockResolvedValueOnce({data: undefined, url: '/manifest'});
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure that's fine
* will have the reason. See manifest-parser.js for more information. | ||
* | ||
* @param {LH.Gatherer.PassContext} passContext | ||
* @return {Promise<LH.Artifacts['Manifest']>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we're going to eventually ditch LH.Artifacts['Manifest']
, switch to LH.Artifacts['WebAppManifest']
(or LH.Artifacts.Manifest|null
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -467,6 +493,7 @@ class GatherRunner { | |||
} | |||
await GatherRunner.beforePass(passContext, gathererResults); | |||
await GatherRunner.pass(passContext, gathererResults); | |||
baseArtifacts.WebAppManifest = await GatherRunner.getWebAppManifest(passContext); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have two other checks against isFirstPass
already in this method, can we move the check for this line out here too and avoid putting it on passContext
(and it'll be more obvious we aren't overwriting it on every turn of the loop)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, done
} | ||
|
||
/** | ||
* Read the parsed manifest and return failure reasons or the startUrl | ||
* @param {?{value?: {start_url: {value: string, warning?: string}}, warning?: string}} manifest | ||
* @param {LH.Artifacts['Manifest']} manifest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LH.Artifacts['WebAppManifest']
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
assert.equal(artifact.explanation, 'Timed out waiting for fetched start_url.'); | ||
}); | ||
const resultPromise = startUrlGatherer.afterPass(passContext); | ||
jest.advanceTimersByTime(5000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wellllllll this is nice
driver: wrapSendCommand(mockDriver, 'https://ifixit-pwa.appspot.com/', 200, true), | ||
}; | ||
const optionsWithQueryString = { | ||
const passContextWithFragment = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:)
}); | ||
|
||
afterEach(() => { | ||
jest.advanceTimersByTime(5000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this needed after each test is done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the other tests not touched by this don't properly cleanup their timer, I'll add a todo to fix this another time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the other tests not touched by this don't properly cleanup their timer, I'll add a todo to fix this another time?
yeah, sounds good. I think advanceTimersByTime
is going to be a game changer for a lot of our older tests and it would be nice to update anyways
*/ | ||
static async getWebAppManifest(passContext) { | ||
// If we already have a manifest, return it. | ||
if (passContext.baseArtifacts.WebAppManifest) return passContext.baseArtifacts.WebAppManifest; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not needed with the isFirstPass
check below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair, removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a lot cleaner to my eyes. excited for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah! love it
}); | ||
|
||
afterEach(() => { | ||
jest.advanceTimersByTime(5000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the other tests not touched by this don't properly cleanup their timer, I'll add a todo to fix this another time?
yeah, sounds good. I think advanceTimersByTime
is going to be a game changer for a lot of our older tests and it would be nice to update anyways
Whatever's been done with the PWA tester in Lighthouse seems to have (or may have) broken it with regards to testing Performance in the other parts of the audit, as well as blocked the PWA audit score as well. In Chrome 71 (still current as I write this), this site gets 100% on performance and PWA; in the Chrome 74.0.3686.0 available today, this site gets 0% performance and 0% PWA despite 100 in all PWA categories except 2 of them: https://ives-fourth-symphony.com This may or may not be related to the manifest fetching rewrite, but the coincidence of the two prompted me to report this here. |
Thanks @tmb-github! The version of Lighthouse in Chrome doesn't have this commit yet, and locally this hash passes on that site, so looks like they're unrelated. Is it possible you're bumping into #6968? |
Please try the same audit again on the new stable Chrome 72.0.3626.81 (Official Build) (64-bit), released today. Nothing can be fetched for the PWA audit nor the Performance audit. |
Thanks @tmb-github it's due to some infrastructure serving outdated version of audits panel that's incompatible with newer Chrome. The team is on it. |
Summary
See #6882 (comment)
Cleans up our start URL gatherer to not fetch and parse the manifest again.
Related Issues/PRs
@brendankenny's preferred implementation of #6882
closes #6881