vitejs / vite

Next generation frontend tooling. It's fast!
http://vite.dev
MIT License
69.09k stars 6.24k forks source link

Wrong File Served When Route Conflicts with File in Project Root #3502

Open dvdzkwsk opened 3 years ago

dvdzkwsk commented 3 years ago

Describe the bug

Vite Config:

{
  "root": "web"
}

Project Structure:

web
├── index.html
├── main.ts
└── route.ts

A request to /route will unexpectedly serve /route.ts.

Since the file extension is omitted, I would expect for the traditional connect-history-api-fallback logic to apply and for /index.html to be served. If wanted to load the source file I would expect to have to make an explicit request for /route.ts. It doesn't seem right for the file extension to be inferred.

This is likely more of an issue for people like me who've configured root since that may mean source files sit at the top-level of root instead of nested inside of a src directory. Still, for cases such as this, this issue becomes more problematic as more source files and routes are created, since there's more opportunity for an inadvertent conflict.

Important: On the first load, you will actually see the correct fallback logic. It's only once vite has processed route.ts that the fallback behavior changes, and you'll start seeing a JavaScript file served instead of index.html.

Thanks for your help!

Reproduction

https://github.com/davezuko/reproductions/tree/master/vite-3502

Steps to reproduce:

  1. Run yarn dev
  2. Open http://localhost:3000, the app loads correctly
  3. Open http://localhost:3000/test, the app loads correctly (renders "/test")
  4. Open http://localhost:3000/route, the app serves /route.ts
  5. Open http://localhost:3000/main, the app serves /main.ts

Alternate reproduction:

  1. Run yarn dev
  2. Open http://localhost:3000/route, the app loads correctly
  3. Reload http://localhost:3000/route, the app now serves /route.ts

System Info

Output of npx envinfo --system --npmPackages vite,@vitejs/plugin-vue --binaries --browsers:

  System:
    OS: macOS 11.2.3
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 324.33 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 12.16.1 - ~/.n/bin/node
    Yarn: 1.22.4 - ~/.yarn/bin/yarn
    npm: 6.13.4 - ~/.n/bin/npm
  Browsers:
    Chrome: 90.0.4430.212
    Edge: 90.0.818.39
    Firefox Developer Edition: 78.0
    Safari: 14.0.3
  npmPackages:
    vite: ^2.3.3 => 2.3.3

Used package manager: yarn

Logs

  #####################
  Note this line, too
  #####################
  vite:resolve 1ms   /route -> /Users/zuko/projects/davezuko/reproductions/vite-xxxx/web/route.ts +0ms
  vite:spa-fallback Rewriting GET /route to /index.html +0ms
  vite:time 21ms  /index.html +0ms
  vite:resolve 1ms   /Users/zuko/projects/davezuko/reproductions/vite-xxxx/node_modules/vite/dist/client/client -> /Users/zuko/projects/davezuko/reproductions/vite-xxxx/node_modules/vite/dist/client/client.js +92ms
  vite:resolve 1ms   /@vite/client -> /Users/zuko/projects/davezuko/reproductions/vite-xxxx/node_modules/vite/dist/client/client.js +0ms
  vite:load 2ms   [fs] /@vite/client +0ms
  vite:resolve 0ms   ./env -> /Users/zuko/projects/davezuko/reproductions/vite-xxxx/node_modules/vite/dist/client/env.js +9ms
  vite:transform 9ms   /@vite/client +0ms
  vite:time 14ms  /@vite/client +88ms
  vite:resolve 1ms   /main.ts -> /Users/zuko/projects/davezuko/reproductions/vite-xxxx/web/main.ts +6ms
  vite:load 1ms   [fs] /main.ts +14ms

  #####################
  Here's where the file extension gets inferred
  vite:resolve 0ms   ./route -> /Users/zuko/projects/davezuko/reproductions/vite-xxxx/web/route.ts +21ms
  #####################

  vite:resolve 0ms   /route.ts -> /Users/zuko/projects/davezuko/reproductions/vite-xxxx/web/route.ts +1ms
  vite:transform 21ms  /main.ts +24ms
  vite:time 23ms  /main.ts +24ms
  vite:load 1ms   [fs] npm: vite +29ms
  vite:rewrite 0ms   [no imports] /Users/zuko/projects/davezuko/reproductions/vite-xxxx/node_modules/vite/dist/client/env.js +0ms
  vite:transform 0ms   npm: vite +9ms
  vite:time 2ms   npm: vite +9ms
  vite:load 2ms   [fs] /route.ts +2ms
  vite:rewrite 0ms   [no imports] route.ts +2ms
  vite:transform 2ms   /route.ts +3ms
  vite:time 4ms   /route.ts +3ms
  vite:spa-fallback Not rewriting GET /favicon.ico because the path includes a dot (.) character. +180ms
  vite:time 1ms   /favicon.ico +42ms

Before submitting the issue, please make sure you do the following

ygj6 commented 3 years ago

@davezuko I figured out that vite will return the cached moduleroute.ts,instead of treating the /route as the requested path,which is unexpected.

I have submitted a pull request ,#3513

bluwy commented 2 years ago

Still reproducible in Vite 2.8.6

haoqunjiang commented 2 years ago

I think it would be better to check the Accept HTTP request header in the Vite dev server, instead of adding an explicit query parameter.

silverwind commented 2 years ago

I think this "extension guessing" should be disabled or at least be made configurable to be disabled. I think it's bad practice to serve /foo.js on route /foo as such paths are very likely to collide with client-side routing.

patak-dev commented 2 years ago

I think you should be able to achieve that already using

resolve: {
  extensions: []
}

https://vitejs.dev/config/#resolve-extensions

silverwind commented 2 years ago

Tried setting resolve.extensions = [] but I'm not sure if vite can operate with such a config. Seeing this error:

✘ [ERROR] [plugin vite:dep-pre-bundle] Failed to resolve entry for package "function-bind". The package may have incorrect main/module/exports specified in its package.json: Failed to resolve entry for package "function-bind". The package may have incorrect main/module/exports specified in its package.json.

    node_modules/vite/dist/node/chunks/dep-8f5c9290.js:40945:10:
      40945 │     throw new Error(`Failed to resolve entry for package "${id}". ` +
            ╵           ^

That function-bind module is a eslint dependency, so it might be that the error relates to linting.

patak-dev commented 2 years ago

mmm... ya, maybe some dependencies expect resolution to work. This should be better once everybody starts to use the exports field. I don't know if Vite should consider extensions only for user code and then patch over wrongly published deps (if that is the problem here)

illegalnumbers commented 1 year ago

I think you should be able to achieve that already using

resolve: {
  extensions: []
}

https://vitejs.dev/config/#resolve-extensions

This documentation does not appear to exist any more. Are there plans to replace it?