Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
docs(svelte-query): Rework SvelteKit setup (#4811)
* Add some default options

* Rewrite hydration example

* Run prettier

* Rename example to SSR

* Add recommended SvelteKit setup

* Rework infinite scroll in sveltekit

* Add SvelteKit note to overview

* Switch basic example to sveltekit

Co-authored-by: Dominik Dorfmeister <office@dorfmeister.cc>
  • Loading branch information
lachlancollins and TkDodo committed Jan 13, 2023
1 parent 3a3d871 commit 2cd92ef
Show file tree
Hide file tree
Showing 86 changed files with 498 additions and 514 deletions.
8 changes: 4 additions & 4 deletions docs/config.json
Expand Up @@ -720,6 +720,10 @@
"label": "Auto Refetching / Polling / Realtime",
"to": "svelte/examples/svelte/auto-refetching"
},
{
"label": "SSR",
"to": "svelte/examples/svelte/ssr"
},
{
"label": "Optimistic Updates in TypeScript",
"to": "svelte/examples/svelte/optimistic-updates-typescript"
Expand All @@ -735,10 +739,6 @@
{
"label": "Infinite Queries",
"to": "svelte/examples/svelte/load-more-infinite-scroll"
},
{
"label": "Hydration",
"to": "svelte/examples/svelte/hydration"
}
]
}
Expand Down
5 changes: 5 additions & 0 deletions docs/svelte/overview.md
Expand Up @@ -47,6 +47,10 @@ Then call any function (e.g. createQuery) from any component:
</div>
```

## SvelteKit

If you are using SvelteKit, please have a look at [SSR & SvelteKit](./ssr).

## Available Functions

Svelte Query offers useful functions and components that will make managing server state in Svelte apps easier.
Expand All @@ -67,3 +71,4 @@ Svelte Query offers useful functions and components that will make managing serv
Svelte Query offers an API similar to React Query, but there are some key differences to be mindful of.

- Many of the functions in Svelte Query return a Svelte store. To access values on these stores reactively, you need to prefix the store with a `$`. You can learn more about Svelte stores [here](https://svelte.dev/tutorial/writable-stores).
- If your query or mutation depends on variables, you must assign it reactively. You can read more about this [here](./reactivity).
42 changes: 34 additions & 8 deletions docs/svelte/ssr.md
Expand Up @@ -3,17 +3,39 @@ id: overview
title: SSR and SvelteKit
---

Svelte Query supports two ways of prefetching data on the server and passing that to the client with SvelteKit.
## Setup

## Caveat
SvelteKit defaults to rendering routes with SSR. Because of this, you need to disable the query on the server. Otherwise, your query will continue executing on the server asynchronously, even after the HTML has been sent to the client.

SvelteKit defaults to rendering routes with SSR. Unless you are using one of the below solutions, you need to disable the query on the server. Otherwise, your query will continue executing on the server asynchronously, even after the HTML has been sent to the client.
The recommended way to achieve this is to use the `browser` module from SvelteKit in your `QueryClient` object. This will not disable `queryClient.prefetchQuery()`, which is used in one of the solutions below.

One way to achieve this is to `import { browser } from '$app/environment'` and add `enabled: browser` to the options of `createQuery`. This will set the query to disabled on the server, but enabled on the client.
```markdown
<script lang="ts">
import { browser } from '$app/environment'
import { QueryClient } from '@tanstack/svelte-query'

const queryClient = new QueryClient({
defaultOptions: {
queries: {
enabled: browser,
},
},
})
</script>

