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

Dev server does not apply base path correctly #2958

Closed
andycarlberg opened this issue Dec 1, 2021 · 57 comments · Fixed by #8046 or #8651
Closed

Dev server does not apply base path correctly #2958

andycarlberg opened this issue Dec 1, 2021 · 57 comments · Fixed by #8046 or #8651
Labels
bug Something isn't working p1-important SvelteKit cannot be used by a large number of people, basic functionality is missing, etc. paths.base bugs relating to `config.kit.paths.base`
Milestone

Comments

@andycarlberg
Copy link

andycarlberg commented Dec 1, 2021

Describe the bug

I'm using a code-server cloud environment to develop a SvelteKit project. In order to access the dev server, a proxy is provided that uses a subpath to proxy the dev server port (see docs. This leads me to need a base path to be set for the dev server.

If I set kit.paths.base as stated in the documentation, the first page load works correctly but the import statements are relative to the root which returns a 404, correctly, because those files are not available without the proxy. If I run build and preview everything works as expected since the base path is built into the compiled project.

Expected behavior
All paths in the dev server reference the base path instead of being relative to the root domain.

Reproduction

  1. Create a new SvelteKit project
  2. Set kit.paths.base to a non-root path
  3. Run the dev server

Expected result
All import statements look for paths with the base path or relative to the base path

Actual result
Module import statements are relative to the root

Example
image
image

Logs

GEThttp://domain.tld/.svelte-kit/dev/runtime/internal/start.js
[HTTP/1.1 404 Not Found 8ms]

Loading module from “http://domain.tld/.svelte-kit/dev/runtime/internal/start.js” was blocked because of a disallowed MIME type (“application/json”). 3000
Loading failed for the module with source “http://domain.tld/.svelte-kit/dev/runtime/internal/start.js”. 3000:13:1
GEThttp://domain.tld/favicon.png
[HTTP/1.1 404 Not Found 6ms]

System Info

System:
    OS: Linux 5.10 Ubuntu 20.04.3 LTS (Focal Fossa)
    CPU: (12) x64 Intel(R) Core(TM) i5-10400 CPU @ 2.90GHz
    Memory: 283.55 MB / 15.32 GB
    Container: Yes
    Shell: 5.0.17 - /bin/bash
  Binaries:
    Node: 14.18.2 - /usr/bin/node
    Yarn: 1.22.15 - /usr/bin/yarn
    npm: 6.14.15 - /usr/bin/npm
  npmPackages:
    @sveltejs/kit: ^1.0.0-next.201 => 1.0.0-next.201 
    svelte: ^3.42.6 => 3.44.2

Severity

annoyance

Additional Information

I've been using the absproxy method with code-server. This passes the full path with the /absproxy/3000 portion intact. This seems like the correct approach for usage with kit.paths.base. I think this method would work fine if the dev server accounted for it when building the pages.

However, there is also the proxy method. The proxy method strips of the proxy subpath before passing the request to the dev server. Thus, on the dev server, all the paths are relative to root. If there was a way to specify a subpath only for use on the client side, this may also be a reasonable solution.

I've made some inline edits to the @sveltejs/kit package in node_modules and was able to get the proxy method working. It would require a config field to set it, of course. Obviously, not everyone is working in a cloud server 😄

@andycarlberg
Copy link
Author

andycarlberg commented Dec 10, 2021

Decided to see if I could fix this myself. After digging in it looks like this might actually be a Vite issue, not a SvelteKit issue.

It's possible that SvelteKit may need additional updates beyond the fix for Vite as well.

@Bastian
Copy link

Bastian commented Dec 14, 2021

I'm having the same issue. My dev server is running behind a Traefik Reverse Proxy and thus it fails to resolve the .svelte-kit/* files which are ignoring the kit.paths.base setting:
image

This is the config with the kit.paths.base set to /demo:

import adapter from '@sveltejs/adapter-node';
import preprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	// Consult https://github.com/sveltejs/svelte-preprocess
	// for more information about preprocessors
	preprocess: [
		preprocess({
			postcss: true
		})
	],

	kit: {
		adapter: adapter(),

		// hydrate the <div id="svelte"> element in src/app.html
		target: '#svelte',
		ssr: true,
		trailingSlash: 'ignore',
		paths: {
			base: '/demo'
		}
	}
};

export default config;

@andycarlberg
Copy link
Author

@Bastian is correct, this is not actually a Vite issue as I first suspected. It does seem to be specific to SvelteKit. So I'll keep looking but I'm probably out of my depth here for a quick fix.

I started looking at it as a Vite problem because I always seemed to come back to Vite when trying to trace the issue through SvelteKit. I must have missed something though since a vanilla Vite project applies the base path as expected.

@rassie
Copy link

