-
Notifications
You must be signed in to change notification settings - Fork 9.6k
report: extract independent report types #12946
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
Conversation
| @@ -0,0 +1,18 @@ | |||
| /** | |||
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.
added a new eslintrc for report/ to make it env browser and remove the ad hoc /* global document window */ and /* eslint-env browser */s sprinkled throughout some of the files.
Also, turns out eslintrc files automatically extend any other eslintrc files up through to the root directory, though I added a root: true in the root file just to make it clear
report/tsconfig.json
Outdated
| // Limit to base JS and DOM defs. | ||
| "lib": ["es2020", "dom", "dom.iterable"], | ||
| // Include `@types/node` for use of `Buffer` in text-encoding.js. | ||
| "types": ["node"], |
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 use of Buffer in text-encoding.js prevents getting rid of node types for these files. I was tempted to write a little type shim just for Buffer to keep out @types/node, but it seemed a bit too fragile. Maybe worth it at some point
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 use of
Bufferintext-encoding.jsprevents getting rid ofnodetypes for these files. I was tempted to write a little type shim just forBufferto keep out@types/node, but it seemed a bit too fragile. Maybe worth it at some point
trying out viewer types on top of this, I think we actually do want a little Buffer shim. The node types infect everything (we end up with errors on setTimeout return types, for instance, if viewer doesn't also import @types/node, which is just getting silly by that point)
| {"path": "./generator/"} | ||
| ], | ||
| "exclude": [ | ||
| "generator/**/*.js", |
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 didn't realize generator/* files would be included even though generator/ is in references and has its own tsconfig. Having to explicitly exclude these is one more argument not to nest generator under report, I think (see other options in #12940 (comment)).
| } | ||
| } | ||
|
|
||
| export {}; |
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.
what's the force module situation these days such that this isn't necessary? I feel like I remember reading a PR description or comment about this recently, but couldn't find it quickly.
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.
what's the force module situation these days such that this isn't necessary? I feel like I remember reading a PR description or comment about this recently, but couldn't find it quickly.
it's kind of dumb: if there's any import or export statements, the file is a module (which is why we had the empty ones in there before when everything was in one or two files and we didn't have any imports), and if you want an explicit declare global {} block in there it has to be a module, otherwise it's ambient and everything is a global type.
Fortunately(?) we almost always have import statements these days, and the error message is a lot better, basically saying you can't declare global unless this file is a module.
I vaguely recall a few years back in the es modules transition wars the idea of using that same heuristic to automatically detect if a file was an .mjs vs .cjs file without a file extension/package.json type entry, and then everyone realized that would be super fragile and annoying and decided not to go that way. But here it is anyways :)
patrickhulce
left a comment
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.
LGTM
|
|
||
| // Expose global types in LH namespace. | ||
| module LH { | ||
| export import ReportResult = _ReportResult; |
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.
Oh interesting I wouldn't have expected export import to be needed since we're reassigning.
does this differ from export type ReportResult = _ReportResult; or because it's a module we can't do that and export import is the only valid way?
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.
Oh interesting I wouldn't have expected
export importto be needed since we're reassigning.does this differ from
export type ReportResult = _ReportResult;or because it's a module we can't do that andexport importis the only valid way?
yeah, you get the interface but not the module, so e.g. LH.ReportResult.AuditRef won't resolve
| /** | ||
| * @param {DOM} dom | ||
| * @param {{fullPageScreenshot?: LH.Artifacts.FullPageScreenshot}} [options] | ||
| * @param {{fullPageScreenshot?: LH.Audit.Details.FullPageScreenshot}} [options] |
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 this starts to illustrate how the boundaries are hard to see here (glancing at this without context, I wouldn't expect LH.Audit to be within the self-contained report context
Long-term do you plan to renamespace the report to LHReport or LH.Report. or similar?
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 this starts to illustrate how the boundaries are hard to see here (glancing at this without context, I wouldn't expect
LH.Auditto be within the self-contained report contextLong-term do you plan to renamespace the report to
LHReportorLH.Report.or similar?
Yeah, it's a really good question. I'm not sure. I defaulted to maintaining the familiar LH.* hierarchy, but in the report files, the LH.Audit namespace is empty except for Details:
module LH {
module Audit {
export import Details = AuditDetails;
}
}so seems doubly weird to maintain it? Not that useful in the report if considered in isolation, and if the goal is consistency across files, it's actually misleading because you might think e.g. LH.Audit.ScoreDisplayMode is going to be in there too.
So long term it may make sense to re work the names, but then it's asking everyone to keep track of multiple names for the same thing...
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.
Maybe if microsoft/TypeScript#41825 is fixed, core could keep the global types and the other areas with fewer files and fewer type needs could just do
/** @typedef {import('../../lhr/audit-details')} AuditDetails */
export class DetailsRenderer {
/**
* @param {DOM} dom
* @param {{fullPageScreenshot?: AuditDetails.FullPageScreenshot}} [options]
*/
constructor(dom, options = {}) {
this._dom = dom;
this._fullPageScreenshot = options.fullPageScreenshot;
}
}Without that issue fixed, though, we'd be stuck with
/** @typedef {import('../../lhr/audit-details').FullPageScreenshot} FullPageScreenshot */
/** @typedef {import('../../lhr/audit-details').OpportunityColumnHeading} OpportunityColumnHeading */
/** @typedef {import('../../lhr/audit-details').TableColumnHeading} TableColumnHeading */
/** @typedef {import('../../lhr/audit-details').List} List */
/** @typedef {import('../../lhr/audit-details').NodeValue} NodeValue */
// ...:(
5533b93 to
789560b
Compare
Isolates
report/as a typescript "project" allowing it to live off in its own type world. This allows it to be browser specific and not bring in the entire lighthouse-cli/lighthouse-core/etc world just to type check the report.Dependencies are simpler and (because of the expanded
-bmode) more compilation caching occurs which means faster follow-up type checks (e.g. if you're working on core and haven't touched the report, theyarn tsc -b report/part will finish in 200ms because the cached.tmp/tsbuildinfofile will be newer than all the files inreport/).The bulk of this PR is splitting up a few more
d.tsfiles for e.g. the parts ofhtml-renderer.d.tsthattreemapandviewerneed vs the parts they don't.I'll follow this PR with changes to make
treemap/,viewer/, andflow-report/to do the same to them. This will be especially helpful for treemap and viewer since they recompile large parts of core due to transitive type deps. There will also probably need to be a final clean up pass to better use tsconfig inheritance and some documentation.