Open benmccann opened 2 years ago
Adding another comment from #3726 which is relevant:
Oh, I really need this to be fixed. I cannot use the workaround mentioned earlier because my case is one level more complex as I need to use the generated middleware handler in another express server (directus). I cannot control exactly when to .use(handler)
and they bind many other middlewares which means that I have to bind the sveltekit handler only to a single subpath (say /dashboard
).
.use(handler)
without setting paths.base
Both frontends (sveltekit and directus) are confused and nothing works...
.use(handler)
with setting paths.base
to /dashboard
Sveltekit frontend displays html pages but scripts are not found. But directus does not load correctly.
.use('/dashboard', handler)
without setting paths.base
I can access the sveltekit frontend via /dashboard
but internal links (href="{base}/about") are not working as base
is empty and javascript cannot be loaded (urls do not contain /dashboard
and thus are not handled by the middleware). Directus works without probems.
.use('/dashboard', handler)
with setting paths.base
to /dashboard
I can access kit via /dashboard/dashboard
(yes duplicated) but the the about page is not available at /dashboard/about
(which is build from href="{base}/about") but at /dashboard/dashboard/about
. Basically I need to duplicate the base path. Strangely now the javascript files can be loaded correctly (at /dashboard/_app/immutable/start-e25cee58.js).
I found I can fix this by removing these lines https://github.com/sveltejs/kit/blob/2a9c19252912d61bd840441fe80dc13366af41f7/packages/kit/src/runtime/server/index.js#L58-L63
Now everything works as expected (i.e. /dashboard
and /dashboard/about
) at least with my minimal testing.
This is surely not the final solution as the dev server needs those lines and I guess the other adapters need them as well...
I got one step further by adding the base url to the request before passing it to the handler
:
app.use('/dashboard', (req, res, next) => {
let requestProxy = new Proxy(req, {
get(target, property) {
if (property === 'url') {
return target.baseUrl + (target.url === '/' ? '' : target.url);
}
return target[property];
},
});
handler(requestProxy, res, next);
});
Now the ssr
function works correctly (because it strips the basepath we just added) but the static files are not correctly served (because sirv does not strip the basepath) as @bundabrg also noted in https://github.com/sveltejs/kit/issues/3726#issuecomment-1049460340
Originally posted by @fehnomenal in https://github.com/sveltejs/kit/issues/3726#issuecomment-1186534972
Anyone have any workarounds to this issue? Its blocking me for dynamic path deployments if i dont know the base at build time
Same here
I found this to work:
import CONFIG from "../svelte.config.js"
import { dev } from "$app/environment";
...
redirect(307, (dev? "" : CONFIG.paths.base) + "/normal/redirect");
Oh wait a second. I think I fixed it. If I reply below, then know that I've "fixed" it. If not, then try using this in your code.
nvm, it "works" but it causes like 100 recursive definition errors which (depending on the environment) could cause the build/
folder to be missing some very very important js files.
Ok, so I found another solution. This solution will only work if you will be setting the base path at compile time. If you are doing it right before launching the executable, I think you could use dynamic env variables instead and manually route everything. Or perhaps intercept the default router.
So, for this method, you will need
1) base.js
- some file in your project root directory. Maybe you could also put it in $lib
.
const BASE = "/new";
export default BASE;
2) Modify svelte.config.js
:
import BASE from "../base.js";
...
export config = {
...
paths: {
base: BASE,
relative: false
}
...
};
3) And finally, modify +hooks.server.ts
or whatever +page.server.ts
:
// make sure to get the path right
import BASE from "../base.js";
...
redirect(307, BASE + "/login");
This works. But this is a work around, not a fix.
When generating a static site we ultimately will be placing it either in the correct folder OR preferably behind a load-balancing reverse proxy that strips off the prefix and have it served from the root. So the prefix should not exist in the build folder at all but the code will need to know to add the prefix when referring to assets.
When generating a dynamic site it can be passed environment variables (or perhaps read a config file) where it gets its base prefix. In the same way the site could exist behind a reverse proxy that strips off the prefix OR it'll handle the prefix itself. It matters not as this is an implementation detail of the adapter. The code needs to know to add the prefix when referring to assets and presumably when doing SSR fetching it'll need to know to add/remove the prefix as necessary.
adapter-node
usesPolka
to serve its assets, executed with the following code:handler
is provided as:The issue is that
ssr
will strip offbase
from the beginning of the URL but the threeserve
calls do not. Thessr
function IMHO should not be doing this and instead everything should be mounted at thepolka().use()
call, something like this:where
BASE_PATH
would be set either by reading the config file or come in from an environment variable.This way if I have a reverse proxy that strips prefixes I can have
BASE_PATH
set to '' but pass the actual base through a header likeX-Forwarded-Prefix
for when building URL's.If I don't strip the prefix, then I can set
BASE_PATH
to the prefix so its handled inside Polka instead but otherwise the rest of the code remains the same.Anyway, that's my 2c.
Originally posted by @bundabrg in https://github.com/sveltejs/kit/issues/3726#issuecomment-1049460340
This overlaps a bit with https://github.com/sveltejs/kit/issues/595