rassie commented Dec 14, 2021

@andycarlberg

I've made some inline edits to the @sveltejs/kit package in node_modules and was able to get the proxy method working. It would require a config field to set it, of course. Obviously, not everyone is working in a cloud server smile

Could you share a gist of what you've changed?

@andycarlberg
Copy link
Author

@rassie
I've pushed up some of my work-in-progress tinkering with the change essentially here.

This applies the base path prefix to the entry file. This is not a complete fix because I'm having trouble finding where these paths should actually be set. It's not a complete solution, more proof that there's an issue to be addressed I think.

@andycarlberg
Copy link
Author

I feel like I'm on the right track here with this change.

It correctly outputs the file path with the base prefix but it 404's when looking for that start.js file. In debugging, it seems like that file is treated differently than other requests since the SvelteKit middleware doesn't process that file without my change (i.e. root-relative).

Any hints on where I might look to get it to recognize that file as the special start file even if it has the prefix?

@bjaskj
Copy link

bjaskj commented Jan 10, 2022

I spent some time on something I think is similar, but I did not manage to figure out a fix for it.

I'm trying to use svelte kit via proxy server, and it works fine with static build and serve via other folder than root (having kit.paths.base) but it goes around and tries to include files that are in "root", like node modules etc. I only got it working if I set the base in vite config in the kit package and also modified the prefix, see below:

I think it boils down to the core/dev/index.js having a hardcoded value of "/", I tried playing around with this with some success but I ran into other issues trying to find a way to set it.

I also looked into prefix set to value of "" in this core/dev/plugin.js

This makes the paths to the script resources etc used in start method inside runtime/server/page/render.js

Maybe someone can help with a fix on this?

@johnnysprinkles

This comment has been minimized.

@johnnysprinkles

This comment has been minimized.

@bjaskj
Copy link

bjaskj commented Jan 13, 2022

What happen to me was that if I set kit.paths.base and then also the vite base path, which is hardcoded to '/' in kit, then I have to use /mypath/mypath to get to index. So something is a bit bork. Also if I managed to get it use /mypath, then all the other paths (node_modules, svelte kit etc) would still go to root/hostname http://localhost/.svelte-kit.

@johnnysprinkles

This comment has been minimized.

@benmccann

This comment has been minimized.

@rassie

This comment has been minimized.

@bjaskj

This comment has been minimized.

@johnnysprinkles

This comment has been minimized.

@johnnysprinkles

This comment has been minimized.

@rassie
Copy link

rassie commented Jan 21, 2022

@johnnysprinkles sorry to be blunt, and I don't think you intended this, but I think you derailed this issue for an unrelated problem.

@benmccann the problem in question still exists and it's a different one. In the example above, localhost:3000/foo is working, but the reason why it's working is because localhost:3000/.svelte-kit is still available without a proxy. If you put a proxy in front and only forward /foo to the server, you'd only forward requests to /foo, but not /.svelte-kit, you'll be getting 404 errors for SvelteKit runtime and nothing will work at all. The issue here is that kit.paths.base should be applied to /.svelte-kit too, which it's currently not.

You can easily verify it with the repro above, but look into Developer Tools, where you should see something like this:

image

If /.svelte-kit is not properly forwarded as /foo/.svelte-kit, nothing will work. And forwarding just /.svelte-kit is not a solution, since the whole reason people use proxies is to host multiple sites on the same domain, so most people need a /foo with /foo/.svelte-kit and a /bar with /bar/.svelte-kit.

@andycarlberg
Copy link
Author

As OP, i wanted to verify that @rassie is correct. Their comment shows the issue I was originally trying to deal with. I haven't personally made any further progress on it but would agree the issue is not fixed.

@benmccann benmccann reopened this Jan 21, 2022
@benmccann benmccann removed this from the 1.0 milestone Jan 21, 2022
@benmccann benmccann added the p3-edge-case SvelteKit cannot be used in an uncommon way label Jan 21, 2022
@tecoad
Copy link

tecoad commented Jan 26, 2022

I confirm this issue, I was meant to user sveltekit on a /blog subdirectory, however all assets still load from root, when it should rewrite to kit.paths.base. Unfortunately will have to stick with nextjs for this project.

@Beiri22
Copy link

Beiri22 commented Feb 10, 2022

Might be the same problem in my situation: I try to access the dev server via a reverse proxy. I have tried kit.paths.base and kit.vite.server.origin. Nothing works to set the sub-path associated on the proxy machine. Still showing import { start } from "/@fs/ which should use some subdirectory...

@davidroeca
Copy link

