-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Description
We're headlining Fraggle Rock in the Lighthouse 10.0 release, asking folks to try out a new API, so this is the best opportunity to make substantial changes to the Legacy and Fraggle-Rock-preview APIs for understandability and easy of use.
Our current architecture is something like:
┌──────────┬────────────┬───────────┐
│ CLI │ DEVTOOLS │ LR │
├──────────┴────────────┴───────────┤
│ CORE │
└───────────────────────────────────┘
(feel free to imagine a better diagram :)
There's also an implicit client in the top level: node users enter into core/ directly and that exacerbates the main issue, which is how things are divided up. eg. chrome-launching is in cli/, so is an annoying detail to handle yourself if using the node module, while -GA is in core, which can cause issues with bundling since the other clients don't have a disk to load from or save to. You also end up with having to anticipate how these layers interact making things more complex and requiring support for core to possibly connect to a browser rather than simply having a Page passed in or not.
Proposal
Instead, we make a place for those decisions while simultaneously making cli/ and core/ simpler and the node experience more featureful.
I've played with a few refactors, but I'm very partial to @patrickhulce's suggestion in #12393 (comment), which is basically make a new top-level node/ directory that handles stuff currently in cli/ that isn't specific to a CLI, and stuff currently in core/ that (as a general rule of thumb) isn't needed for the DevTools and LR bundles:
┌──────────┐
│ CLI │
├──────────┼────────────┬───────────┐
│ NODE │ DEVTOOLS │ LR │
├──────────┴────────────┴───────────┤
│ CORE │
└───────────────────────────────────┘
New cli/
- parse cli flags
- custom exit codes where needed
node/
- launch Chrome
-GA- save reports to disk
- Sentry(?)
- node entry point (new package.json
main) - public types (#1773)
Some of core/ and node/ would be repeating each other (like a lot of re-exporting what's in fraggle-rock/api.js, wherever that ends up), but it wouldn't be that large and it would allow for a well documented and curated main export from lighthouse, free from e.g. the extras that the different clients need out of core/.
API
As a rough starting point (more or less what we have now):
function generateConfig(configJson?: LH.Config.Json, flags?: LH.Flags): Config
function lighthouse(url?: string, flags?: LH.Flags, configJSON?: LH.Config.Json, page?: LH.Puppeteer.Page): Promise<LH.RunnerResult | undefined>
/** @deprecated */
function legacyNavigation(url?: string, flags?: LH.Flags, configJSON?: LH.Config.Json, userConnection?: Connection): Promise<LH.RunnerResult | undefined>
function startFlow(page: LH.Puppeteer.Page, options?: {name?: string, config?: LH.Config.Json, configContext?: LH.Config.FRContext}): Promise<UserFlow>
function navigation(requestor: LH.NavigationRequestor | undefined, options: {page?: LH.Puppeteer.Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}): Promise<LH.RunnerResult|undefined>
function snapshot(options: {page?: LH.Puppeteer.Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}): Promise<LH.RunnerResult|undefined>
function startTimespan(options: {page?: LH.Puppeteer.Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}): Promise<{endTimespan: () => Promise<LH.RunnerResult|undefined>}>The biggest opportunity for improvement is probably a pass or two rationalizing configJson, flags, and configContext before we foist them on the world :)
There's also a lot of legacy re-exports, that I think it would be helpful to revisit. e.g. lighthouse.Audit and lighthouse.Gatherer
- The new
base-gathererhas no imports of its own, just types. Maybe we should switch just to type enforcement rather than asking custom gatherers to extend a class that does nothing? - Similarly, core
Auditstuff is just types, can it also switch to just an interface and all helper functions move off ofAuditand into a module of audit utilities?
Public types
We're at the point that putting together public types could be a useful exercise for improving Lighthouse's API. Through transitive types we currently expose more or less the entire Lighthouse universe through core/index.js, and the best places to cut the type graph seem also to be some of the best places to cut our own dependency graph (e.g. base-gatherer.js and audit.js).
If we get serious about plugins again, we could publish a separate types package, something like @types/lighthouse-plugins/@types/lighthouse-deep-cuts or whatever, allowing deep requires into select parts of lighthouse to be typed for use in plugins.