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

Unable to resolve TS modules with a .js import path extension if lang="ts" is missing #887

Closed
AdrianGonz97 opened this issue Apr 18, 2024 · 5 comments
Labels
bug Something isn't working vite

Comments

@AdrianGonz97
Copy link
Member

AdrianGonz97 commented Apr 18, 2024

Describe the bug

Given a TS module, foo.ts, we can import this module into a svelte component like so:

<!-- src/lib/TSComponent.svelte -->
<script lang="ts">
	import { foo } from "./foo.js";
	// ...
</script>

However, if we were to remove the lang="ts" attribute from the script tag:

<!-- src/lib/JSComponent.svelte -->
<script>
	import { foo } from "./foo.js"; 
	// ...
</script>

the module will now fail to load, throwing the following error:

[vite] Internal server error: Failed to resolve import "./foo.js" from "src/lib/JSComponent.svelte". Does the file exist?

...which is a bit unexpected.

If we were to replace the extension for a .ts extension instead, the module loads fine:

<!-- src/lib/JSComponent.svelte -->
<script>
	import { foo } from "./foo.ts"; 
	// ...
</script>

...which is also unexpected, especially when allowImportingTsExtensions is not enabled in the tsconfig.json, causing the LSP to error.


This bug was a bit baffling to figure out at first. The warning wasn't particularly helpful in indicating that I was missing the lang="ts" attribute either. Either way, this doesn't seem like it's the expected behavior. However, I am unsure if this is directly a Vite issue or a vite-plugin-svelte issue.

Reproduction URL

https://github.com/AdrianGonz97/broken-js-import-paths-repro

Reproduction

  1. git clone https://github.com/AdrianGonz97/broken-js-import-paths-repro
  2. pnpm install
  3. pnpm dev
  4. Open the browser and navigate to the page
  5. In the editor, go to src/lib/JSComponent.svelte to see the issue

Logs

