Skip to content

Consume files generated by other loaders using data['ts-loader-files']#520

Closed
MortenHoustonLudvigsen wants to merge 25 commits intoTypeStrong:masterfrom
MortenHoustonLudvigsen:ts-loader-files
Closed

Consume files generated by other loaders using data['ts-loader-files']#520
MortenHoustonLudvigsen wants to merge 25 commits intoTypeStrong:masterfrom
MortenHoustonLudvigsen:ts-loader-files

Conversation

@MortenHoustonLudvigsen
Copy link
Copy Markdown

This PR creates a mechanism where by ts-loader can consume files generated by other loaders.
Right now this is meant to support ts-css-loader, but it can be used with other loaders, that write to data['ts-loader-files'].

I have not made a test for this PR yet, but I wanted to get the code up here to be reviewed. :-)

See also #512

@johnnyreilly
Copy link
Copy Markdown
Member

Sure - when the tests are green I'll set aside some time for a review.

Comment thread src/index.ts Outdated
}

// Load files generated by previous loaders in the same chain
const generatedFiles = getGeneratedFiles(this);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we put the new functionality behind a loader option please? Something like usePreviousLoaderGeneratedFiles. (Maybe something shorter?) I don't want this to run unless people have "flicked the switch".

So calling getGeneratedFiles etc only happens when you're using usePreviousLoaderGeneratedFiles

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

No problem.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The option usePreviousLoaderGeneratedFiles has been implemented in the latest commit.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Btw. I am happy with the option name usePreviousLoaderGeneratedFiles, but say the word, and I will change it.

Comment thread src/index.ts
const fileVersion = updateFileInCache(filePath, contents, instance);

const { outputText, sourceMapText } = options.transpileOnly
? getTranspilationEmit(filePath, contents, instance, this)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is it significant that it's not passed down to getTranspilationEmit but is to getEmit?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It is only in getEmit that dependencies are handled. Dependencies should not be added for generated files. For example a dependency should not be added for Game.css.d.ts if it is a generated file. We rely on the generator to add any dependencies, that are needed. In this example the generator (ts-css-loader) would add a dependency on Game.css, not Game.css.d.ts witch it generates.

Copy link
Copy Markdown
Author

@MortenHoustonLudvigsen MortenHoustonLudvigsen Apr 13, 2017

Choose a reason for hiding this comment

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

Hmm... I see that the above may not be entirely clear. The reason getEmit recieves generatedFiles is that it adds dependencies, and they need to be filtered so that generated files are excluded. getTranspilationEmit does not add dependencies and so does not need generatedFiles.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I could easily move the filtering of dependencies out of getEmit. That would also make it easy to restrict it to those cases when generated files are enabled.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Filtering of dependencies has been moved to new function removeGeneratedFileDependencies in the latest commit. The call to this function is, of course, only made if the usePreviousLoaderGeneratedFiles option is true.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Actually removeGeneratedFileDependencies has become removeDependencies, and is also used in getEmit instead of clearDependencies.

Comment thread src/index.ts Outdated
const output = instance.languageService.getEmitOutput(filePath);

loader.clearDependencies();
// loader.clearDependencies();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this commented for a reason? I think this is necessary.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I commented it out because I am a bit unsure. But if loader.clearDependencies is called any dependencies added in previous loaders in the chain will be forgotten, which would require som jumping through hoops to handle.
I may be missing something, but I don't see that it is necessary to make this call. Normally (if there are no previous loaders in the chain) there would only be one file dependency - on the ts-file being loaded. Or am I misuderstanding something?

Copy link
Copy Markdown
Author

@MortenHoustonLudvigsen MortenHoustonLudvigsen Apr 13, 2017

Choose a reason for hiding this comment

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

I think what is really wanted is not to clear dependencies, but to replace the original dependency on resourcePath with a dependency on rawFilePath.
My latest commit implements this while preserving any other existing dependencies.

.replace(/[\d]+[.][\d]* kB/g, ' A-NUMBER-OF kB')
// We also don't want a difference in the number of bytes to fail the build
.replace(/ \d+ bytes /g, ' A-NUMBER-OF bytes ')
// Sometimes "[built]" is written to output, and sometimes not. This should not fail the build
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Actually having "[built]" is significant I believe. It indicates whether a module has been recompiled as part of a run. I believe this is important for the integration tests which have multiple iterations.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Well, in the previous PR, and in the first integration test of this PR, I saw that one test failed, but only for Node 4, because [build] was not there. However the test succeeded for all other versions of Node and TypeScript.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The test in question is aliasResolution. See Job #1484.6

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This also happens sometimes in nightly builds: #1473.20

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Oh, and I made a mistake by filtering out [build] in stead of [built], but the second integration test of this PR still passed. So there must be something, unrelated to this PR, that makes webpack output [built] where it is not expected on seldom occasions, but I am at a loss as to what that something is.

