SvelteKitのそれぞれのload関数で値を返したときの挙動まとめ

# はじめに
SvelteKitでは、`+layout.ts`、`+layout.server.ts`、`+page.ts`、`+page.server.ts`ファイル内でそれぞれ`load`関数を呼び出して値を返すことができます。しかし、同じキーの値を返した場合や、`+page.ts`と`+page.server.ts`でそれぞれ値を返す場合にどうなるかなど、少し分かりづらい点がありますので、ここでまとめて説明します。

# 動作確認環境
- SvelteKit: 2.5.17
- svelte: 4.2.18

# 実行される順序

+layout.server.ts 
  (サーバー側のレイアウトデータ)
  ↓
+layout.ts 
  (クライアント側のレイアウトデータ)
  ↓
+page.server.ts 
  (サーバー側のページデータ)
  ↓
+page.ts 
  (クライアント側のページデータ)


# +layout.tsと+page.tsの例
:::note info
+layout.server.ts, +page.server.tsの組み合わせでも同様の結果です。
:::

## キーが被っていない場合

```ts:+layout.ts
export const load = async () => {	
  return {		
    a: 1, 
    b: 2
  };
};
```


```ts:+page.ts
export const load = async () => {	
  return {		
    c: 3, 
    d: 4
  };
};
```

```json:結果
{
  "a": 1,
  "b": 2,
  "c": 3,
  "d": 4
}
```

`+layout.ts`と`+page.ts`で返した値がマージされて返されます。

## 同じキーが含まれる場合

```ts:+layout.ts
export const load = async () => {	
  return {		
    a: 1, 
    b: 2
  };
};
```


```ts:+page.ts
export const load = async () => {	
  return {		
    b: 3,
    c: 4
  };
};
```

```json:結果
{
  "a": 1,
  "b": 3,
  "c": 4
}
```

`+layout.ts`で返された`b: 2`は`+page.ts`で返された`b: 3`に上書きされ、最終的な結果として返されます。SvelteKitでは、同じキーが存在する場合、後に実行されたファイルの値が優先されます。

# +page.tsと+page.server.tsの例
:::note info
+layout.tsと+layout.server.tsの組み合わせでも同様の動作となります。
:::
## キーが被っていない場合

```ts:+page.server.ts
export const load = async () => {	
  return {		
    a: 1, 
    b: 2
  };
};
```


```ts:+page.ts
export const load = async () => {	
  return {		
    c: 3, 
    d: 4
  };
};
```

```json:結果
{
  "c": 3, 
  "d": 4
}
```

`+page.server.ts`と`+page.ts`が別々のキーの値を返しても、+page.tsで返した値のみが最終結果として返されます。両方の値を返すには以下のように記述する必要があります。

```ts:+page.server.ts
export const load = async () => {	
  return {		
    a: 1, 
    b: 2
  };
};
```


```ts:+page.ts
export const load = async ({ data }) => {	
  return {
    ...data,		
    c: 3,
    d: 4
  };
};
```

または

```ts:+page.ts
export const load = async ({ data }) => {	
  return {
    a: data.a,
    b: data.b,
    c: 3,
    d: 4
  };
};
```

```json:結果
{
  "a": 1, 
  "b": 2, 
  "c": 3, 
  "d": 4
}
```
`+page.ts`のdataには`+page.server.ts`で返された値が含まれているため、それをマージして返すことで、すべての値が最終結果として返されます。

```ts:+page.server.ts
export const load = async () => {	
  return {		
    a: 1, 
    b: 2
  };
};
```


```ts:+page.ts
export const load = async ({ data }) => {	
  return {
    ...data,		
      b: 3,
      c: 4
  };
};
```

```json:結果
{
  "a": 1,
  "b": 3,
  "c": 4
}
```

ここでは単純にオブジェクトをスプレッド構文でマージしているため、元のオブジェクトに同じキーが存在する場合は、後の値で上書きされます。

# +layout.ts、+layout.server.ts、+page.ts、+page.server.tsの例
## キーが被っていない場合

```ts:+layout.server.ts
export const load = async () => {	
  return {		
    a: 1, 
    b: 2
  };
};
```

```ts:+layout.ts
export const load = async () => {	
  return {
    c: 3,
    d: 4
  };
};
```

```ts:+page.server.ts
export const load = async () => {	
  return {
    e: 5,
    f: 6
  };
};
```

```ts:+page.ts
export const load = async () => {	
  return {	
    g: 7,
    h: 8
  };
};
```

```json:結果
{
  "c": 3, 
  "d": 4, 
  "g": 7, 
  "h": 8
}
```

他の結果と同様に、`+page.server.ts`や`+layout.server.ts`で返された値を`+page.ts`や`+layout.ts`で利用するためには、手動でデータをマージする必要があります。

```ts:+layout.server.ts
export const load = async () => {	
  return {		
    a: 1, 
    b: 2
  };
};
```

```ts:+layout.ts
export const load = async ({ data }) => {	
  return {
    ...data,
    c: 3,
    d: 4
  };
};
```

```ts:+page.server.ts
export const load = async () => {	
  return {
    e: 5,
    f: 6
  };
};
```

```ts:+page.ts
export const load = async ({ data }) => {	
  return {	
    ...data,
    g: 7,
    h: 8
  };
};
```

```json:結果
{
  "a": 1,
  "b": 2,
  "c": 3,
  "d": 4, 
  "e": 5,
  "f": 6,
  "g": 7,
  "h": 8
}
```

すべての値が最終結果として返されました。

## 同じキーが含まれる場合

```ts:+layout.server.ts
export const load = async () => {	
  return {		
    a: 1, 
    b: 2
  };
};
```

```ts:+layout.ts
export const load = async ({ data }) => {	
  return {
    ...data,
    b: 3,
    c: 4
  };
};
```

```ts:+page.server.ts
export const load = async () => {	
  return {
    c: 5,
    d: 6
  };
};
```

```ts:+page.ts
export const load = async ({ data }) => {	
  return {	
    ...data,
    d: 7,
    e: 8
  };
};
```

```json:結果
{
  "a": 1,
  "b": 3,
  "c": 5,
  "d": 7,
  "e": 8
}
```

スプレッド構文使用時、同じキーが存在する場合は最後に実行されたファイルでの値が最終結果として返されます。

# まとめ

## 実行順序
- `+layout.server.ts` → `+layout.ts` → `+page.server.ts` → `+page.ts` の順に実行されます
- サーバー側でデータを取得するファイルが先に実行され、その後クライアント側のファイルが実行されます

## 値のマージ
- `+layout.ts` と `+page.ts`、または `+layout.server.ts` と `+page.server.ts` の組み合わせでは、同名のキーを持たない値はマージされます
- 同名のキーがある場合、後から定義されたファイルでの値が優先されます（上書きされます）

## データの受け渡し
- `+page.server.ts` などで返したデータを `+page.ts` でも利用したい場合、`data` オブジェクトを使用してスプレッド構文などでマージする必要があります

## キーが被る場合のオブジェクトマージ
- 同名のキーを持つ場合、スプレッド構文でのマージにより、最後に実行されたファイルでの値が最終的に返されます