4:18:00 PM [vite] Pre-transform error: Failed to resolve import "./foo.js" from "src/lib/JSComponent.svelte". Does the file exist?
4:18:01 PM [vite] Internal server error: Failed to resolve import "./foo.js" from "src/lib/JSComponent.svelte". Does the file exist?
  Plugin: vite:import-analysis
  File: /home/koala/Reproductions/svelte-vite/src/lib/JSComponent.svelte:4:21
  16 |  
  17 |  // this import causes the app to break because of the `.js` extension
  18 |  import { foo } from "./foo.js";
     |                       ^
  19 |  
  20 |  const file = "src/lib/JSComponent.svelte";
      at formatError (file:///home/koala/Reproductions/svelte-vite/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-_QLjGPdL.js:50877:46)
      at TransformContext.error (file:///home/koala/Reproductions/svelte-vite/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-_QLjGPdL.js:50871:19)
      at normalizeUrl (file:///home/koala/Reproductions/svelte-vite/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-_QLjGPdL.js:66110:33)
      at async file:///home/koala/Reproductions/svelte-vite/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-_QLjGPdL.js:66265:47
      at async Promise.all (index 2)
      at async TransformContext.transform (file:///home/koala/Reproductions/svelte-vite/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-_QLjGPdL.js:66186:13)
      at async Object.transform (file:///home/koala/Reproductions/svelte-vite/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-_QLjGPdL.js:51186:30)
      at async loadAndTransform (file:///home/koala/Reproductions/svelte-vite/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-_QLjGPdL.js:53941:29)
      at async viteTransformMiddleware (file:///home/koala/Reproductions/svelte-vite/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-_QLjGPdL.js:63793:32)

System Info

System:
    OS: Linux 5.15 Ubuntu 20.04.6 LTS (Focal Fossa)
    CPU: (24) x64 AMD Ryzen 9 5900X 12-Core Processor
    Memory: 18.73 GB / 31.30 GB
    Container: Yes
    Shell: 5.8 - /usr/bin/zsh
  Binaries:
    Node: 20.12.1 - ~/.volta/tools/image/node/20.12.1/bin/node
    Yarn: 1.22.21 - ~/.volta/tools/image/yarn/1.22.21/bin/yarn
    npm: 10.5.0 - ~/.volta/tools/image/node/20.12.1/bin/npm
    pnpm: 8.15.1 - ~/.volta/bin/pnpm
    bun: 1.1.3 - ~/.bun/bin/bun
  npmPackages:
    @sveltejs/vite-plugin-svelte: ^3.0.2 => 3.1.0 
    svelte: ^4.2.12 => 4.2.15 
    vite: ^5.2.0 => 5.2.9
@AdrianGonz97 AdrianGonz97 added bug Something isn't working triage Awaiting triage by a project member labels Apr 18, 2024
@dominikg
Copy link
Member

i don't think this is a bug, the file is actually has a .ts extension, not .js. So importing foo.js only works because of typescript. If you remove lang=ts, it is no longer typescript, so the error is correct, foo.js does not exist. Resolving does not try foo.ts without lang=ts.

If you import it as foo.ts, vites ts transform works as expected.

Not sure if there is a way to make the error message more descriptive, in my opinion it already is.

@AdrianGonz97
Copy link
Member Author

AdrianGonz97 commented Apr 21, 2024

thanks for checking out the issue!

i don't think this is a bug, the file is actually has a .ts extension, not .js. So importing foo.js only works because of typescript. If you remove lang=ts, it is no longer typescript, so the error is correct, foo.js does not exist.

i dont think this is correct, especially when allowJs is enabled in the tsconfig. AFAIK, typescript does not transform import paths during compilation (unless allowImportingTsExtensions is enabled), making this not the expected result. here's a simple demo using tsc where it's working as expected: https://stackblitz.com/edit/stackblitz-starters-togwkq?file=index.js

Not sure if there is a way to make the error message more descriptive, in my opinion it already is.

I completely disagree. Just to check my own sanity, I made a repro and showed it to several people (all of whom are very experienced with TS and Svelte) and none of them were able to find the fix in a reasonable amount of time. i even guided them to inspect the error to see if that would help them solve it. it did not - so it's certainly not descriptive enough on it's own.

however, i think it's becoming more clear that this is more of a Vite issue than a vite-plugin-svelte specific issue when testing this in normal js/ts modules outside of the svelte components (e.g. bar.js importing foo.ts with a .js extension fails to resolve). I'll look to see if an issue has already been raised over there

@bluwy
Copy link
Member

bluwy commented Apr 22, 2024

Thanks for the repro. This seems like a bug in Vite (vitejs/vite#8993) as Svelte only compiles to JS, and the import paths are later resolved by Vite.

Frankly though, you should use "moduleResolution": "bundler" in your tsconfig.json so it better matches bundler resolving behaviors, which sort-of made the linked Vite issue lower priority now.

I'll close this for now as it's an upstream issue.

@bluwy bluwy closed this as not planned Won't fix, can't repro, duplicate, stale Apr 22, 2024
@dominikg dominikg added vite and removed triage Awaiting triage by a project member labels Apr 22, 2024
@AdrianGonz97
Copy link
Member Author

thanks @bluwy, I appreciate the insight!

Frankly though, you should use "moduleResolution": "bundler" in your tsconfig.json so it better matches bundler resolving behaviors, which sort-of made the linked Vite issue lower priority now.

Unfortunately, this sort of conflicts with the recommended setup for creating svelte libraries, which is to use "moduleResolution": "nodenext" for libraries (it's also used in the default library template for create-svelte), which is how we originally fell into this conundrum 😄

@bluwy
Copy link
Member

bluwy commented Apr 23, 2024

Ah true. I forgot about that. I suppose when it comes down to using the right moduleResolution, it depends on what environment your library is meant to be used it. If it's plain JS with no Svelte components, nodenext is correct. If it involves Svelte components so the only way to work is to bundle your library, then bundler is correct.

So presumably it should be safe for you to change to bundler, but I'm not sure if there will be other issues with svelte-package. SvelteKit has some issues about it: https://github.com/search?q=repo%3Asveltejs%2Fkit+moduleresolution+svelte-package&type=issues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working vite
Projects
None yet
Development

No branches or pull requests

3 participants