Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs markdown content #377

Merged
merged 1 commit into from
Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions documentation/docs/00-introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: Introduction
---

### Before we begin

> SvelteKit is in early development, and some things may change before we hit version 1.0. This document is a work-in-progress. If you get stuck, reach out for help in the [Discord chatroom](https://svelte.dev/chat).
>
> See the [migration guides](migrating) for help upgrading from older versions.

### What is SvelteKit?

SvelteKit is a framework for building extremely high-performance web apps. You're looking at one right now! There are two basic concepts:

* Each page of your app is a [Svelte](https://svelte.dev) component
* You create pages by adding files to the `src/routes` directory of your project. These will be server-rendered so that a user's first visit to your app is as fast as possible, then a client-side app takes over

Building an app with all the modern best practices — code-splitting, offline support, server-rendered views with client-side hydration — is fiendishly complicated. SvelteKit does all the boring stuff for you so that you can get on with the creative part.

You don't need to know Svelte to understand the rest of this guide, but it will help. In short, it's a UI framework that compiles your components to highly optimized vanilla JavaScript. Read the [introductory blog post](https://svelte.dev/blog/svelte-3-rethinking-reactivity) and the [tutorial](https://svelte.dev/tutorial) to learn more.


### Why the name?

SvelteKit is meant to be a full kit of everything necessary to build a Svelte application.


### Comparison with Next.js

[Next.js](https://github.com/zeit/next.js) is a React framework from [Vercel (formerly ZEIT)](https://vercel.com), and is the inspiration for SvelteKit. There are a few notable differences, however:

* SvelteKit is powered by Svelte instead of React, so it's faster and your apps are smaller
* As well as *pages*, you can create *server routes* in your `src/routes` directory. This makes it very easy to, for example, add a JSON API such as the one powering this very page (try visiting [/docs.json](/docs.json))
* Links are just `<a>` elements, rather than framework-specific `<Link>` components. That means, for example, that [this link right here](/), despite being inside a blob of markdown, works with the router as you'd expect


### Getting started

The easiest way to start building a SvelteKit app is to run `npm init`:

```bash
mkdir my-app
cd my-app
npm init svelte@next
npm install
npm run dev
```

This will scaffold a new project in the `my-app` directory, install its dependencies, and start a server on [localhost:3000](http://localhost:3000). Try editing the files to get a feel for how everything works – you may not need to bother reading the rest of this guide!
86 changes: 86 additions & 0 deletions documentation/docs/01-structure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
title: SvelteKit app structure
---

If you take a look inside a new SvelteKit project, you'll see some files that SvelteKit expects to find:

```bash
├ package.json
├ src
│ ├ routes
│ │ └ index.svelte
│ ├ components
│ │ └ Counter.svelte
│ ├ service-worker.js
│ └ app.html
├ static
│ ├ # your files here
└ snowpack.config.js
└ svelte.config.js
```

### package.json

Your package.json contains your app's dependencies and defines a number of scripts:

* `npm run dev` — start the app in development mode, and watch source files for changes
* `npm run build` — build the app in production mode
* `npm start` — start the app in production mode after you've built it


### src

This contains the *home page* for your app — `src/index.svelte` and (optionally) `src/service-worker.js` — along with a `src/app.html` file.


#### src/routes/index.svelte

This is the home page for your application and is just like any other Svelte component.


#### src/service-worker.js

Service workers act as proxy servers that give you fine-grained control over how to respond to network requests. For example, when the browser requests `/goats.jpg`, the service worker can respond with a file it previously cached, or it can pass the request on to the server, or it could even respond with something completely different, such as a picture of llamas.

Among other things, this makes it possible to build applications that work offline.

Because every app needs a slightly different service worker (sometimes it's appropriate to always serve from the cache, sometimes that should only be a last resort in case of no connectivity), Sapper doesn't attempt to control the service worker. Instead, you write the logic in `service-worker.js`. You can import any of the following from `@sapper/service-worker`:

* `files` — an array of files found in the `static` directory
* `shell` — the client-side JavaScript generated by the bundler (Rollup or webpack)
* `routes` — an array of `{ pattern: RegExp }` objects you can use to determine whether a Sapper-controlled page is being requested
* `timestamp` — the time the service worker was generated (useful for generating unique cache names)


#### src/app.html

This file is a template for responses from the server. Sapper will inject content that replaces the following tags:

* `%svelte.base%` — a `<base>` element (see [base URLs](docs#Base_URLs))
* `%svelte.styles%` — critical CSS for the page being requested
* `%svelte.head%` — HTML representing page-specific `<head>` contents, like `<title>`
* `%svelte.html%` — HTML representing the body of the page being rendered
* `%svelte.scripts%` — script tags for the client-side app
* `%svelte.cspnonce%` — CSP nonce taken from `res.locals.nonce` (see [Content Security Policy (CSP)](docs#Content_Security_Policy_CSP))


### src/routes

This is the meat of your app — the pages and server routes. See the section on [routing](docs#Routing) for the juicy details.


### static

This is a place to put any files that your app uses — fonts, images and so on. For example `static/favicon.png` will be served as `/favicon.png`.

Sapper doesn't serve these files — you'd typically use [sirv](https://github.com/lukeed/sirv) or [serve-static](https://github.com/expressjs/serve-static) for that — but it will read the contents of the `static` folder so that you can easily generate a cache manifest for offline support (see [service-worker.js](docs#src_service-worker_js)).

> Note that the default behaviour of the service worker is to cache all assets from the static directory, so if you have more than 50mb of files here, you will start to exceed the cache limit for service-workers in some browsers, which can cause the service worker to stop loading. In this instance, it is advisable to customise what files are cached by editing the service-worker yourself.

### snowpack.config.js

This is the [Snowpack configuration file](https://www.snowpack.dev/reference/configuration) for your project.

### svelte.config.js

This file contains SvelteKit options as well as options for `svelte-preprocess`.
143 changes: 143 additions & 0 deletions documentation/docs/02-routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
title: Routing
---

As we've seen, there are two types of route in SvelteKit — pages and API endpoints.


### Pages

Pages are Svelte components written in `.svelte` files. When a user first visits the application, they will be served a server-rendered version of the route in question, plus some JavaScript that 'hydrates' the page and initialises a client-side router. From that point forward, navigating to other pages is handled entirely on the client for a fast, app-like feel.

The filename determines the route. For example, `src/routes/index.svelte` is the root of your site:

```html
<!-- src/routes/index.svelte -->
<svelte:head>
<title>Welcome</title>
</svelte:head>

<h1>Hello and welcome to my site!</h1>
```

A file called either `src/routes/about.svelte` or `src/routes/about/index.svelte` would correspond to the `/about` route:

```html
<!-- src/routes/about.svelte -->
<svelte:head>
<title>About</title>
</svelte:head>

<h1>About this site</h1>
<p>TODO...</p>
```

Dynamic parameters are encoded using `[brackets]`. For example, here's how you could create a page that renders a blog post:

```html
<!-- src/routes/blog/[slug].svelte -->
<script context="module">
import * as api from '$common/api.js';

// the (optional) load function takes a
// `{ page, session }` object and turns it into
// the data we need to render the page
export async function load({ page, session }) {
// the `slug` parameter is available because this file
// is called [slug].svelte
const { slug } = page.params;

// `api.get` is a wrapper around `fetch` that allows
// you to make credentialled requests on both
// server and client
const res = await api.get(`blog/${slug}.json`);
const article = await res.json();

return { { props: article } };
}
</script>

<script>
export let article;
</script>

<svelte:head>
<title>{article.title}</title>
</svelte:head>

<h1>{article.title}</h1>

<div class='content'>
{@html article.html}
</div>
```

If you want to capture more params, you can create nested folders using the same naming convention: `[slug]/[language]`.

If you don't want to create several folders to capture more than one parameter like `[year]/[month]/...`, or if the number of parameters is dynamic, you can use a spread route parameter. For example, instead of individually capturing `/blog/[slug]/[year]/[month]/[day]`, you can create a file for `/blog/[...slug].svelte` and extract the params like so:

```html
<!-- src/routes/blog/[...slug].svelte -->
<script context="module">
export async function load({ page }) {
let [slug, year, month, day] = page.params.slug;

return { props: { slug, year, month, day }};
}
</script>
```


> See the section on [loading](docs#Loading) for more info about `load` and `this.fetch`


### Server routes

Server routes are modules written in `.js` files that export functions corresponding to HTTP methods. Each function receives HTTP `request` and `response` objects as arguments, plus a `next` function. This is useful for creating a JSON API. For example, here's how you could create an endpoint that served the blog page above:

```js
// routes/blog/[slug].json.js
import db from './_database.js'; // the underscore tells SvelteKit this isn't a route

export async function get(req, res, next) {
// the `slug` parameter is available because this file
// is called [slug].json.js
const { slug } = req.params;

const article = await db.get(slug);

if (article !== null) {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(article));
} else {
next();
}
}
```

> `delete` is a reserved word in JavaScript. To handle DELETE requests, export a function called `del` instead.


### File naming rules

There are three simple rules for naming the files that define your routes:

* A file called `src/routes/about.svelte` corresponds to the `/about` route. A file called `src/routes/blog/[slug].svelte` corresponds to the `/blog/:slug` route, in which case `params.slug` is available to `load`
* The file `src/routes/index.svelte` corresponds to the root of your app. `src/routes/about/index.svelte` is treated the same as `src/routes/about.svelte`.
* Files and directories with a leading underscore do *not* create routes. This allows you to colocate helper modules and components with the routes that depend on them — for example you could have a file called `src/routes/_helpers/datetime.js` and it would *not* create a `/_helpers/datetime` route


### Error page

In addition to regular pages, there is a 'special' page that SvelteKit expects to find — `src/routes/$error.svelte`. This will be shown when an error occurs while rendering a page.

The `error` object is made available to the template along with the HTTP `status` code. `error` is also available in the [`page` store](docs#Stores).


### Regexes in routes

You can use a subset of regular expressions to qualify route parameters, by placing them in parentheses after the parameter name.

For example, `src/routes/items/[id([0-9]+)].svelte` would only match numeric IDs — `/items/123` would match and make the value `123` available in `page.params.id`, but `/items/xyz` would not match.

Because of technical limitations, the following characters cannot be used: `/`, `\`, `?`, `:`, `(` and `)`.
67 changes: 67 additions & 0 deletions documentation/docs/03-client-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
title: Client API
---

The `$app/navigation` and `$app/stores` modules contain functions for controlling SvelteKit programmatically and responding to events.


### start({ target })

* `target` — an element to render pages to

This configures the router and starts the application — listens for clicks on `<a>` elements, interacts with the `history` API, and renders and updates your Svelte components.

Returns a `Promise` that resolves when the initial page has been hydrated.

```js
import * as sapper from '@sapper/app';

sapper.start({
target: document.querySelector('#sapper')
}).then(() => {
console.log('client-side app has started');
});
```


### goto(href, options?)

* `href` — the page to go to
* `options` — not required
* `replaceState` (`boolean`, default `false`) — determines whether to use `history.pushState` (the default) or `history.replaceState`.
* `noscroll` (`boolean`, default `false`) — prevent scroll to top after navigation.

Programmatically navigates to the given `href`. If the destination is a Sapper route, Sapper will handle the navigation, otherwise the page will be reloaded with the new `href`. In other words, the behaviour is as though the user clicked on a link with this `href`.

Returns a `Promise` that resolves when the navigation is complete. This can be used to perform actions once the navigation has completed, such as updating a database, store, etc.

```js
import { goto } from '@sapper/app';

const navigateAndSave = async () => {
await goto('/');
saveItem();
}

const saveItem = () => {
// do something with the database
}
```


### prefetch(href)

* `href` — the page to prefetch

Programmatically prefetches the given page, which means a) ensuring that the code for the page is loaded, and b) calling the page's `preload` method with the appropriate options. This is the same behaviour that Sapper triggers when the user taps or mouses over an `<a>` element with [rel=prefetch](docs#rel_prefetch).

Returns a `Promise` that resolves when the prefetch is complete.


### prefetchRoutes(routes?)

* `routes` — an optional array of strings representing routes to prefetch

Programmatically prefetches the code for routes that haven't yet been fetched. Typically, you might call this after `sapper.start()` is complete, to speed up subsequent navigation (this is the 'L' of the [PRPL pattern](https://developers.google.com/web/fundamentals/performance/prpl-pattern/)). Omitting arguments will cause all routes to be fetched, or you can specify routes by any matching pathname such as `/about` (to match `src/routes/about.svelte`) or `/blog/*` (to match `src/routes/blog/[slug].svelte`). Unlike `prefetch`, this won't call `preload` for individual pages.

Returns a `Promise` that resolves when the routes have been prefetched.
Loading