Copy link
Copy Markdown
Member

@johnnyreilly johnnyreilly Apr 18, 2017

Choose a reason for hiding this comment

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

Hey! The first thing to say is that the integration tests are flaky. As it's a full integration test you do sometimes get false failures. This happens during the nightly builds. I've never looked into it in detail but generally rerunning a failing test pack will result in a green run. Anyway, [built] is significant AFAIK as it indicates whether a module has been recompiled as part of a run.

So I'd take the occasional failure here as a "something to live with". I think we need this or we may break behaviour in ts-loader in future and not realise it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Right - I'll roll back that change then.

Comment thread src/servicesHost.ts
const moduleResolutionHost = {
fileExists: (fileName: string) => utils.readFile(fileName) !== undefined,
readFile: (fileName: string) => utils.readFile(fileName),
fileExists: (fileName: string) => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks unrelated to the change being made - could you provide some info on this please?

Copy link
Copy Markdown
Author

@MortenHoustonLudvigsen MortenHoustonLudvigsen Apr 13, 2017

Choose a reason for hiding this comment

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

When a file is generated by a previous loader in the chain, it does not necessarily exist in the file system. So to make sure the TypeScript compiler can resolve the file, I look up in intance.files first. Otherwise it would not be able to resolve generated files. This should actually give a slight performance improvement, as files will only be loaded once (and of course maybe in watch-run).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Cool - could we document that in comments please? Perhaps it would be worth this code path only being executed if usePreviousLoaderGeneratedFiles is true; presumably otherwise it would not work if there weren't previous loaders in the chain?

Copy link
Copy Markdown
Author

@MortenHoustonLudvigsen MortenHoustonLudvigsen Apr 18, 2017

Choose a reason for hiding this comment

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

I'll add some comments.

However I don't think it is necessary to wrap the code with a check for usePreviousLoaderGeneratedFiles. The files object is the one already used in ts-loader to cache files. Its contents are loaded in the following places:

  • From the file system initially in getTypeScriptInstance:
const files: interfaces.TSFiles = {};
...
const filesToLoad = configParseResult.fileNames;
filesToLoad.forEach(filePath => {
	normalizedFilePath = path.normalize(filePath);
	files[normalizedFilePath] = {
		text: fs.readFileSync(normalizedFilePath, 'utf-8'),
		version: 0
	};
  });
  • In the loader itself, using updateFileInCache (I've excluded my additional calls to updateFileInCache for this discussion):
const rawFilePath = path.normalize(this.resourcePath);
const filePath = utils.appendTsSuffixIfMatch(options.appendTsSuffixTo, rawFilePath);
const fileVersion = updateFileInCache(filePath, contents, instance);
  • In watch-run.ts where file changes are registered

So it should be safe enough to load a file from files and use that, if it exists, instead of reading the file from the file system. This should even result in a slight performance improvement.

I would actually recommend updating files after reading them from the file system, and being able to have text == undefined for those files, that do not exist. This would reduce the file system access to once per file (initially - watch-run can of cause re-read any number of files).

All uses of file.text should be checked so they can handle file.text == undefined.

I am very happy to make this change - either in this PR or a new one, if you like.

There is one fly in the ointment. When I look at watch-run.ts, I see:

file.text = utils.readFile(filePath) || '';

This means that files that no longer exist are not deleted and have a valid text.

If I make the changes I recommend above I would change this to:

file.text = utils.readFile(filePath);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All seems reasonable. If existing tests pass with those changes then I don't have any objection. I'm guessing performance would not be hurt by this?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Quite the contrary :-) I'll get to these changes within the next couple of days (I am actually at my day job right now).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I have added comments to moduleResolutionHost. I have decided not to make the suggested changes to file caching though, as I think that deserves its own PR, and shouldn't delay this one.

@johnnyreilly
Copy link
Copy Markdown
Member

Hi @MortenHoustonLudvigsen,

Just wanted you to know I haven't forgotten you. It's Easter here and I'll be offline probably until Tuesday.

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

MortenHoustonLudvigsen commented Apr 14, 2017

@johnnyreilly
No worries :-) I'll probably have written a simple test by then and some documentation in Readme.md.

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

@johnnyreilly
I didn't get around to test and documentation, but I will in the next couple of days.

Comment thread src/index.ts
const output = instance.languageService.getEmitOutput(filePath);

loader.clearDependencies();
// Remove original dependency on resourcePath and replace with rawFilePath
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you provide some explanation on what is happening here? This replaces the simple loader.clearDependencies() with something that will clear dependencies and then perhaps add dependencies again. I'm not clear on what loader.resourcePath is and whether we always want to follow this path.

Some details of what this should achieve would be helpful. Also, we still have the addDependency call after removeDependencies - will this result in double adds?

Copy link
Copy Markdown
Author

@MortenHoustonLudvigsen MortenHoustonLudvigsen Apr 18, 2017

Choose a reason for hiding this comment

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

I think maybe you missed the comments on outdated changes (probably my fault, not being an experienced GitHub user). But the gist is this:

The problem with calling clearDependencies is that it clears dependencies for the entire chain, not just the current loader. So if a loader has been run before ts-loader, any dependencies it has added will be cleared (in the case of ts-css-loader this could be dependencies on .css files).

Normally, if there are no previous loaders in the chain, there would only be one file dependency: the ts-file being loaded (resourcePath).

I think what is really wanted is not to clear dependencies, but to replace the original dependency on resourcePath with a dependency on rawFilePath, which is defined like so:

const rawFilePath = path.normalize(this.resourcePath);

That's why I replaced clearDependencies with removeDependencies and addDependency.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Of course, I should check if rawFilePath === this.resourcePath, and if so skip this step entirely.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

To be honest I think the GitHub UI is making things more confusing than I would hope 😄

I'm still a little confused and at least part of that is down to my incomplete knowledge of the webpack API. (Just for history, ts-loader was originally written by @jbrantly and I'm the main caretaker at present.) I'll lay out my confusion and you can set me straight.

As I read it, removeDependencies does the following:

  • it gathers up existing contextDependencies and dependencies from webpack.
  • clears dependencies
  • re-adds the previously gathered dependencies unless they are the resourcePath - could you clarify what the intent of this is please? I can see what's happening but I'm not so clear as to what you want to not be added as a dependency and what you do.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

See my comment in the changes tab.

Copy link
Copy Markdown
Author

@MortenHoustonLudvigsen MortenHoustonLudvigsen Apr 18, 2017

Choose a reason for hiding this comment

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

Well my understanding is that the goal of the original call to clearDependencies is to replace the dependency on resourcePath with rawFilePath, because it might be different.

To understand what is going on, I have looked in webpack/loader-runner where dependencies for loaders are handled, and f.ex. addDependency and clearDependencies are implemented.

It turns out that there is no method that will remove individual dependencies. The only method that actually removes dependencies is clearDependencies.

There is a method getDependencies that returns file dependencies, but it returns a copy of the internal dependency array, so any changes to will have no effect. The method getContextDependencies works in the same way.

So, if I want to replace a dependency, I have to get the existing dependencies, call clearDependencies, add all the dependencies except the one I want to replace, and then add the new dependency.

It turns out that clearDependencies clears file and context dependencies, so I have to do the same for context dependencies.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

NB. I have just checked the code in webpack/loader-runner again, and my assumption that, if ts-loader is the only loader, resourcePath will be the only dependency, is correct.
So the only reason, I can think of, for the original call to clearDependencies is to replace resourcePath with the same path, but normalized.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK cool that makes sense. So given we weren't preserving dependencies / contextDependencies in our original code it wasn't an issue because we would only be dealing with a single file in that context. But this is not true in the world where css-ts-loader is chained before ts-loader. Is that correct?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Exactly!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I wonder whether replacing the dependency on resourcePath is really necessary. Even if it isn't normalized it should still trigger a new webpack build if the file is changed. Otherwise webpack would have problems with other loaders. The only place I can think of where it would be an issue is in watch-run.ts, but it already normalizes the paths of changed files.

Comment thread src/index.ts

/**
* Remove dependencies specified by argument exclude.
*/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm basically happy with this - I'd just like to do some variable renames to improve clarity. Please could

  • dependencies become dependenciesToPreserve
  • contextDependencies become contextDependenciesToPreserve

Bit of a mouthful but it makes intent obvious

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done

Comment thread src/index.ts
function removeDependencies(loader: interfaces.Webpack, exclude: (filePath: string) => boolean): void {
const dependencies = loader.getDependencies();
const contextDependencies = loader.getContextDependencies();
loader.clearDependencies();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could filePath be renamed to something so people don't mix it up with the filePath in the method signature for exclude please?

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

Hi @johnnyreilly,
Just wanted to let you know I haven't forgotten this, I should have time this weekend 😄

@johnnyreilly
Copy link
Copy Markdown
Member

No worries!

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

I'm so sorry I haven't got back to this till now. My day job got in the way 😄
I will be putting time into this today, and this weekend. Hopefully this PR will be ready for the real world.

Comment thread src/index.ts
function removeDependencies(loader: interfaces.Webpack, exclude: (filePath: string) => boolean): void {
const dependenciesToPreserve = loader.getDependencies();
const contextDependenciesToPreserve = loader.getContextDependencies();
loader.clearDependencies();
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Identifier filePath has become dependency.

@grantila
Copy link
Copy Markdown

You're right @johnnyreilly this could be a solution to #506.

To me, something like usePreviousLoaderGeneratedFiles goes against the philosophy in webpack, as this (if I'm not mistaken) should be inferred by there being a loader "after" this one (thereby running before). One simply shouldn't have to tell a loader that there has been another loader before it, or am I missing the purpose of this flag, in that extra data needs to be passed? If so, could TypeScript-aware loaders pass this data without this flag being necessary?

Also, will this PR allow a .ts file to import another .ts file without manually reading it if there's a loader already doing this? Such as loader: 'ts-loader!webpack-append' (see https://github.com/dumconstantin/webpack-append)?

@johnnyreilly
Copy link
Copy Markdown
Member

Hey @MortenHoustonLudvigsen - would you be able to respond to @grantila please? Just want to ensure we've missed nothing relevant.. thanks!

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

MortenHoustonLudvigsen commented May 29, 2017

Right, first of all, I agree that ts-loader does go against the webpack philosophy by reading files directly from the file system, instead of using the sources provided by webpack exclusively.

However, I don't think that this is easy to change without doing a major rewrite of ts-loader:

  • The typescript compiler needs to reference files, other than the one being loaded, for type-checking (except if it is in transpileOnly mode, of course). One could use loaderContext.loadModule for this.

  • The typescript compiler is inherently synchronous, whereas most operations in webpack (in particular loaderContext.loadModule) are asynchronous. So when the compiler tries to resolve a file which is not the one being loaded, it does so synchronously, which would be difficult for ts-loader to provide by loading the file from webpack.

  • ts-loader would need a mechanism to load files as they are immediately before they are loaded by ts-loader.

If we could get ts-loader to function like that this PR would be redundant! But reality exists, and for now this is how I have been able to implement custom typings. I would, however, be very open to participating in trying to do the rewrite!

With this in mind I still think this PR is relevant.

BTW. I have ts-css-loader and ts-json-loader ready to go, as soon as this PR is accepted 😄

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

Oh, and btw: I agree that the option usePreviousLoaderGeneratedFiles can be inferred by checking if data['ts-loader-files'] exists!

@johnnyreilly
Copy link
Copy Markdown
Member

The typescript compiler needs to reference files, other than the one being loaded, for type-checking (except if it is in transpileOnly mode, of course).

I've actually recently been using this approach with https://github.com/Realytics/fork-ts-checker-webpack-plugin to do type checking. It's faster!

I agree that the option usePreviousLoaderGeneratedFiles can be inferred by checking if data['ts-loader-files'] exists!

Should we do this instead? If there's no performance penalty then it seems reasonable

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

I've actually recently been using this approach with https://github.com/Realytics/fork-ts-checker-webpack-plugin to do type checking. It's faster!

I haven't looked at this package, but does it also read from disk or will it read from webpack modules? For transforms performed pre-ts-loader (f.ex. webpack-append) it would need to do this.

I agree that the option usePreviousLoaderGeneratedFiles can be inferred by checking if data['ts-loader-files'] exists!

Should we do this instead? If there's no performance penalty then it seems reasonable

I'm happy to make the usePreviousLoaderGeneratedFiles option inferred! I'll get right on it 😄

@johnnyreilly
Copy link
Copy Markdown
Member

I haven't looked at this package, but does it also read from disk or will it read from webpack modules?

I don't actually know - @piotr-oles may be able to confirm...

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

Option usePreviousLoaderGeneratedFiles is now inferred. I've removed the documentation for the option as well, but should I write a section at the end?

@johnnyreilly
Copy link
Copy Markdown
Member

I would yes. The build is now failing though :-(

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

MortenHoustonLudvigsen commented May 29, 2017

Could you try running Job #1598.15 again?
Test appendSuffixToWatch is failing with [built] in one environment:

      -    [0] ./.test/appendSuffixToWatch/component.vue A-NUMBER-OF bytes {0} [built]
      -    [2] ./.test/appendSuffixToWatch/entry2.ts A-NUMBER-OF bytes {0} [built]
      +    [0] ./.test/appendSuffixToWatch/component.vue A-NUMBER-OF bytes {0}
      +    [2] ./.test/appendSuffixToWatch/entry2.ts A-NUMBER-OF bytes {0}

@johnnyreilly
Copy link
Copy Markdown
Member

Done. Question: is usePreviousLoaderGeneratedFiles something that can be inferred once and the value stored for reuse with each subsequent run? I figure that would allow better performance on subsequent runs. This might be micro-optimisation territory...

@grantila
Copy link
Copy Markdown

Great work @MortenHoustonLudvigsen, you're right about how large a rewrite would be, so this is a good approach that will do for quite a while.

@johnnyreilly Yeah, that's a micro-optimization - checking a bool or !!data['ts-loader-files'] will be practically identical performance as a whole (compiling will be much slower). And the difference pragmatically would be for this loader to be more inline with webpack per se, which is really important.

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

MortenHoustonLudvigsen commented May 29, 2017

Done. Question: is usePreviousLoaderGeneratedFiles something that can be inferred once and the value stored for reuse with each subsequent run? I figure that would allow better performance on subsequent runs. This might be micro-optimisation territory...

Right now I infer usePreviousLoaderGeneratedFiles by checking whether data['ts-loader-files'] is set and has any entries. This will depend on the file being loaded, so no, I don't think that is possible - at least not the way I have implemented it now. If I change it to not check for entries, then yes. But I'm not sure which option is better!

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

BTW. ts-css-loader and ts-json-loader both do caching, so typings for a css og json will be generated only once.

@johnnyreilly
Copy link
Copy Markdown
Member

johnnyreilly commented May 29, 2017

@grantila - cool. Could you just elaborate on this please?

will be practically identical performance as a whole (compiling will be much slower). And the difference pragmatically would be for this loader to be more inline with webpack per se, which is really important.

I didn't quite follow the point about compiling speed. The compiling will be much slower comment raised alarm bells. I don't want to increase compiling speed at all and I wasn't clear what you thought would make it slower. Either way I wish to avoid that!

Also your "inline with webpack point".. (ie is it your view that caching the value more or less inline with webpack).

Given what @MortenHoustonLudvigsen has said it doesn't sound like caching the value is a valid approach anyway but I wanted to be clear I fully had your meaning on the other points.

@grantila
Copy link
Copy Markdown

@johnnyreilly No I just meant "property access optimizations" is going to be far less important than the compiling from TypeScript to JavaScript per se. That will still be 95%+ of the time of ts-loader. Same for caching of files - the OS handles this for us. Caching of pre-compiled files is different though, naturally.

Regarding "inline with webpack", I meant that loaders should try to be as similar in philosophy as possible. That means, having defaults so that most users need no extra config, and respecting pre-loaders to provide the file (rather than reading from disk). Requiring an option for ts-loader to allow pre-loaders would go against this IMO.

As of now, it's impossible to let a loader prepend ts-loader and generate TypeScript. I think this PR will mostly solve that.

@johnnyreilly
Copy link
Copy Markdown
Member

Great - thanks for the clarification!

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

Hey @johnnyreilly
I've just submitted some documentation, and changed test usePreviousLoaderGeneratedFiles to match.

@johnnyreilly
Copy link
Copy Markdown
Member

I saw - thanks. And I'm sorry it's taking so long to get this reviewed BTW. Life is pretty busy right now...

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

No worries! 😄

@MortenHoustonLudvigsen
Copy link
Copy Markdown
Author

MortenHoustonLudvigsen commented Jun 2, 2017

@johnnyreilly
I hate to say it after all my work, but if #552 turns out to be viable, this PR should be redundant. So I think we should hold off on merging this PR until then.

@johnnyreilly
Copy link
Copy Markdown
Member

Great - thanks for letting me know. I'll hold off for now. Better to do things right than having to back them out later.

@johnnyreilly
Copy link
Copy Markdown
Member

Closing as inactive

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.

3 participants