My team uses nginx + docker-compose to set up a dev environment with multiple APIs/frontends. Since we only have one svelte-kit project, this is ok for now, but it is not ideal. In order to get the current version of svelte-kit to work in this set up, we need to set up nginx with the below configuration. I'd expect that analogous configuration is required in whatever reverse proxy environment is being used. (HMR config is separate, but easier to implement because it's on a different port).

        location /svelte-kit-ui-base-path {
            set $target "http://svelte_kit_ui:3000";
            proxy_pass $target;
        }
        location  /@fs {
            set $target "http://svelte_kit_ui:3000";
            proxy_pass $target;
        }
        location /.svelte-kit {
            set $target "http://svelte_kit_ui:3000";
            proxy_pass $target;
        }
        location /node_modules {
            set $target "http://svelte_kit_ui:3000";
            proxy_pass $target;
        }
        location /@vite/client {
            set $target "http://svelte_kit_ui:3000";
            proxy_pass $target;
        }
        location /src {
            set $target "http://svelte_kit_ui:3000";
            proxy_pass $target;
        }

I'd view this as a work-around, not a long-term solution. Hopefully this saves time for anyone else having trouble with this.

It would be very nice to be able to prefix every route above with /svelte-kit-ui-base-path.

@JohnRSim

This comment was marked as resolved.

@JohnRSim

This comment was marked as resolved.

@BenediktAllendorf
Copy link

I didn't find a working configuration, but I've managed to patch the source code to work as desired.

I think there are two parts to this:

  1. The import of start.js must use the correct (base-)prefix.
  2. The base for Vite must be set correctly instead of the hardcoded ./.

It worked as expected when adding my prefix ( web) into those two lines. I could run my SvelteKit-project at localhost:3000/ and access it via my proxy at localhost:9999/web. Please note that I didn't add paths.base to svelte.config.js because then I would have had localhost:3000/web/web and localhost:9999:/web/web ( I guess that's an artifact of messing around).

I feel SvelteKit's understanding/usage of "base" differs from Vite's - how is it supposed to work here? I'm willing to create a PR for this, but I'd need some guidance (as in, is this even reasonable? How should this be tested?).

@benmccann benmccann added the vite label Oct 11, 2022
@benmccann
Copy link
Member

I tried passing SvelteKit's base path to Vite awhile back, but found out that it's not currently possible because Vite handles the base path and static file serving in some ways that are different. We would need to resolve the following issues in Vite to make it possible to handle this correctly in SvelteKit:

I would very much welcome PRs for those issues in the Vite repo. ViteConf is today. Vite 3.2 will be released later this week I believe and then work on Vite 4 can begin, which may enable us to make these changes, which would probably all be breaking changes. I can help check with the Vite team to ensure they're open to making these changes and agree on an approach, but would love help with implementing them.

@BenediktAllendorf
Copy link

I'm eager to help with the implementation (the alternative would be for us to maintain a fork and I'd rather see this being fixed upstream), but I'm cannot really asses right now what/where exactly should be changed. So if you, @benmccann, check with the Vite team, that would be great!

@benmccann
Copy link
Member

I talked to the Vite team this morning and made quite a bit of progress on a plan for moving forward. I sent #7343 to address one of the items. I also sent vitejs/vite#10590 to address a good chunk of vitejs/vite#9236. @BenediktAllendorf I'll ping you after vitejs/vite#10590 gets merged and perhaps if you're still interested you can finish the rest of vitejs/vite#9236 which would be the last blocker.

@benmccann
Copy link
Member

vitejs/vite#10590 has been merged now. @BenediktAllendorf let me know if you'd be able to take a look at vitejs/vite#9236. If we can get that fixed it should be the last blocker to setting the base path in Vite and removing our file serving in favor of Vite's. I updated that ticket with some details to help with getting started.

@rassie
Copy link

rassie commented Nov 18, 2022

Seems like those issues have been fixed. Is anything else necessary to be able to say that Vite 4 will solve this?

@benmccann
Copy link
Member

There is a Vite 4 branch of SvelteKit: #7543. I'd appreciate if folks could test against it and let me know if it is fixed or not

@alexbjorlig
Copy link
Contributor

I'm trying to figure out why I can't serve Sveltekit from a different directory - is this issue the culprit?

@benmccann
Copy link
Member

This is no longer blocked by Vite, but I believe an additional change will be needed on our side

@lc-spxl
Copy link

lc-spxl commented Jan 12, 2023

Any update on this ?

@duruer
Copy link

duruer commented Jan 15, 2023

This is no longer blocked by Vite, but I believe an additional change will be needed on our side

Yes, Vite fixed the issue, but seems like SvelteKit is still using /node_modules path.

@duruer
Copy link

duruer commented Jan 15, 2023

Seems like one of the causing issue is this line:
https://github.com/sveltejs/kit/blob/master/packages/kit/src/exports/vite/dev/index.js#L96

