Repository navigation
fix: let the root route honor an explicit trailingSlash option when paths.base is set - #17392
Open
firatciftci wants to merge 4 commits into
Open
firatciftci wants to merge 4 commits into
firatciftci wants to merge 4 commits into
Conversation
… `paths.base` is set
…se root trailing slash
|
Install the latest version of pnpm add https://pkg.svelte.dev/@sveltejs/kit/c/5d3e9c2f613be33a5c5e927eb0f9345f21a5b47bOpen in Note This PR is from a fork. A maintainer must approve approve each commit before it can be built and installed. |
🦋 Changeset detectedLatest commit: 5d3e9c2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #17391.
With
paths.baseset, the root route always redirects to the slash form (/appto/app/), even when the root layout exportstrailingSlash = 'never'. This PR lets an explicittrailingSlashon the root apply to pages rendered on demand. Apps that don't set the option, and prerendered roots, keep the current behavior.Why the rule exists
#9343 added the rule to fix #9341. With relative paths, the root's assets are emitted as
./_app/..., and those links only resolve from/app/. From/app,.resolves to/. A prerendered root also has to keep the slash, because it's written toindex.htmland static hosts serve it at/app/. #10763 and #11388 later aligned the preview server and the client router with the same rule.The PR keeps both reasons intact and only changes the case neither applies to: a root rendered on demand, whose layout explicitly asks for no slash.
Changes
respond.js: the root route still defaults to'always', but an explicitly settrailingSlashnow wins, unless the root is being prerendered.PageNodes#trailing_slashtakes a fallback so the root can tell "unset" apart from'never'.$app/paths/internal/server.js: a newrelative_base(pathname)holds the relative-prefix rule. When the request is for the base itself (/app), it returns./appinstead of., so links resolve to/app/.... Every other pathname gets the same.or../..prefix as before.resolve_pathsinserver_routing.js(assets, the hydration base and server-side route resolution) and the server-sideresolve()in$app/paths/server.jseach had their own copy of this rule. They both use the shared function now, which keeps<a href={resolve('/about')}>on the root from resolving to/about.render.js: the hydrationbaseexpression now resolvesbase + '/'before removing the trailing slash, so./appgives/appand not/ap. For.and../..the result is the same as before.client.js: the root defaults to'always', and the branch'sslashoverrides it the same way it does for every other route. As in fix: respect trailing slash option when navigating from the root page of the basepath #11388, the default only applies when the target is the root, so it doesn't leak into navigations away from it.preview/index.js: the preview server only does its/appto/app/redirect when a prerendered rootindex.htmlexists. Otherwise the request goes to the server, which applies the rule above.Verified
I used the reproduction from the issue (adapter-node,
base: '/app', root layouttrailingSlash = 'never') built against this branch:/app./app//app/../app/app/about/app/about/../about../about/app, asset links render as./app/_app/immutable/...and load with 200. The page hydrates. Navigating/appto/app/aboutto/appto back stays on one document load, with no console errors.trailingSlashexport,/appstill redirects to./app/, as before.prerender = trueandtrailingSlash = 'never'on the root, the root is still written toindex.htmlwith./_app/...links andnew URL("./", location)as the base, the same as today.Open question
A prerendered root that sets
trailingSlash = 'never'still gets the slash, since itsindex.htmlcan only be served from/app/. The client router doesn't know whether the root was prerendered, so a client-side navigation to it lands on/app, while a reload is served at/app/. I checked this in a browser with adapter-node and only the root prerendered. Going from/app/aboutto the root client-side shows/app. A reload redirects to/app/and servesindex.htmlwith every asset loading, and navigating on from there works. There were no failed requests and no console errors, so the only difference is the address bar. I could add a build warning for this combination, or document that prerendered roots under a base path always keep the slash. I'd go with whichever you prefer.Tests
This PR adds a small
base-root-trailing-slashtest app (port 5312), because options-2 asserts the default/basepathto/basepath/redirect and needs to keep it. The app hasbase: '/basepath'and a root layout withtrailingSlash = 'never', and it checks:/basepathreturns 200, and/basepath/?foo=barreturns a 308 to../basepath?foo=bar/basepathwith no failed requests, andresolve('')gives./basepath/during SSR/basepathto/basepath/aboutto/basepathkeeps the slashless root, with and without JSOn
mainall 8 build-mode tests fail. On this branch all 8 pass in dev and build modes. The no-JS failures without therelative_basechange are how I found the duplicatedresolve()rule.Locally,
pnpm check,pnpm lintandpnpm test:unit(1063 passed) are clean. These suites pass in dev and build modes: the new app,options-2(including the service worker runs),options,hash-based-routingandembed, plusoptionswith server-side route resolution. Inbasics, two tests failed in the full runs and passed three times out of three when rerun alone: "using window.fetch does not cause false-positive warning" and "AbortSignal works with internal fetch optimization". One more, "captures and restores function snapshots on shallow navigations", fails underROUTER_RESOLUTION=serveronmainas well.Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
Tests
pnpm testand lint the project withpnpm lintandpnpm checkChangesets
pnpm changesetand following the prompts. Changesets that add features should beminorand those that fix bugs should bepatch. Please prefix changeset messages withfeat:,fix:, orchore:.Edits