-
Notifications
You must be signed in to change notification settings - Fork 102
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
findFirstExistingPath
is extremely slow
#72
Comments
So, the problem seems to be this: tsconfig-paths/src/mapping-entry.ts Lines 37 to 44 in 6beaeaf
I mean the comment there explains pretty clearly why it does that, but the problem is that it runs the path resolution for all of |
I think it seems reasonable to make it configurable. It is open for a PR if you want to add it. |
Thanks, will do :-) |
just tried commenting out the code and can confirm that removing the match-all cuts the |
this solves part of dividab#72
this solves part of dividab#72
Running into this as well at the moment. Is it possible to invert, or provide configuration to invert the module resolution strategy? So, if specified, allow the original module resolver to be run first, and if it wasn't able to locate the module then run the internal ts-config-paths resolver? Any thoughts @jonaskello? Worth noting this would likely fix the 2nd half of @Swatinem issue, where |
Hm, in our specific usecase, we want to rewrite Its just that the match-all rule is something that normal node developers just do not expect. I have also looked at https://www.typescriptlang.org/docs/handbook/module-resolution.html shortly. And I think that the match-all behavior is what the
That is basically what this match-all rule achieves, plus it uses all the But when you specify
So I have looked it up and we definitely have the wrong |
@Swatinem — I have upgraded to the new version that contains your fix, I am still getting a 7 - 12 second boot up time for a relatively small project that's 98% JavaScript (we're trying to move to TS incrementally). Without this plugin we'll have to go back to |
Since I didn’t want this to break anything, the default is to still enable the match-all rule. |
Just a thought, have you tried setting it up as a monorepo with |
Would you mind sharing any links or further expanding on what you suggested? I’d like to investigate it further but our team is new to TS.
So far this is our biggest hurdle trying to transition. Face the slow compile times or extra generation step, or return to path tree madness that we were shielded from via using NODE_PATH! 😞
|
So monorepos is not typescript specific. It just means you have several packages in the same git repo. So you split your app in several npm packages with their own package.json even if you don't intend to publish them because then you can import them using Once you have split your app into separate packages, you can make The basic idea is that all packages reference each other through regular node resolution, which is just look upward for |
@jonaskello - thank you, that has been incredibly informative, and the number of tabs I now have open is a testament to the rabbit hole I've been pulled into. This looks like a great direction to go, and using lerna will fix a few problems we saw on the horizon (shared library for frontend and backend)...! In the mean time, would you help me run the new performance change? I am using it via Thank you. |
You have to create your own register hook, like explained here: https://github.com/dividab/tsconfig-paths#bootstraping-with-explicit-params |
@Swatinem — thanks! I got it working using that method, and there's no difference in speed for me regardless of what |
Hm, I just tested this on our codebase, and with the following require('source-map-support').install()
const fsExtra = require('fs-extra')
const path = require('path')
const tsConfigPaths = require('tsconfig-paths')
const baseUrl = path.join(__dirname, '..')
// eslint-disable-next-line
const tsConfig = new Function(`return ${fsExtra.readFileSync(path.join(baseUrl, 'tsconfig.json'), 'utf-8')}`)()
tsConfigPaths.register({
baseUrl,
paths: tsConfig.compilerOptions.paths,
addMatchAll: false,
}) |
We cannot for the life us get this to improve the compilation speed. We have ultimately been forced to back down from TS until we move to the yarn workspaces/monorepo set up so module resolution will work out of box without an additional step. Thanks a lot for your help! |
Hi all, just run into the same problem that the TL;DRUsing The problemUsing Typescript and postcards with webpack to build our own web application. Most of the part that includes // setup hooks for webpack 4
if (compiler.hooks) {
compiler.hooks.compilation.tap('HtmlWebpackPluginHooks', compilation => {
---> const SyncWaterfallHook = require('tapable').SyncWaterfallHook;
const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook;
compilation.hooks.htmlWebpackPluginAlterChunks = new SyncWaterfallHook(['chunks', 'objectWithPluginRef']);
compilation.hooks.htmlWebpackPluginBeforeHtmlGeneration = new AsyncSeriesWaterfallHook(['pluginArgs']);
compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing = new AsyncSeriesWaterfallHook(['pluginArgs']);
compilation.hooks.htmlWebpackPluginAlterAssetTags = new AsyncSeriesWaterfallHook(['pluginArgs']);
compilation.hooks.htmlWebpackPluginAfterHtmlProcessing = new AsyncSeriesWaterfallHook(['pluginArgs']);
compilation.hooks.htmlWebpackPluginAfterEmit = new AsyncSeriesWaterfallHook(['pluginArgs']);
});
} ReasonEvery time the For some Js project, there’re still quite a lot of places that put the require in the function body instead of extracting then out to the top of the script, which cause this problem. But still, it is not a good thing that the part called Screenshots: It is stocked by the SuggestionI'm not familiar with the ts-config code base but I think we can introduce cache to the part // Some where as a file variable
const NOT_EXISTS = {};
const __matchPathCache = {};
// Inside register.js
Module._resolveFilename = function(request: string, _parent: any): string {
const isCoreModule = coreModules.hasOwnProperty(request);
if (!isCoreModule) {
+ if (request) {
+ found = __matchPathCache[request];
+ } else {
+ found = matchPath(request);
+ __matchPathCache = found || NOT_EXISTS;
+ }
+ if (found && found !== NOT_EXISTS) {
const modifiedArguments = [found, ...[].slice.call(arguments, 1)];
// Passes all arguments. Even those that is not specified above.
// tslint:disable-next-line:no-invalid-this
return originalResolveFilename.apply(this, modifiedArguments);
}
}
// tslint:disable-next-line:no-invalid-this
return originalResolveFilename.apply(this, arguments);
}; |
|
Sorry, but what is the fix for this? I have one alias and the project is only 4 files, but this adds several seconds to nodemon. I tried the "register" function, but I either implemented it wrong, or it did not help. tsconfig.json
|
We are currently evaluating using
tsconfig-paths/register
together with@babel/register
for a pretty large, mostly js project (slowly migrating to ts)I have found that both of these register hooks have an extreme overhead.
For
tsconfig-paths
, most of that seems to come from a huge amount of filesystem accesses. Using it delays the startup of our app from ~5s to ~7s, and a profile shows quite clearly where the time is going:I haven’t looked too much into what is exactly happening, but what I can say from the profile is that it apparently probes a ton of files before settling on which one to actually use. I will continue investigating and will update this issue with any findings.
The text was updated successfully, but these errors were encountered: