language-tools icon indicating copy to clipboard operation
language-tools copied to clipboard

[Performance]: .vue.d.ts are not used in TypeScript Project References

Open vidal7 opened this issue 1 year ago • 9 comments

Hello.

What I want to do

I want to better organize my codebase. So I began to introduce TypeScript Project References to help cope with performance problems in vscode and also separating tests from implementation thus it was not possible for the implementation files to import the test files. I was inspired by the official TypeScript Project References documentation on https://www.typescriptlang.org/docs/handbook/project-references.html#an-example-project.

What is my problem

However, I keep getting this TypeScript error in vscode and vue-tsc

vue/main.unit.ts:1:18 - error TS6307: File 'vue/main.vue.ts' is not listed within the file list of project 'vue/tsconfig.unit.json'. Projects must list all files or use an 'include' pattern.
  The file is in the program because:
    Imported via './main.vue' from file 'vue/main.unit.ts'
    Imported via './main.vue' from file 'vue/main.vue.ts'

1 import Main from './main.vue';
                   ~~~~~~~~~~~~

  vue/main.vue.ts:42:45
    42 let __VLS_internalComponent!: typeof import('./main.vue')['default'];
                                                   ~~~~~~~~~~~~
    File is included via import here.


Found 1 error.

image

What I expect to get No errors in vscode, npm script build:vue is working the same way as build:ts

To reproduce

  • Clone https://github.com/vidal7/volar-issue-project-references
  • npm install
  • npm run build:ts => works
  • npm run build:vue => doesn't work

Details before reproducing

  • build:ts is building a test files project that is referring to a implementation project that contains only a ts file and it works
  • build:vue is building a tests files project that is referring to a implementation project that contains only a vue file and it doesn't work.

Is this a bug? Am I missing something?

Thank you.

vidal7 avatar Aug 31 '23 12:08 vidal7

Add *.vue to the include pattern in your tsconfig.unit.json file

so1ve avatar Aug 31 '23 13:08 so1ve

Add *.vue to the include pattern in your tsconfig.unit.json file

It works but I don't think it is an acceptable solution. My understanding is that it defeats the purpose of separating tests from implementation. Your solution merge the test files with the implementation thus implementation can now depends on test files.

Am I right or I am missing something? Also, why I don't have to do it with ts/tsconfig.unit.json that build:ts is using?

vidal7 avatar Aug 31 '23 14:08 vidal7

Ugh! Thanks for your clarification. This is likely a bug in volar.

so1ve avatar Aug 31 '23 14:08 so1ve

@so1ve, I tried the official vue scaffolding npm create vue@latest with typescript, vitest options and they are using your solution too... But I can't wrap my head around the following question :

Why I don't have to do it with ts/tsconfig.unit.json that build:ts is using? build:ts is not building any vue files with vue-tsc and I don't have to include any implementation files in the tsconfig include option just refer them with the references tsconfig option.

vidal7 avatar Sep 01 '23 11:09 vidal7

Continuing my investigation, with your solution that seems to works, I am afraid that there is a performance hit. Here is the out dir content

npm run build:ts image

npm run build:vue image

So far so good, every files get compiled in .d.ts files correctly.

Here's the interesting part. If you look closely inside the *.tsbuildinfo files and in the fileNames field, here's what we have. I intentionnaly cut down the list with a value of '...' for brevity.

ts-out/tsconfig.src.tsbuildinfo image

ts-out/tsconfig.unit.tsbuildinfo image

vue-out/tsconfig.src.tsbuildinfo image

vue-out/tsconfig.unit.tsbuildinfo image

My conclusion, TypeScript project ts-out/tsconfig.unit.json is using main.d.ts and TypeScript project vue-out/tsconfig.unit.json is using main.vue.ts and not main.vue.d.ts. So I am afraid that there is a performance hit.

vidal7 avatar Sep 01 '23 12:09 vidal7

