Skip to content

Reduce file lookups in node_modules module resolution #16568

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

Closed
wants to merge 6 commits into from
Closed

Conversation

ghost
Copy link

@ghost ghost commented Jun 15, 2017

  • In node_modules, look for a '.d.ts' file before looking for a '.ts' file -- opposite of how it is normally.
  • Never look for node_modules/foo.d.ts, only node_modules/foo/index.d.ts.

Edit by @DanielRosenwasser: Addresses issues seen in #16426.

@ghost ghost force-pushed the dts-first branch from 2acedd6 to a316827 Compare June 15, 2017 20:48
@ghost ghost requested a review from aozgaa June 16, 2017 17:49
TypeScript, /** '.ts', '.tsx', or '.d.ts' */
JavaScript, /** '.js' or '.jsx' */
DtsOnly /** Only '.d.ts' */
const enum Extensions {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name this enum as Extensions seems misleading. I was expecting file extensions....though I have no good idea for alternatives 😞

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about ExtensionsToTry?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe ExtensionsOfKind?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On reflection, calling this ExtensionsToTry is better. Renaming instances to extensionsToTry would help clarify their use as well.

@ghost
Copy link
Author

ghost commented Jun 20, 2017

@yuit @aozgaa Could you give this a review?

"Directory '/node_modules/@types' does not exist, skipping all lookups in it.",
"Loading module 'foo' from 'node_modules' folder, target file type 'JavaScript'.",
"File '/node_modules/foo.js' does not exist.",
"File '/node_modules/foo.jsx' does not exist.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removal of this path lookup seems incorrect.
Refer https://nodejs.org/api/modules.html

LOAD_NODE_MODULES(X, START)

  1. let DIRS=NODE_MODULES_PATHS(START)
  2. for each DIR in DIRS:
    a. LOAD_AS_FILE(DIR/X)
    b. LOAD_AS_DIRECTORY(DIR/X)

It looks like node does look for node_modules/foo.js

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true, but as far as I know, every package manager fills node_modules with only directories, and searching for a file there is costing us a lot of fileExists calls (as you can see from the diff).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pinging @DanielRosenwasser , as he may have some more insight into whether we want to do this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its unlikely we will break anyone with this change, but I'd like to see what kind of performance gain we get out of removing these extraneous lookups.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran the perf tests and there is basically no change between this branch and master -- a 0.5% improvement in parse time.

Copy link
Contributor

@aozgaa aozgaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a technical perspective, looks good modulo the naming of Extensions and some minor nits.

Still not sure we want to go ahead and make this change to explicitly drop supporting node-modules/foo.ts as a target of module resolution.

Can you test the effect of the change on RWC?

@@ -920,22 +939,26 @@ namespace ts {
return combinePaths(directory, "package.json");
}

function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, nodeModulesFolder: string, nodeModulesFolderExists: boolean, failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
// Inside of node_modules we should be looking for '.d.ts' files before '.ts' files.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps:

Inside node_modules, we should look for '.d.ts' ...

}

function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache): SearchResult<Resolved> {
return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache);
// In node_modules, we will look for a '.d.ts' file first.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering what the next line says, not sure what this comment adds.

function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, nodeModulesFolder: string, nodeModulesFolderExists: boolean, failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
// Inside of node_modules we should be looking for '.d.ts' files before '.ts' files.
type NodeModulesExtensions = Extensions.TypeScriptDtsFirst | Extensions.JavaScript | Extensions.DtsOnly;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move this type declaration next to the enum declaration for Extensions.

TypeScript, /** '.ts', '.tsx', or '.d.ts' */
JavaScript, /** '.js' or '.jsx' */
DtsOnly /** Only '.d.ts' */
const enum Extensions {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On reflection, calling this ExtensionsToTry is better. Renaming instances to extensionsToTry would help clarify their use as well.

@@ -32,10 +32,27 @@ namespace ts {
* Kinds of file that we are currently looking for.
* Typically there is one pass with Extensions.TypeScript, then a second pass with Extensions.JavaScript.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment explaining the significance of the enum's members' values.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty heavily commented already, what should I add?

* '.ts', '.tsx', or '.d.ts'
* This is for regular imports of TypeScript code.
*/
TypeScript = "TypeScript",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would adding ('.ts' preferred) make sense here? May clarify debugging for people looking at trace-reoslution output.

@ghost ghost force-pushed the dts-first branch from 2738728 to ed30611 Compare June 26, 2017 22:01
@mhegazy
Copy link
Contributor

mhegazy commented Jan 8, 2018

@Andy-MS please refresh this PR.

@ghost ghost force-pushed the dts-first branch from 62240ee to 5140312 Compare January 12, 2018 18:55
@typescript-bot
Copy link
Collaborator

Thanks for your contribution. This PR has not been updated in a while and cannot be automatically merged at the time being. For housekeeping purposes we are closing stale PRs. If you'd still like to continue working on this PR, please leave a message and one of the maintainers can reopen it.

@jakebailey jakebailey deleted the dts-first branch November 7, 2022 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants