Removing session
#5883
Replies: 25 comments 116 replies
-
I'm all for removing |
Beta Was this translation helpful? Give feedback.
-
I love But I'm all for change that resolves issues and uses the new capabilities we have. |
Beta Was this translation helpful? Give feedback.
-
Is the And if so, what will know to update and how? |
Beta Was this translation helpful? Give feedback.
-
Is this still happening ? Wasn't sure of the meaning of |
Beta Was this translation helpful? Give feedback.
-
How could I reach the data from a |
Beta Was this translation helpful? Give feedback.
-
I just tried doing this on a project, and it does work quite fine for the SSR, but the moment the client goes to another page and the client side navigation has to trigger a load, the call to // +layout.server.ts
import type { LayoutServerLoad } from '../../.svelte-kit/types/src/routes/$types';
import type { Session } from '$lib/models/session';
export const load: LayoutServerLoad = ({ locals }): { session: Session } => {
console.log('load server'); // Only logged on server (as expected)
return {
session: {
authToken: locals.authToken,
},
};
}; // +page.ts
export const load: PageLoad = async ({ parent, fetch, params }): Promise<{ some: Thing }> => {
console.log({ p: await parent() });
// On server: { p: { session: { authToken: 'some_token' } } }
// On client on navigation: { p: { } }
} Otherwise I'm a big fan of the idea. I have been cursing that session object for quite a while. |
Beta Was this translation helpful? Give feedback.
-
So I'm having a similar issue with // layout.server.js
export async function load({url, request}) {
const session = await db.getSession(request.headers.cookies)
console.log("session", session) // << does get here
return session
} // layout.js
<script>
export let data
</script>
<slot />
{JSON.stringify(data) } // logout/page.server.js
import cookie from 'cookie'
import { redirect } from '@sveltejs/kit'
export async function load({ request, setHeaders }) {
const str = cookie.serialize("sid", "", {
path:"/",
expires: new Date(0)
})
setHeaders({'set-cookie': str})
throw redirect(302, "/")
} when i navigate to logout I see something in the terminal like the following which indicates
However the |
Beta Was this translation helpful? Give feedback.
-
This change makes me super happy. Mostly because it makes the DB part of this #4822 no longer a pain. |
Beta Was this translation helpful? Give feedback.
-
I'm rethinking my entire existence looking at all the changes in SvelteKit over the last couple of weeks. From now on, you need to do I have the utmost respect and admiration for everyone involved in the development of this framework, I really do, but it has to be said, this is all very disappointing and backwards. |
Beta Was this translation helpful? Give feedback.
-
Could we have this moved to "announcement"? Might make it easier for people to see these changes more visibly |
Beta Was this translation helpful? Give feedback.
-
Under "Why don't we need it any more?", the example uses // src/routes/+layout.server.js
/** @type {import('./$types').Get} */
export async function GET({ request, setHeaders }) { Shouldn't it use /** @type {import('./$types').LayoutServerLoad} */
export async function load({ request, setHeaders }) { I used this code as reference when refactoring my codebase and couldn't figure out why it wasn't working until I looked at the docs and tried changing it to load. |
Beta Was this translation helpful? Give feedback.
-
I dont think removing session is that bad. However, i dislike the loss of type safety for global state. |
Beta Was this translation helpful? Give feedback.
-
@Rich-Harris Have you migrated svelte.dev yet? I'm using supabase with their auth-helpers and now don't know how to use it with the latest sveltekit as it expects
Any ideas how to get this working without rewriting the supabase auth helpers? |
Beta Was this translation helpful? Give feedback.
-
Hey guys, In our //add the language the user's browser accepts as main language
/** @type {import('@sveltejs/kit').GetSession} */
export function getSession(event) {
const languageHeaderParsed = parseHeader(event?.request?.headers?.get('accept-language'));
let acceptedLanguage = languageHeaderParsed && languageHeaderParsed[0] ? languageHeaderParsed[0].code : 'de';
if (!supportedLanguages[acceptedLanguage]) {
acceptedLanguage = 'de';
}
return {
'user-language': acceptedLanguage
};
} We now could access the language using If I understand you correctly I now have to put the logic I've put into Thank you! |
Beta Was this translation helpful? Give feedback.
-
@dummdidumm The generated types by Svelte on this example aren't correct. You'd expect any page that taps onto the default layout's server load function to have typed in its returning value, and it completely lacks any information about that signature. It seems to be due to named layouts.
|
Beta Was this translation helpful? Give feedback.
-
I'm trying to refactor my app to the latest SvelteKit version. Updated to 414 first, took a few hours but everything works and the code got better I think (absolutely love the new data prop vs the old hooks.js import cookie from "cookie";
export async function handle({ event, resolve }) {
const cookies = cookie.parse(event.request.headers.get("cookie") || "");
event.locals.token = cookies.token;
return await resolve(event);
} +layout.server.js export async function load({ locals }) {
return {
...locals
};
} +layout.js export async function load({ fetch, parent }) {
const data = await parent();
console.log(data);
} I get an empty object here, even though the token is definitely returned from |
Beta Was this translation helpful? Give feedback.
-
for those who have been struggling to get SvelteKit and Supbase Auth to play nicely. I've been battling away and got it working as nicely as I can figure. I'm still unsure why we need to set the cookies, as I expected the Supabase auth redirection to do that, but it doesn't seem to happen in Firefox. Anyway; suggestions for improvement in my approach more than welcom. |
Beta Was this translation helpful? Give feedback.
-
What would be the
This is massive update, as the simple use of Not sure it's the best decision. Seem like all the recent changes have taken away from |
Beta Was this translation helpful? Give feedback.
-
From my point of view, this is the most controversial part in all this API update. But after implementing on some projects and seeing the solution from @j4w8n here #5883 (reply in thread) I have to admit that this is a much cleaner way to solve the Yes, I a bit more boilerplate ( just a bit...), but at least in my experience working with new devs, the moment I explained how $session store works is confusing, specially when you could overwrite it in the client side ( that's pretty ugly/awful/confusing.... ). Congrats @Rich-Harris for this update ( I hope the last big one ) and I think in the long term we will see the benefit of all theses changes. |
Beta Was this translation helpful? Give feedback.
-
One problem I'm going to run into with this change is that I was previously using the ability to update the session client-side as a way to provide limited personalisation on pre-rendered pages (after the initial load, obviously) – think about the common case where you have some sort of navigation bar that has different states depending on whether the user is logged in or not. Previously, I'd created an endpoint that just returned the contents of the server generated session, so I could just fetch that in my root layout's onMount and update the session store with the results. Non-prerendered pages could use session directly, while prerendered pages could still use session data asynchronously within components via the session store. I can definitely recreate a session store myself, but it does feel like SvelteKit is a bit less straightforward in this use case as a result. |
Beta Was this translation helpful? Give feedback.
-
In case anyone is interested, this is what i came up with (works great with supabase): Types can be declared like before /// <reference types="@sveltejs/kit" />
declare namespace App {
interface Locals extends UserSession {
user: import('@supabase/supabase-js').User;
accessToken?: string;
error: import('@supabase/supabase-js').ApiError;
}
interface Session {
user: import('@supabase/supabase-js').User;
accessToken?: string;
}
interface PageData {
session: App.Session;
}
// interface Platform {}
} src/lib/stores.ts import { getContext, setContext } from 'svelte';
import { writable, type Writable } from 'svelte/store';
// store creation
export const session = getContextStore<App.Session>('__SESSION__');
// helper functions
export function setupContextStore<T>(key: string, data: T) {
const store = setContext<Writable<T>>(key, writable(data));
let initial = true;
function update(data: T) {
if (initial) {
initial = false;
return;
}
store.set(data);
}
return {
store,
update
};
}
function getContextStore<T>(key: string): Writable<T> {
const store: Writable<T> = {
subscribe: (cb) => setup().subscribe(cb),
set: (cb) => setup().set(cb),
update: (cb) => setup().update(cb)
};
return store;
function setup() {
const { set, update, subscribe } = getContext<Writable<T>>(key);
store.set = set;
store.update = update;
store.subscribe = subscribe;
return store;
}
} provide the session data src/routes/+layout.server.ts import type { LayoutServerLoad } from './$types';
export const load: LayoutServerLoad = ({ locals }) => {
return {
session: {
user: locals.user,
accessToken: locals.accessToken
}
};
}; use parent data src/routes/account/+layout.ts import { redirect } from '@sveltejs/kit';
import type { LayoutLoad } from './$types';
export const load: LayoutLoad = async ({ parent }) => {
const data = await parent();
if (!data.session.user) {
throw redirect(302, '/signin');
}
}; setup the store src/routes/+layout.svelte <script lang="ts">
import { session, setupContextStore } from '$lib/stores';
import type { LayoutData } from './$types';
export let data: LayoutData;
const { update: updateSession } = setupContextStore<App.Session>('__SESSION__', data.session);
// update the store whenever the layout data is invalidated
// ignores the first run
$: updateSession(data.session);
</script> use the store src/routes/+page.svelte (or any other page/component nested in the root layout) <script lang="ts">
import { session } from '$lib/stores';
</script>
<!-- print out the users email -->
<p>{$session.user.email}</p> |
Beta Was this translation helpful? Give feedback.
-
Can we update the sveltekit realworld app to reflect this update? I always go back to that as a reference and it would really clarify things for me. This has been the most confusing change to me as a beginner. Only reason I updated to latest was cause session was misbehaving for some reason, but now I see this :D |
Beta Was this translation helpful? Give feedback.
-
I have successfully converted my app from the old The issue I am having, is that on successful sign in, I am using Is there anything inside the e.g.
|
Beta Was this translation helpful? Give feedback.
-
I'm a little late to this party; hopefully, someone can help get me straightened out. I'm migrating our big ole app and working through all of this. Like many of you, I've got user deets in session. Taking @Rich-Harris example up top doesn't seem to work $page.data doesn't seem to reflect was +layout.server.js returned. Now I've found this https://kit.svelte.dev/docs/load#input-properties-data, which leads me to if that is now the way, what is the point of $page? All in all, I've read through this and a few other things multiple times but I'm confused AF. I'd like to make sure I get this right as 1/2 of my site used the old session damn near everywhere. |
Beta Was this translation helpful? Give feedback.
-
@Rich-Harris @dummdidumm I have an application written around Currently, I store the user's data, including these pair of tokens, in // routes/accounts/sign-in/+page.svelte
...
const handleLogin = async () => {
const [res, err] = await post(`${BASE_API_URI}/login/`, {
user: {
email: email,
password: password
}
});
if (err.length > 0) {
errors = err;
} else {
const userResponse: UserRequest = res;
if (userResponse.user) {
$session.user = userResponse.user;
$notificationData = {
message: `Login successful ${happyEmoji}...`,
backgroundColor: `${greenColor}`
};
await goto($redirectUrl || '/');
}
}
};
... And subsequently, in protected routes, check whether or not a user is authenticated. In my // routes/+layout.svelte
...
const refreshToken = async () => {
if (!isEmpty($session.user)) {
const res = await fetch(`${BASE_API_URI}/token/refresh/`, {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
refresh: $session.user.tokens ? $session.user.tokens.refresh : ''
})
});
const accessRefresh = await res.json();
$session.user.tokens = accessRefresh;
}
};
...
let clear: any;
$: {
clearInterval(clear);
clear = setInterval(refreshToken, 499990);
} To get and update user tokens at intervals. How can I migrate this to the new SvelteKit version since the |
Beta Was this translation helpful? Give feedback.
-
Update: session was removed in #5946
One of the great joys of designing APIs is the realisation, when you finally hit upon the right design, that previously hard problems become trivial to solve. An example: while we were coming up with #5748, we realised that it gave us the opportunity to generate types for
export let data
, giving you incredibly low-effort type safety.In other cases, it's being able to remove features of the design that existed to compensate for shortcomings that no longer exist.
session
is one of those features.What is
session
?session
is an app-level construct that basically exists to get commonly-needed data from the server to the client. Most often, it's used for information about the currentuser
. The data is available inload
functions and via thesession
store.It is created by the
getSession
hook.Why don't we need it any more?
When we introduced 'page endpoints', we solved the problem of getting data from the server to the client, but only for 'leaf nodes'. After #5748, we have a much more general solution — all you need to do is put some data in your root
+layout.server.js
file......and every
load
function can access it withparent
......and every page can access it via
$page.data
:If a
load
function didn't depend onuser
, it would no longer be blocked ondb.getUser
, unlike today.Ok but is it doing any harm?
Yes.
For one thing, any concept that increases the API surface area is bad, other things being equal — it's just more stuff to learn. In the case of
session
it touches the API in three separate places —load
,$app/stores
andgetSession
.It causes confusion in other ways. Navigating from a prerendered page to a non-prerendered page results in an unpopulated
session
(#4426), which is very hard to solve cleanly. Because it's a writable store, people sometimes write to it, and that causesload
to re-run at times they don't expect (#3732/#2301).It also causes unnecessary work. On https://svelte.dev, we have to read session data from Supabase for every single request, even though the only place we actually need session data is https://svelte.dev/repl and https://svelte.dev/apps. (I only just realised this, but since we're prerendering most of the site, this means we're affected by the unpopulated
session
bug described in the last paragraph. That's how insidious the bug is!)Getting rid of all this stuff would be a huge win.
Beta Was this translation helpful? Give feedback.
All reactions