-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
cli: compile out remaining typescript; add tsc type checking via jsdocs #3747
Conversation
😢 |
Just a question why move cli back to js? Just to keep consistency between everything? |
Ha, yeah, probably should have addressed this. We've been split for some time with ts in If we want a unified codebase (language, but also build/test/distribution/run steps), type checking, and to minimize rewrites for the sole purpose of making our tooling happy, continuing with our current code style but checking the types with the Typescript compiler seemed like a good path forward. With Not everyone was completely sold on it, but I was going to check out the feasibility of this. Turns out it's pretty feasible :) (re:unifying things, this PR also removes the separate install/build/test/etc steps from |
This is updated to what it would look like now. Very few changes to our code, at most occasionally doing something kind of awkward to satisfy The typescript compiler walks all dependencies it sees from |
|
||
const log = require('lighthouse-logger'); | ||
// @ts-ignore |
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.
for some reason typescript won't resolve json
files as part of require()
(you get a "Cannot find module '../lighthouse-core/config/perf.json'"
here). Searching didn't find a better solution, and @JoelEinbinder did this in puppeteer, so I'm going with that unless anyone has a better fix :)
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.
did some searching as well, there is no support.
@@ -93,6 +97,9 @@ | |||
"yargs": "3.32.0", | |||
"yargs-parser": "7.0.0" | |||
}, | |||
"resolutions": { |
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.
had to add this as tsc
needs one version of node's d.ts
file, and chrome-launcher
has a specific version while everyone else just does *
. See this discussion (and links in that thread) for background
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.
This is actually pretty nice! I'm pleasantly surprised. The externs typescript ease of declaration is pretty cool mix you get with this method.
// accept noop modules for these, so the real dependency is optional. | ||
import {updateNotifier} from './shim-modules'; | ||
import {askPermission} from './sentry-prompt'; | ||
const updateNotifier = require('update-notifier'); |
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.
intentionally not shimming anymore?
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.
intentionally not shimming anymore?
yeah, I think(?) it only added value to users not installing from package.json
and managing all dependencies themselves (since we didn't add them as peerDependencies
), and I don't think we have any of those users anymore, so it seemed like a good time to remove. No big deal to add back if we want to keep though
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 that seems fine, better to be clear about our non users than half support :)
lighthouse-cli/run.js
Outdated
launchedChrome = launchedChromeInstance; | ||
flags.port = launchedChrome.port; | ||
return lighthouse(url, flags, config); | ||
}).then(results => { |
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.
nit: let's do })\n.then
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
|
||
const log = require('lighthouse-logger'); | ||
|
||
const MAXIMUM_WAIT_TIME = 20 * 1000; | ||
// clang-format off |
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 witch is dead :D
return result.isErrorReportingEnabled; | ||
}), | ||
timeoutPromise, | ||
]); | ||
} | ||
|
||
export async function askPermission() { | ||
/** | ||
* @return {!Promise<boolean>} |
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.
does inquirer
not have types exposed? it'd be nice to reuse them if possible
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 actually do use them above in prompt()
. For here do you just mean so that the return type doesn't have to be explicit? Or something else.
(unfortunately one of the few places the inquirer
type checking is used is broken. inquierer.promprt()
returns a promise decorated with an additional ui
property (allowing prompt.ui.close()
), but the type declaration just calls it a promise, which is why that // @ts-ignore
line has to be up there)
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 they don't have the proper types haha got it carry on 👍
package.json
Outdated
"zone.js": "^0.7.3" | ||
}, | ||
"dependencies": { | ||
"@types/configstore": "^2.1.1", |
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.
how many of these types do we expose in our public facing definitions? feels like a lot could be moved to devDependencies
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.
how many of these types do we expose in our public facing definitions?
I don't actually know how this works, so happy to move them :)
If it's a transitive dep, does the compiler not need types for those as it walks dependencies? Or does it stop at the node_modules
border and just checks use of the public interface of the module? (most of the @types/*
we use don't have deps themselves, but some do...e.g. inquirer
pulls in typings for through
and a bunch of rx
modules)
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.
my understanding is that you need to include any types you expose in your .d.ts
files as dependencies so when consumers try to compile they'll be able to find them.
the only case where you need to include internal type dependencies is when you expect your consumers to also be compiling your ts themselves, not just consuming the type definitions and js. since we have no ts to be compiling, it seems like we should be ok here?
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.
this comment is what led me to believe this
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.
cool, I'll do that then. I can't think of anywhere in our module API where we expose or depend on external types
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. | ||
*/ | ||
|
||
export as namespace LH |
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.
ahhhhhh so here's the magic :)
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.
🎩
⬇️
🐰
Perhaps a really stupid question but do we still need yarn closure to do the type checking? |
In theory, no. We can remove the explicit I imagine we'll keep
We can figure this out going forward. Maybe we should?
There are also some weird jsdoc->tsc behaviors, e.g. there are a few cases where jsdoc types are coerced to |
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! 💯
package.json
Outdated
@@ -47,10 +45,16 @@ | |||
"deploy-viewer": "cd lighthouse-viewer && gulp deploy", | |||
"bundlesize": "bundlesize", | |||
"plots-smoke": "bash plots/test/smoke.sh", | |||
"changelog": "conventional-changelog -n ./build/changelog-generator/index.js -i changelog.md -s" | |||
"changelog": "conventional-changelog -n ./build/changelog-generator/index.js -i changelog.md -s", | |||
"type": "tsc -p ." |
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'd have a slight preference for type-check
or something
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 type
personally. :) but w/e
package.json
Outdated
@@ -47,10 +45,16 @@ | |||
"deploy-viewer": "cd lighthouse-viewer && gulp deploy", | |||
"bundlesize": "bundlesize", | |||
"plots-smoke": "bash plots/test/smoke.sh", | |||
"changelog": "conventional-changelog --config ./build/changelog-generator/index.js --infile changelog.md --same-file" | |||
"changelog": "conventional-changelog --config ./build/changelog-generator/index.js --infile changelog.md --same-file", | |||
"type": "tsc -p ." |
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.
🚲 🏠 slight preference for type-check
or something
switched to |
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'm uncomfortably excited. like so uncomfortable it's awkward.
package.json
Outdated
@@ -47,10 +45,16 @@ | |||
"deploy-viewer": "cd lighthouse-viewer && gulp deploy", | |||
"bundlesize": "bundlesize", | |||
"plots-smoke": "bash plots/test/smoke.sh", | |||
"changelog": "conventional-changelog -n ./build/changelog-generator/index.js -i changelog.md -s" | |||
"changelog": "conventional-changelog -n ./build/changelog-generator/index.js -i changelog.md -s", | |||
"type": "tsc -p ." |
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 type
personally. :) but w/e
"target": "ES2017", | ||
"allowJs": true, | ||
"checkJs": true, | ||
"strict": true, |
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.
When this lands, anyone with an existing checkout will likely want to delete |
WIP PR, though the pieces are all here.Interested in feedback (I've never seriously usedtsc
before).Uses the same approach as puppeteer/puppeteer#986, using the TypeScript compiler's increasingly good jsdoc type support to do type checking of regular JS files. A somewhat minimal
externs.d.ts
file is provided for types that are implicitly or diffusely defined (cliFlags, LHR, auditResults, etc). Only a few// @ts-ignore
and explicit casts added to work around current ts bugs in control flow analysis and type checking.Uses the same async/await code used in the original ts code, but that means it won't work in Node < 8 (hence the 2/3 Travis failures). If we don't want to move to Node 8 yet (#3742), I can move those back to promises.(moved back to promises for node 6+ compat)