If I change the line like this:

file: `/test${runtime_base}/client/start.js`,

It kinda fixes the issue but, then when you visit /test, it throws this error in console and shows 404 page in browser:

TypeError: Cannot create proxy with a non-object as target or handler
    at Module.handle_error_and_jsonify (/node_modules/@sveltejs/kit/src/runtime/server/utils.js:123:12)
    at Module.render_page (/node_modules/@sveltejs/kit/src/runtime/server/page/index.js:251:25)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async resolve (/node_modules/@sveltejs/kit/src/runtime/server/respond.js:358:17)
    at async Module.respond (/node_modules/@sveltejs/kit/src/runtime/server/respond.js:229:20)
    at async file:///home/kahverengi/Projects/Pano/panel-ui/node_modules/@sveltejs/kit/src/exports/vite/dev/index.js:468:22

@benmccann
Copy link
Member

Perhaps this line:

const prefixed = (path) => (path.startsWith('/') ? path : `${resolved_assets}/${path}`);

Needs to be changed to:

const prefixed = (path) => (path.startsWith('/') ? base + path : `${resolved_assets}/${path}`);

Would someone affected by this problem be able to test it out?

@SudoerWithAnOpinion
Copy link

Looks like this change works, I'm using coder's code-server and serving from some-domain/proxy/5173

The page is loading the start script from the correct location.
image

@janabimustafa
Copy link

janabimustafa commented Mar 9, 2023

The solution appears to be inadequate in handling cases where paths.relative is enabled but paths.base is absent, which was implemented to enable flexible base paths.

If a reverse-proxy is created and directed to the site using a path like /site-pr-10, the app.js file will load correctly but the start.js file will not. Essentially, this solution disrupts the functionality described in issue #595 when used behind a reverse proxy.

mbland added a commit to mbland/vitest-utils-browser-import that referenced this issue Dec 6, 2023
These changes helped me find the definitive source of the problem in
Vite 5.0.0-beta.8:

- "fix!: return 404 for resources requests outside the base path"
  vitejs/vite@40fd2d9
  vitejs/vite#5657
  vitejs/vite#5656
  https://vitejs.dev/guide/migration.html#advanced

- Related:
  vuejs/vitepress#3239
  sveltejs/kit#2958

Of course, this is effectively a bug fix for Vite, pointing at a bug in
Vitest. Vite is now more strict about enforcing the Public Base Path,
and Vitest needs to propagate config.base somehow:

- https://vitejs.dev/config/shared-options.html#base
- https://vitejs.dev/guide/build.html#public-base-path

I'll explain the workaround in the next commit. What follows describes
how my methodology to pinpoint the problem evolved and concluded.

---

Adding the vite/packages/vite as a "file:" dependency and adding its
directory as part of the workspace proved challenging. The TypeScript
compiler (`tsc`) kept erroring out on the `tsc --emitDeclarationOnly
--outDir temp/node -p src/node` step of the build.

It took a few tries to realize that I needed to remove vite/node_modules
before every "pnpm build" in vite/. Somehow some stale artifacts were
poisoning subsequent runs.

That left the problem of running `pnpm i` in this project, which would
still try to rebuild vite/packages/vite and choke on the TypeScript.

After skimming vite/README.md, I realized I could try adding
vite/packages/vite as a "link:" dependency instead of a "file:"
dependency. I also learned I could use pnpm.overrides in package.json to
ensure other packages used this local version. I kept vitest/packages/*
in the workspace to make sure they used this linked version of
vite/packages/vite.

After that, I could now reliably build the two local packages, and have
the local vitest use the local vite.

Each time in the ../vite repository, I would:

```sh
rm -rf packages/vite/node_modules
git reset --hard <tag or commit>
pnpm i --frozen-lockfile
pnpm build
```

Then I'd go back to this repository and:

```sh
pnpm i
pnpm test
```

And here's the results of my bisection (I didn't actually use `git
bisect`, but followed the same essential process):

```text
v5.0.0-beta.12 FAIL
v5.0.0-beta.6  OK
v5.0.0-beta.9  FAIL
v5.0.0-beta.7  OK
v5.0.0-beta.8  FAIL
```text

Once I had my culprit, I went back into ../vite and ran:

```sh
gitk v5.0.0-beta.7..v5.0.0-beta.8
```

And once I did that, I could see the the commit immediately after
v5.0.0-beta.7 affected base path handling. So I repeated the process,
setting `<tag or commit>` in ../vite to
40fd2d9bf4073420e6c334f48dc3b63558b688ce. Indeed, this build failed,
confirming that commit as the culprit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working p1-important SvelteKit cannot be used by a large number of people, basic functionality is missing, etc. paths.base bugs relating to `config.kit.paths.base`
Projects
None yet