To prove that there is a performance hit, I did something silly but funny with only `tsc'

If you checkout the performance-test branch, I found that build:performant has always 25% less build time than build:non-performant

So I think vue-tsc / volar should do the same thing as tsc since using *.vue.d.ts files in a project instead of using *.vue files will boost the performance.

vidal7 avatar Sep 01 '23 17:09 vidal7

Also, if you use the cli option --dry, the .vue.d.ts files are not removed enforcing the idea that these files are generated but not used by referencing projects.

vidal7 avatar Oct 13 '23 14:10 vidal7

Update when trying version 2.0.11 with typescript version 5.1.6. Error messages in the console has dissapeared but build:vue doesn't seem to do anything at all. There is no vue-out directory created.

vidal7 avatar Apr 08 '24 11:04 vidal7

Update when trying version 2.0.11 with typescript version 5.4.4, there is now a error message in the console.

vue/main.unit.ts(1,18): error TS6305: Output file './vue-out/main.vue' has not been built from source file './vue/main.vue'.

vidal7 avatar Apr 08 '24 11:04 vidal7

Did you find any way around this @vidal7? I'm getting the same error as you ("Output file has not been built from source file").

DavidR95 avatar Jun 20 '24 15:06 DavidR95

Did you find any way around this @vidal7? I'm getting the same error as you ("Output file has not been built from source file").

Not yet. I am still including vue files in the include part of my typescript projects and doing so it compiles many time the same .vue files making compile time very long :( I am still on Vue@2 and also, I am still on Volar 1.8.27 because vue-tsc@2.* doesn't seem to work at all with typescript projects at least with Vue@2

@DavidR95, what version of volar, vue-tsc and Vue are you using?

vidal7 avatar Jun 20 '24 18:06 vidal7

@vidal7 Version 3.3.2 of Vue, and 2.0.21 of vue-tsc.

All pure TS files work fine (i.e., don't generate the error mentioned above), seems to just be Vue files. If I hack around with the paths in the TS config to make my aliases point to the outDir directory, it does work as expected. Not that I really understand what that suggests in terms of the underlying issue, nor where the actual problem lies 😄

The workaround of includeing the Vue files in all relevant projects feels infeasible for us as we have many refering projects so type errors within the Vue files are reported multiple times in the CLI which feels... weird (and compiled multiple times, like you say).

As such, I've abandoned project references for now :/

DavidR95 avatar Jun 21 '24 13:06 DavidR95

@DavidR95 , thanks you for giving me the idea of hacking around the aliases to the outDir directory. It might helps me to boost the performance of compiling my monorepo of 16 ts projects and 1500 SFC components.

Project references are very useful to us because it guides the developers of our team by forbiding certains imports in certain typescript project. In other words, this implements what projects can import and cannot import. Unfortunately, it comes at a great performance cost. Like you said, if it was just ts files, all will be fine but with vue files and vue-tsc, there is a performance cost of compiling many times the same vue file.

vidal7 avatar Jun 21 '24 14:06 vidal7

Finally, hacking my way around aliases was more challenging that I tought because we use aliased imports and also relative imports. To make it works, I have to change all my relative imports with aliased imports and it will be too much of a burden to do.

So this issue is still revelant to the following reasons :

  • Fix the performance problem by not compiling many time the same vue files
  • Be more consistant with the native tsc compiler by reusing already .d.vue compiled files
  • Doesn't need to hack your way through changing paths of aliases causing those two side effects
    • VSCode do navigate to the .d.vue when ctrl-clicking to definition instead of .vue
    • Changing all the relative imports to aliased imports

vidal7 avatar Jun 21 '24 17:06 vidal7

I'm also getting the Output file has not been built from source file error when building project references containing vue files. I switched to project references after encountering this issue. I noticed my vue files weren't being type-checked so I added them to my tsconfig.json along with declaration: true and emitDeclarationOnly: true and ran vue-tsc -b. That's when I started encountering the error.

package version
vue 3.4.31
vue-tsc 2.0.24
typescript 5.5.3

gtbuchanan avatar Jul 02 '24 16:07 gtbuchanan

So @gtbuchanan, you are confirming me that it doesn't works in the latest versions of vue, vue-tsc and typescript.

vidal7 avatar Jul 02 '24 18:07 vidal7

With big monorepos vue files, is it frustating that there is a major performance hit. The situation for now is simply that monorepos with vue files can't scale. In my opinion, this is a very big drawback of adopting Vue in monorepos. How guys do you cope with that?

In my opinion, this issue should be prioritized. @johnsoncodehk, is that something planned? It seems that it was planned in the 2.0 backlogs but later dropped. Since that, it seems that there is nothing.

vidal7 avatar Jul 02 '24 18:07 vidal7

I've started adding // @ts-expect-error vue-tsc bug above every vue file import to ignore the error. This seems to preserve type-checking in the file so, though painful, it's a workaround for now. Unfortunately, Volar doesn't appear to detect the error in VS Code and reports that ts-expect-error is unnecessary.

gtbuchanan avatar Jul 03 '24 15:07 gtbuchanan

Sorry it took so long, the problem should now be resolved by https://github.com/volarjs/volar.js/pull/222.

johnsoncodehk avatar Jul 04 '24 06:07 johnsoncodehk

No problem @johnsoncodehk, I know you are working super hard. Thank you. Can't wait to test the new version.

vidal7 avatar Jul 04 '24 11:07 vidal7

For your info, https://github.com/volarjs/volar.js/pull/222 landed in vuejs/[email protected].

vidal7 avatar Jul 04 '24 14:07 vidal7

I just confirmed the new version of vue-tsc (2.0.26) resolved my issue. Thank you!

gtbuchanan avatar Jul 08 '24 16:07 gtbuchanan

I can confirm that vue-tsc (2.0.29) is resolving this issue and there is no more performance hit.

Big vue monorepos can now scale! Thank you.

Compile time vue-tsc 1.8.27 : 12m22s vue-tsc 2.0.29 : 4m6s

67% reduction time! Thank you so much.

vidal7 avatar Jul 29 '24 20:07 vidal7

When removing extraneous included vue files in tsconfig.json that is refering a project reference, it works with vue-tsc but there is still an error in vscode with the following message : Cannot find module '***.vue' or its corresponding type declarations. ts-plugin(2307) @johnsoncodehk, is this something you are aware of? BTW, hybrid mode is on but I don't get the error when hybrid mode is off only in vue files. I still get the error on ts files even if hybrid mode is off.

vidal7 avatar Jul 30 '24 17:07 vidal7

@vidal7 For reproducibility's sake, I believe I see the same error in my example project, where I have tsconfig.vitest.json reference tsconfig.app.json instead of includeing app source files:

npm run type-check says everything is ok but VSCode with Vue extension v2.0.28 reports an error in HelloWorld.spec.ts:

image

Meanwhile, before upgrading the extension from version 2.0.26 to 2.0.28, it reported:

image

EDIT: It seems (with Vue extension v2.0.28) the error message actually seems to alternate a bit between the two messages from the screenshots. In my real-life project (not the playground I linked above) I sometimes see one, sometimes the other, depending on whether the import is relative or absolute (using a path alias set in tsconfig.json). Not sure what's going on there.

codethief avatar Aug 05 '24 14:08 codethief

Thank you @codethief, I believe that if a error is not reported with vue-tsc, it should also be not reported in vscode and vice-verca. In other words, consistency between vue-tsc and vscode should be enforce like normal typescript compiler tsc is doing. I believe also that vue-tsc and tsc should behave the same. I am wondering if we should reopen this issue or open another.

For now, my temporarily fix is to create two typescript configs : one for vscode with extraneous included vue files and one for vue-tsc without extraneous includes vue files.

vidal7 avatar Aug 06 '24 13:08 vidal7

@vidal7

I believe that if a error is not reported with vue-tsc, it should also be not reported in vscode and vice-verca. […] I believe also that vue-tsc and tsc should behave the same.

I fully agree!

I am wondering if we should reopen this issue or open another.

I don't think I'm the right person to decide this but to me it sounds like the "fix" for the original issue was not an actual fix but just ended up replacing one error message with another. So I'd vote for re-opening the ticket.

codethief avatar Aug 07 '24 13:08 codethief

@johnsoncodehk Would you mind re-opening this ticket?

codethief avatar Aug 12 '24 21:08 codethief

I just ran into another interesting case in my real-life project where it's the other way around (somewhat):

  • The VSCode extension does not complain about the import as long as the import path is absolute (using a path alias defined in my tsconfig). :heavy_check_mark:
    • On the other hand, it does complain about the import (and type errors where the imported variables are being used) as soon as I use a relative path. :x:
  • The CLI (vue-tsc) never complains about the import itself (no matter whether the path is absolute or relative) but always complains about type issues where the imported variables are being used. (Likely because it assumes the variables are of type any.)

EDIT: Please ignore this comment, I just realized my project was still on vue-tsc 2.0.7. Now that I've upgraded to vue-tsc 2.0.29, the CLI works as expected (just like in my example project). VSCode still complains about the imports, though.

codethief avatar Aug 12 '24 21:08 codethief

I have decided to create a new ticket, partially to raise awareness but also because I've come to think the issue we started discussing here might be different from the original issue #3526 (even though it's certainly related) since it only shows up in the IDE, not on the command line (see my edited previous comment). So let's continue this discussion in the new ticket.

codethief avatar Aug 21 '24 15:08 codethief