Cookies, Sessions and Caching

When a user clicks on the add button of an item page, how does the site know what items were added in subsequent requests? There are different ways of dealing with this problem, each with its own set of tradeoffs and compromises. We'll be exploring several of these in this lesson, but I encourage you to first pause and think about how you'd approach the problem.

Cookies

A simple way of keeping track of what's in a cart is to place that information in a cookie. To understand how cookies work, it's first important to understand how communication between the browser and your server occurs. When a user loads a page, they make an HTTP request to your server that looks like this:


GET /checkout
Accept: text/html
Host: northofboston-farm.vercel.app

The first line describes the operation the server must perform and all subsequent lines define headers included in the request. When a form is submitted, you can also change the GET to a POST by changing the method attribute of the form element. The words GET and POST are different verbs that can be sent to the server, there are others as well but those two are the most common.

A POST request also has to include the form data, also known as the payload. This is denoted in a request by adding information after a blank line. Let's say that a form has inputs named test1 and test2, then the request for that form submission would look like this:


POST /checkout
Accept: text/html
Host: northofboston-farm.vercel.app

test1=a&test2=b
    

The default method for a form submission is actually GET, when that occurs the payload is instead communicated in the location:


GET /checkout?test1=a&test2=b
Accept: text/html
Host: northofboston-farm.vercel.app
    

There are some security and technical constraints with using GET, so people typically prefer to use POST for form submission. The main situation where GET is useful is that URLs produced can be shared with others and bookmarked. So, for example, if you have some search result you want to share with a friend, the fact that the search was performed using GET means that when you send over that URL your friend will see the same thing.

When the server receives a request, it will produce a response that looks very similar:


HTTP/1.1 200 OK
Date:	Thu, 11 Apr 2024 23:21:44 GMT
Server: Vercel

<html>
  <head>
    <title>An Example Page</title>
  </head>
  <body>
    <p>Hello World, this is a very simple HTML document.</p>
  </body>
</html>
  

In this case you can think of the first line as a summary of the request. The part you'll be most interested in is the 200, which is the status code. If you haven't heard of them before, you've probably seen the most famous one: 404. Following that are again headers, and then a blank line and the payload.

How this relates to cookies is, if the response contains the header Set-Cookie, the value specified will be included in all subsequent requests. So the response would instead looks like this:


HTTP/1.1 200 OK
Date:	Thu, 11 Apr 2024 23:21:44 GMT
Server: Vercel
Set-Cookie: item_id=5

<html>
  <head>
    <title>An Example Page</title>
  </head>
  <body>
    <p>Hello World, this is a very simple HTML document.</p>
  </body>
</html>
  

Now, when the next request on your site is made, it will instead look like this:


GET /checkout
Accept: text/html
Host: northofboston-farm.vercel.app
Cookie: item_id=5

This cookie will be sent by the browser every time until you or the user clears it. SvelteKit provides some facilities for setting and viewing cookies, which you can read about here.

Even though it's technically possible to track specific information like item_id in cookies, including this information in every single request can be cumbersome. For that reason, often times instead a UUID is stored in the cookie and more extensive information is written into some form of storage like a database.

One thing to be cautious of with the use of cookies is the GDPR. This law is a complex topic and I'm by no means an expert, so I don't want to mislead you here. My basic understanding is that as long as you limit cookie usage to just what's necessary for the functionality you provide, you should be on the right side of that law. But if you plan to use cookies extensively you'll need to spend some time figuring out how to ensure compliance.

Storage API

A more modern approach to tracking information between requests is to use the Storage API. This allows you to use Javascript to store information on the users local machine, which allows more extensive navigation before needing to make the server aware of these choices. Fewer requests mean better performance and enhanced privacy, so this approach definitely has some appealing attributes.

Here's how you set and get values from local storage:


localStorage.setItem("lastname", "Smith");
localStorage.getItem("lastname");
    

In SvelteKit, you'll be tempted to write something along these lines in +page.svelte:


<script>
  const lastname = localStorage.getItem("lastname");
</script>

While this might seem to work at first, it's important to understand that the bare lines within a script tag have the chance to run before the page has had a chance to initialize. So facilities like localStorage may not yet have been created, to work around this you would need something more complicated like this:


<script>
  import { onMount } from 'svelte';
  let lastname = "";
  onMount(async () => {
    lastname = localStorage.getItem("lastname");
  });
</script>

This will load the page initially with lastname set to an empty string. As a result, you will also need to make sure your page looks reasonable until that value is loaded.

The localStorage facility will store information indefinitely, but sometimes you may only want this information to be stored until the user closes the window or tab. In this case you can use sessionStorage instead.

One major drawback of this approach is it only works if Javascript is enabled. It may seem like nobody would be running without Javascript these days, but it's still possible and something to keep in mind.