kit: Dev server does not apply base path correctly

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 😄

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 23
  • Comments: 57 (15 by maintainers)

Commits related to this issue

Most upvoted comments

I am running a svelte-kit dev server behind a code-server proxy and can confirm that this is still an issue. Any fix or workaround available?

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

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

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

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 pardon me asking, maybe I’m missing something here, but what exactly has been fixed? You basically just said “works for me” (which is fine and probably true for the example above), but has there been any change addressing the original problem and the comments above?

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

In a setup with a reverse proxy, the “external base path” might or might not be preserved when forwarded to the server itself. So it would be nice to have either a) thw base paths: an external that is used when creating all the links and an internal that is used when interpreting the requests b) a flag that allows for the fact that the proxy might remove the external base path when relaying the request to the server.

It’s really annoying. I need to run the programm behind a reverse proxy in order get the correct authentication information. I would run “dev” mode, but that does not work in that setup. So i need to run buikd and preview after each change in code.

Above point_up_2 there are the routes you need to add to your proxy. Posted as an example for nginx. Adapt, and it works. Do you need any help with another proxy?

Only works for one proxied site. Two or more is currently impossible.

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

If you’re just running the dev server locally, you will be able to navigate the project. Check the browser dev tools and note the paths that are being requested. The /@fs/... paths don’t include the base path prefix. This is the actual issue that needs to be addressed.

It works for local development because the local dev server has access to both the base path and the non-prefixed paths. It becomes a problem for development behind a proxy where the base path is necessary to access any files on the dev server. In my case, this is surfaced when I’m trying to use code-server to develop. The dev server isn’t accessible locally because it isn’t running locally. Instead, I access it through a proxied base path. It works for the initial page load but those /@fs/... paths can’t be reached without the base path prefix.

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.

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.

Perhaps this line:

https://github.com/sveltejs/kit/blob/06a56ae587795113b17fec559ab49c93f40861e8/packages/kit/src/runtime/server/page/render.js#L168

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?

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.

Note that both http://localhost:3000 and http://localhost:3000/foo give you a 404.

http://localhost:3000/foo works for me. Closing as fixed

So I just wanted to clarify and provide simple repo steps, and make sure I’m actually in the right bug (I can open a new one if not.) This doesn’t have anything to do with proxies or missing js/css assets, it’s actually that the main HTML document is 404 when using a base path and running in dev mode.

  1. Init a brand new SvelteKit app with npm init svelte@next sv which gives as of now, SvelteKit v1.0.0-next.230
  2. Choose the Demo App
  3. cd sv; npm i
  4. npm run dev
  5. Everything works fine
  6. Kill that, edit svelte.config.js to include kit.paths.base = '/foo'
  7. Start up again with npm run dev
  8. Note that both http://localhost:3000 and http://localhost:3000/foo give you a 404.
  9. Note that deeper paths do work however, i.e. http://localhost:3000/foo/about

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?