Another way to achieve this is using page options. For that page or layout, you should set `export const ssr = false` in either `+page.ts` or `+layout.ts`. You can read more about using this option [here](https://kit.svelte.dev/docs/page-options#ssr).
<QueryClientProvider client={queryClient}>
<slot />
</QueryClientProvider>
```

## Using `initialData`
## Prefetching data

Svelte Query supports two ways of prefetching data on the server and passing that to the client with SvelteKit.

If you wish to view the ideal SSR setup, please have a look at the [SSR example](../examples/svelte/ssr).


### Using `initialData`

Together with SvelteKit's [`load`](https://kit.svelte.dev/docs/load), you can pass the data loaded server-side into `createQuery`'s' `initialData` option:

Expand Down Expand Up @@ -54,11 +76,12 @@ Cons:
- If you are calling `createQuery` with the same query in multiple locations, you need to pass `initialData` to all of them
- There is no way to know at what time the query was fetched on the server, so `dataUpdatedAt` and determining if the query needs refetching is based on when the page loaded instead

## Using `prefetchQuery`
### Using `prefetchQuery`

Svelte Query supports prefetching queries on the server. Using this setup below, you can fetch data and pass it into QueryClientProvider before it is sent to the user's browser. Therefore, this data is already available in the cache, and no initial fetch occurs client-side.

**src/routes/+layout.ts**

```ts
import { QueryClient } from '@tanstack/svelte-query'
import type { LayoutLoad } from './$types'
Expand All @@ -70,6 +93,7 @@ export const load: LayoutLoad = async () => {
```

**src/routes/+layout.svelte**

```markdown
<script lang="ts">
import { QueryClientProvider } from '@tanstack/svelte-query'
Expand All @@ -84,6 +108,7 @@ export const load: LayoutLoad = async () => {
```

**src/routes/+page.ts**

```ts
import type { PageLoad } from './$types'

Expand All @@ -97,6 +122,7 @@ export const load: PageLoad = async ({ parent }) => {
```

**src/routes/+page.svelte**

```markdown
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'
Expand All @@ -117,4 +143,4 @@ Pros:
Cons:

- Requires more files for initial setup
- Works with only `+page.ts`/`+layout.ts` load functions
- Will not work with `+page.server.ts`/`+layout.server.ts` load functions (however, APIs which are used with TanStack Query need to be fully exposed to the browser anyway)
8 changes: 4 additions & 4 deletions examples/svelte/auto-refetching/package.json
@@ -1,15 +1,16 @@
{
"name": "@tanstack/query-example-svelte-auto-refetching",
"version": "0.0.1",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json"
},
"dependencies": {
"@tanstack/svelte-query": "^4.12.0"
"@tanstack/svelte-query": "^4.20.0"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^1.0.0",
Expand All @@ -19,6 +20,5 @@
"tslib": "^2.4.1",
"typescript": "^4.7.4",
"vite": "^4.0.0"
},
"type": "module"
}
}
9 changes: 8 additions & 1 deletion examples/svelte/auto-refetching/src/routes/+layout.svelte
@@ -1,8 +1,15 @@
<script lang="ts">
import '../app.css'
import { browser } from '$app/environment'
import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query'
const queryClient = new QueryClient()
const queryClient = new QueryClient({
defaultOptions: {
queries: {
enabled: browser,
},
},
})
</script>

<QueryClientProvider client={queryClient}>
Expand Down
1 change: 0 additions & 1 deletion examples/svelte/auto-refetching/src/routes/+layout.ts

This file was deleted.

29 changes: 7 additions & 22 deletions examples/svelte/basic/.gitignore
@@ -1,24 +1,9 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

.DS_Store
node_modules
dist
dist-ssr
*.local
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
!lib/

# Editor directories and files
.vscode
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
58 changes: 24 additions & 34 deletions examples/svelte/basic/README.md
@@ -1,48 +1,38 @@
# Svelte + TS + Vite
# create-svelte

This template should help get you started developing with Svelte and TypeScript in Vite.
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).

## Recommended IDE Setup
## Creating a project

[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
If you're seeing this, you've probably already done this step. Congrats!

## Need an official Svelte framework?
```bash
# create a new project in the current directory
npm create svelte@latest

Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.

## Technical considerations

**Why use this over SvelteKit?**

- It brings its own routing solution which might not be preferable for some users.
- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
`vite dev` and `vite build` wouldn't work in a SvelteKit environment, for example.

This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.

Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.

**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
# create a new project in my-app
npm create svelte@latest my-app
```

Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
## Developing

**Why include `.vscode/extensions.json`?**
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:

Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
```bash
npm run dev

**Why enable `allowJs` in the TS template?**
# or start the server and open the app in a new browser tab
npm run dev -- --open
```

While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.
## Building

**Why is HMR not preserving my local component state?**
To create a production version of your app:

HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
```bash
npm run build
```

If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
You can preview the production build with `npm run preview`.

```ts
// store.ts
// An extremely simple external store
import { writable } from 'svelte/store'
export default writable(0)
```
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
13 changes: 0 additions & 13 deletions examples/svelte/basic/index.html

This file was deleted.

12 changes: 6 additions & 6 deletions examples/svelte/basic/package.json
@@ -1,20 +1,20 @@
{
"name": "@tanstack/query-example-svelte-basic",
"private": true,
"version": "0.0.0",
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json"
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json"
},
"dependencies": {
"@tanstack/svelte-query": "^4.12.0"
"@tanstack/svelte-query": "^4.20.0"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^2.0.2",
"@tsconfig/svelte": "^3.0.0",
"@sveltejs/adapter-auto": "^1.0.0",
"@sveltejs/kit": "^1.0.0",
"svelte": "^3.54.0",
"svelte-check": "^2.9.2",
"tslib": "^2.4.1",
Expand Down
13 changes: 0 additions & 13 deletions examples/svelte/basic/src/App.svelte

This file was deleted.

12 changes: 6 additions & 6 deletions examples/svelte/basic/src/app.css
Expand Up @@ -41,14 +41,14 @@ h1 {
padding: 2em;
}

#app {
main {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

button {
.button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
Expand All @@ -59,11 +59,11 @@ button {
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
.button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
.button:focus,
.button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}

Expand All @@ -75,7 +75,7 @@ button:focus-visible {
a:hover {
color: #747bff;
}
button {
.button {
background-color: #f9f9f9;
}
}
File renamed without changes.
File renamed without changes.
1 change: 0 additions & 1 deletion examples/svelte/basic/src/assets/svelte.svg

This file was deleted.

15 changes: 0 additions & 15 deletions examples/svelte/basic/src/lib/BasicQuery.svelte

This file was deleted.

0 comments on commit 2cd92ef

Please sign in to comment.