Я работаю над приложением SvelteKit, в котором мне нужно получить список данных сообщений и избежать избыточных вызовов API.
Маршрут: all-posts/+page.svelte
fetchAllPostsData()
Маршрут: post/[id]/[title]/+page.svelte
fetchPostDataById(id)
Текущая реализация приводит к вызову fetchAllPostsData()
, а затем повторному вызову fetchPostDataById(id)
, что неэффективно. Вот соответствующий код:
all-posts/+page.svelte
:
<script>
import { onMount } from 'svelte';
import { fetchAllPostsData } from './fetch-post-data';
let postsDataArr = [];
onMount(async () => {
postsDataArr = await fetchAllPostsData();
});
</script>
<section>
<ul>
{#each postsDataArr as post}
<li><a href = {`/post/${post.id}/${post.title.replace(/[\s ]/g, '-')}`}>{post.title}</a></li>
{/each}
</ul>
</section>
post/[id]/[title]/+page.svelte
:
<script>
import { onMount } from 'svelte';
import { page } from '$app/stores';
import { fetchPostDataById } from '../fetch-post-data';
let id;
/**
* @type {any}
*/
let data;
$: id = $page.params.id;
onMount(async () => {
data = await fetchPostDataById(id);
});
</script>
<section>
{#if data}
<div>
<div>{@html data.html}</div>
</div>
{/if}
</section>
Дополнительный контекст:
Я не хочу полностью удалять функцию fetchPostDataById(id)
, так как это важно в тех случаях, когда пользователи делятся прямой ссылкой на публикацию. В таких сценариях ссылка на публикацию должна получать данные публикации по идентификатору, чтобы гарантировать отображение правильных данных, даже если пользователь обращается к публикации напрямую через URL-адрес.
Вопрос:
Как я могу реорганизовать свой код, чтобы избежать повторного вызова API? Я хочу получить список сообщений один раз и использовать эти данные в обоих маршрутах без избыточной выборки.
Теперь я использую TanStack Query в Svelte вместо того, чтобы каждый раз напрямую вызывать API. Подробнее читайте в официальном документе
<script lang = "ts">
import { createQuery } from '@tanstack/svelte-query';
// Define the options for the fetch request
const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({"limit":100})
};
// Fetch function to get paginated posts
const fetchPaginatedPosts = async () => {
try {
const response = await fetch('http://localhost:4000/get-paginated-posts', options);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const res = await response.json()
console.info(res)
/*
res = {
"posts": [
{
"id": "667776bcc5d22d6226f7647b",
"description": "Hello, this is me!",
"title": "My page is here!",
"update_count": 0,
"updated_at": "2024-06-23T10:13:32.190+00:00"
"created_at": "2024-06-23T10:13:32.190+00:00",
"created_by": "666ff11d406248baf2e87df4",
} ,{...}
],
"nextToken": "667776bcc5d22d6226f7647b"
}
*/
return res;
} catch (error) {
console.error(error);
throw error;
}
};
// Create the query
const query = createQuery({
queryKey: ['posts'],
queryFn: fetchPaginatedPosts,
initialData: null,
});
// Access and log the posts data
const result = $query.data
console.info({result})
</script>
<!--html omitted-->
🤔 А знаете ли вы, что...
Svelte обеспечивает хорошую поддержку серверного рендеринга для SEO-оптимизации.
Это немного сложнее, чем можно было подумать на первый взгляд. Чтобы оптимизировать получение данных, вам следует не только избегать дублирующих/ненужных запросов (цель вашего вопроса), но и избегать предоставления устаревших данных вашим пользователям. Короче говоря, вам нужно реализовать эффективный механизм кэширования данных ваших публикаций.
Хотя вы можете создать такой механизм вручную, используя хранилища Svelte, временные метки и т. д., Tanstack, создатели react-query
, выпустили библиотеку запросов и кэширования для Svelte, которая будет обрабатывать сложные детали запуска эффективного кэширования за вас и сделать вашу жизнь намного проще.
Tanstack также опубликовал несколько примеров использования, которые могут оказаться очень полезными при реализации вашего собственного варианта использования.
Если вы по-прежнему предпочитаете идти по ручному маршруту, я думаю этот другой ТАК-ответ может оказаться хорошей отправной точкой.
Надеюсь, вы найдете это полезным. Удачи!