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

Importing file without filename extension, with filename prefix which matches other file, fails #118

Closed
rsms opened this issue May 17, 2020 · 4 comments

Comments

@rsms
Copy link

rsms commented May 17, 2020

Repro

  • Create files main.ts, foo.bar.ts and foo.bar (see below)
  • esbuild --bundle main.ts

Expected:

  • esbuild to select foo.bar.ts and ignore the foo.bar file

Actual:

$ esbuild --bundle  main.ts
main.ts:1:15: error: File extension not supported: /Users/rsms/esbuild/foo.bar
import hi from "./foo.bar"
               ~~~~~~~~~~~
1 error

Notes

This can be worked around by import “./foo.bar.ts”, however if you run TypeScript’s tsc for type checking, it will complain with an error:

main.ts:1:15 - error TS2691: An import path cannot end with a '.ts' extension.
Consider importing './foo.bar' instead.

1 import "./foo.bar"
         ~~~~~~~~~~~

File listing

  • main.ts: import "./foo.bar"
  • foo.bar.ts: export default 1
  • foo.bar: (empty; contents doesn’t matter)

Versions

  • esbuild 0.3.3
  • macOS 10.14.6
  • TypeScript 3.9.2 (for the tsc error message in “Notes” section)
@evanw
Copy link
Owner

evanw commented May 17, 2020

I've been trying to make sure esbuild follows the node module resolution algorithm for compatibility, so I look to what node does to resolve questions like these. If I create the following files:

// foo.bar
console.log('in foo.bar')

// foo.bar.js
console.log('in foo.bar.js')

// main.js
const hi = require('./foo.bar')

and then run node main.js, it prints in foo.bar not in foo.bar.js. I believe this is because the LOAD_AS_FILE function in node's module resolution algorithm prefers an exact match over a match with implicit extensions. I'm trying to have esbuild match this algorithm, so esbuild behaves the same way.

I also tried webpack to see what it does in this case. I used your original example with .ts files instead of .js files:

// foo.bar
console.log('in foo.bar')

// foo.bar.ts
console.log('in foo.bar.ts')

// main.ts
import hi from './foo.bar'

I ran webpack with webpack main.ts. It also generates a bundle that prints in foo.bar instead of in foo.bar.ts.

So I'm not convinced that what you expected esbuild to do (ignore foo.bar and load foo.bar.ts) is the right thing to do. Can you say more about your use case? What are you trying to do? What are the contents of foo.bar and foo.bar.ts?

@rsms
Copy link
Author

rsms commented May 18, 2020

Oh, very interesting.
My use case is that I have some .glsl files mixed in with my .ts files. The .glsl files are preprocessed into .ts files with export default “contents of glsl file” to be used when building the bundle.

I agree that it would be a good idea to stick with the behavior of existing stuff like nodejs. Let’s close this :–)

For anyone coming here in the future, there are three workarounds that I can think of:

  1. Separate the “foo.bar” file from the “foo.bar.ts” file, i.e. in a subdirectory
  2. Rename one of the files so they don’t share prefix, e.g. “foo.bar” and “foo_bar.ts”
  3. Use import "./foo.bar.ts" and ignore or filter out the TypeScript error

Thank you for investigating Evan!

@rsms rsms closed this as completed May 18, 2020
@matthiasg
Copy link

Since typescript actually supports importing with a .js extension and translates this to the ts extension during build I would favor esbuild to follow that convention when asked to transpile ts files.

E.g import something from './something.js' should be allowed and resolve to ./something.ts in case the original file is a ts file and a something.ts exists

@evanw
Copy link
Owner

evanw commented Aug 10, 2020

@matthiasg Thanks for the reminder about this behavior. That sounds reasonable to me. I'll include this in the next release.

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

No branches or pull requests

3 participants