v0.11.0 Release Notes

Sessions and Cookies

This release introduces first-class support for sessions and cookies at the route level instead of piggy-backing on framework middleware like express-session.

Background

We initially thought we could just build out our sessions API on top of existing frameworks and cloud providers. After all, why reinvent something that is already working well for people? One of the core goals of Remix is to play well with your existing stack and technologies that you already know and love.

However, we quickly discovered that not all cloud providers support session management. To some of them it's a detail that's best left up to the app developer. That's a fair position, but it means that in order to provide a consistent experience in Remix when it comes to handling sessions, we had a bit of work to do.

Another reason we weren't comfortable with this approach is that in many node server frameworks, sessions rely on using middleware. To use sessions in Express, you insert some middleware into your stack in one spot and it runs for multiple different request handlers.

While there's nothing inherently bad about this model, our goal with Remix is to push all functionality for handling a request into your route loader and action functions. This means each one will have a bit more work to do, but it also means it's completely isolated from other request handlers in your app, which is closer to the lambda model. Our hope is that by enforcing an architecture that completely encapsulates the request/response cycle at the route level it will be easier to eventually deploy Remix loaders and actions to individual cloud functions, if desired.

That being said, remember your escape hatch is always getLoadContext. So if you really want to use something from your cloud provider or framework (like an Express middleware) and get it through to your loaders/actions, we completely support that.

Session storage

The major new API in this release is the SessionStorage interface. A session storage object is responsible for parsing/serializing HTTP cookies and managing persistence of session data between requests.

SessionStorage has three methods:

  • getSession - Returns the Session object associated with a HTTP cookie, or a new session if there was no Cookie header
  • commitSession - Saves session data to storage and returns the value to use for the response's Set-Cookie header
  • destroySession - Like commitSession, but destroys all session data instead of saving it

Remix provides three built-in session storage options:

  • createFileSessionStorage() - Stores session data on the filesystem, ala PHP
  • createCookieSessionStorage() - Stores session data in the session cookie itself. This is useful when you don't have a filesystem or don't want to use a database for some reason.
  • createMemorySessionStorage() - A lightweight development/testing-only session storage for testing your session-based user flows

The docs on sessions contain a comprehensive example of how you might build a simple user authentication form using the new API.

The docs also include an example of building a custom session storage using the new createSessionStorage() API, which is designed to let you build a session storage solution backed by any database you want.

Cookies

Of course, a core component behind sessions is the ability to handle HTTP cookies. Remix v0.11 also includes a Cookie interface and createCookie() function that help when dealing with cookies generally.

The idea behind the Cookie API is that you create reusable cookie objects that know how to parse and serialize cookies, complete with support for rotating secrets used for signing cookies to verify their integrity (important when it's a session cookie).

Changes to server endpoints

This is mostly an internal change, but in order to make cookies work better in your loaders and actions, we've made a few subtle changes to the server endpoints. Specifically, the /_remix/data endpoint is now just the regular route endpoint with a ?_data parameter in the query string. This means when you set a path on your cookies to the path of one of your routes, you'll get that cookie in your loader/action as well.

The /_remix/manifest endpoint also changed to the same as the route endpoint, but with a ?_manifest parameter in the URL query string. This is for consistency with the data endpoint, but may also prove helpful in the future for specifying additional security around the manifest endpoint.

In addition to these usability benefits, it tends to clean up the Network tab quite a bit as well :D

Upgrading

Upgrading to v0.10 should be zero work if you weren't using sessions. If you were, take the following steps:

  • Create your own session storage object in app/sessionStorage.ts (or app/sessionStorage.js if you're using JavaScript)
  • Remove the session argument in your loader and action functions and use the getSession and commitSession functions from your session storage object instead
  • For @remix-run/express - Remove your express session middleware since we're not using it anymore

And that should be just about it. Please let us know if you encounter any issues upgrading.

As always, thank you for your support!