Svelte journey | SvelteKit: Page options, Link Options, Environment variables
Tags: javascript, tutorial, frontend, svelte
Published: 2024-01-13 09:23:46


Welcome,

In this article, we will focus on how to fine-tune preloading and prerendering functionalities, as well as effectively manage environment variables in **SvelteKit**.

If you’ve been following the series from the beginning, congratulations — you've put in great effort, and this marks the final installment of the series! If not, I would strongly recommend taking a glance through the previous articles; you may still find something interesting.

So, let’s get started.

## Page Options

This section explores the fine-tuning of preloading, prerendering, and other functionalities in SvelteKit. It details how to export options and discusses specific page options, such as disabling SSR, client-side rendering, and defining trailing slashes.

- Options can be exported from `+page.js`, `+page.server.js`, `+layout.js`, and `+layout.server.js`, but it actually works when exports happen from `+<type>.server.js`:
    - E.g., `export const ssr = false`;
    - Page options can be applied for an individual page or layout;
    - To apply globally, export options from the root layout;
    - More nested definitions override inherited ones.

We can export the following options:

- `ssr` — to disable SSR;
    - If you define `export const ssr = false;` in a non-server file, it may not make much sense. When defined in a plain page or layout, it may not be helpful in case of interaction with browser-related API. For example, when you load an app from `/` and navigate to `/bar` which uses the `window` object, it would work. But if you then reload the browser tab on `/bar`, you get a 500 Error, `window` is undefined, and an error would be thrown;
    - `ssr = false` in `src/routes/+layout.server.js` transforms the entire app into a SPA.
    
    ```jsx
    // bar/+page.svelte
    <script>
        export const ssr = false; // will really make a difference in +page.server.js. Here it may be useless
    </script>
    <h1>{window.innerWidth}x{window.innerHeight}</h1>
    
    ```
    
- `csr` — to disable client-side rendering (no JS is served to the client);
    - Same story as with `ssr` and not `server` suffixed files;
- `prerender` — prepare HTML for a page only once, not dynamically for each request (build static HTML on the build step). `false` by default;
    - `ssr = false` in `src/routes/+layout.server.js` transforms the entire app into a [SSG](https://www.cloudflare.com/en-gb/learning/performance/static-site-generator/);
    - Can be [configured](https://kit.svelte.dev/docs/configuration#prerender);
- `trailingSlash` — we have two URLs: `/foo` and `/foo/`. We have a relative URL `./bar`. For `/foo`, it would be `/bar`, for `/foo/`, it would be `/foo/bar`.
    - By default, SvelteKit strips trailing slashes out, so `/foo/` will result in a redirect to `/foo`;
    - `export const trailingSlash = 'always' | 'ignore' | 'never'` — never is by default, better leave as is;
    - Trailing slashes are applied affects pre-rendering. A URL like `/always/` will be saved to disk as `always/index.html` whereas a URL like `/never` will be saved as `never.html`.

## Link (Route) Options

Delving into the tuning of page loading accessible by links, this section covers various attributes for preloading tuning.

- Implemented as attributes;
- Cascade application (if applied on some parent → will be applied for all anchor children;
- To prevent cascade behavior, you can set the attribute to false in a required place, e.g.:

```jsx
<div data-sveltekit-preload-data>
	<a href="/a">a</a>
	<div data-sveltekit-preload-data="false">
		<a href="/b">b</a>
	</div>
</div>

```

### Preloading

“Anticipate” that the link would be used → starts to fetch the resource behind the link when the anchor is hovered (or tapped on mobile). Need to add `data-sveltekit-preload-data` attribute.

- Attribute’s values can have values: `"hover"` (default) | `"tap"` (default for mobile) | `"off"`;
- Can be placed on `<a />` or **any element** whose has `<a />` as a child;
- `<body data-sveltekit-preload-data>` is by default in the generated project;

```jsx
<nav>
	<a href="/">home</a>
	<a href="/chart" data-sveltekit-preload-data>Chart</a>
</nav>

```

Alternative attribute: `data-sveltekit-preload-code` — preloads code for the route without loading its data. Possible values:

- `"eager"` — preload everything on the page following navigation;
- `"viewport"` — preload everything as it appears in the viewport;
- `"hover" | "tap" | "off"` — same as for `data-sveltekit-preload-data`.

### Programmatic Preload

The same purpose but can be done in pages and layouts:

```jsx
import { preloadCode, preloadData } from '$app/navigation';
preloadData('/foo');
preloadCode('/bar');

```

### Other Options

- `data-sveltekit-noscroll` — do not scroll to the top on navigation;
- `data-sveltekit-keepfocus` — do not reset focus on navigation;
- `data-sveltekit-replacestate` — replace the browser’s history instead of pushing one more step;
- `data-sveltekit-reload` — full-page reload (or it can be `rel="external”` attribute on an anchor)

## Environment Variables Access — `$env` Module

Variables should be defined in a `.env` file, in the root folder.

### Private Variables

- `.env.[mode]` files are also supported according to [Vite documentation](https://vitejs.dev/guide/env-and-mode.html#env-files);
- In an app, variables are accessible via `$env/static/private`;
- Variables from `process.env` are also available from `$env/static/private`;
- Env. variables only accessible in *server* modules:
    - Any `+page.server.js | +layout.server.js | +server.js,` any files ending with `server.js`;
    - Any files inside `src/lib/server`;

### Static vs Dynamic

Previously mentioned `$env/static/private` — these variables are known at a build time — it helps Svelte to optimize the code, so `static` are more preferable.

- Dynamic ones are not known until the app is running. It means no optimizations from Svelte’s side;
- From the dev’s perspective, you just need to use `$env/dynamic/private` import instead of `static` one;
- Dynamic variables are accessible via `env` object:

```jsx
import { env } from '$env/dynamic/private';
// env.API_TOKEN

```

### Public Variables

The variables that can be safely exposed to the client side.

- Their naming must start from `PUBLIC_` prefix, e.g., `PUBLIC_MAPBOX_KEY` ;
- Import them through `$env/static/public` or `$env/dynamic/public`:

```jsx
import { PUBLIC_MAPBOX_KEY } from '$env/static/public';
import { env } from '$env/dynamic/public';

```

## Final words

We've concluded our journey through this impressive toolkit crafted by the Svelte team, known for its exceptional developer experience and user-centric design. While we've covered substantial ground, there's still a wealth of features to discover. I trust this exploration has sparked your interest to delve deeper into the possibilities it offers.

It's a well-designed tool that should bring joy to both creators and consumers — a goal definitely achieved by the Svelte team.

If you want to join the community, there is a Discord server at [svelte.dev/chat](https://svelte.dev/chat) and Reddit's [r/sveltejs](https://www.reddit.com/r/sveltejs).

I hope you've enjoyed this Svelte journey and have gained a general understanding of what the Svelte toolkit is all about.

Take care, go Svelte.

## Resources

- [SvelteKit Docs | Page options](https://kit.svelte.dev/docs/page-options)
- [SvelteKit Docs | Env. variables](https://kit.svelte.dev/docs/modules#$env-dynamic-private)