Skip to content
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

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

Closed
vidal7 opened this issue Aug 31, 2023 · 31 comments
Closed

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

vidal7 opened this issue Aug 31, 2023 · 31 comments
Labels
bug Something isn't working good reproduction ✨ This issue provides a good reproduction, we will be able to investigate it first

Comments

@vidal7
Copy link

vidal7 commented Aug 31, 2023

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

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.

@so1ve
Copy link
Member

so1ve commented Aug 31, 2023

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

@so1ve so1ve added the question Further information is requested label Aug 31, 2023
@vidal7
Copy link
Author

vidal7 commented Aug 31, 2023

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?

@so1ve
Copy link
Member

so1ve commented Aug 31, 2023

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

@so1ve so1ve added bug Something isn't working good reproduction ✨ This issue provides a good reproduction, we will be able to investigate it first and removed question Further information is requested labels Aug 31, 2023
@vidal7
Copy link
Author

vidal7 commented Sep 1, 2023

@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
Copy link
Author

vidal7 commented Sep 1, 2023

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
Copy link
Author

vidal7 commented Sep 1, 2023

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 vidal7 changed the title TypeScript Project References is not working when separating tests from a vue implementation file [Performance]: TypeScript Project References is not working when separating tests from a vue implementation file Sep 7, 2023
@vidal7 vidal7 changed the title [Performance]: TypeScript Project References is not working when separating tests from a vue implementation file [Performance]: .vue.d.ts are not used in TypeScript Project References Oct 13, 2023
@vidal7
Copy link
Author

vidal7 commented Oct 13, 2023

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
Copy link
Author

vidal7 commented Apr 8, 2024

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
Copy link
Author

vidal7 commented Apr 8, 2024

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'.

@DavidR95
Copy link

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").

@vidal7
Copy link
Author

vidal7 commented Jun 20, 2024

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?

@DavidR95
Copy link

@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 :/

@vidal7
Copy link
Author

vidal7 commented Jun 21, 2024

@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
Copy link
Author

vidal7 commented Jun 21, 2024

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

@gtbuchanan
Copy link

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

@vidal7
Copy link
Author

vidal7 commented Jul 2, 2024

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

@vidal7
Copy link
Author

vidal7 commented Jul 2, 2024

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.

@gtbuchanan
Copy link

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.

@johnsoncodehk
Copy link
Member

Sorry it took so long, the problem should now be resolved by volarjs/volar.js#222.

@vidal7
Copy link
Author

vidal7 commented Jul 4, 2024

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

@vidal7
Copy link
Author

vidal7 commented Jul 4, 2024

For your info, volarjs/volar.js#222 landed in vuejs/language-tools@2.0.26.

@gtbuchanan
Copy link

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

@vidal7
Copy link
Author

vidal7 commented Jul 29, 2024

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
Copy link
Author

vidal7 commented Jul 30, 2024

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.

@codethief
Copy link

codethief commented Aug 5, 2024

@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.

@vidal7
Copy link
Author

vidal7 commented Aug 6, 2024

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.

@codethief
Copy link

@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
Copy link

@johnsoncodehk Would you mind re-opening this ticket?

@codethief
Copy link

codethief commented Aug 12, 2024

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). ✔️
    • 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. ❌
  • 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
Copy link

codethief commented Aug 21, 2024

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.

@vidal7
Copy link
Author

vidal7 commented Aug 21, 2024

Thank you @codethief for creating the new issue. For now, the thing I did for working around the issue was creating two different typescript settings. One for VSCode with extraneous included vue files and one for vue-tsc without extraneous included vue files.

But I am agree that we should not have different typescript settings. Maybe when your issue will be fixed, without extraneous included vue, we can gain some performance in VSCode but it is more a hypothesis that still to be proven.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good reproduction ✨ This issue provides a good reproduction, we will be able to investigate it first
Projects
None yet
Development

No branches or pull requests

6 participants