Como Fazer Lazy Load de Componentes no Svelte
Sua aplicação Svelte pode ser rápida por padrão, mas se você está incluindo um editor de rich text, uma biblioteca de gráficos ou um widget complexo de dashboard no payload inicial de JavaScript, os usuários estão baixando código que talvez nunca usem. O lazy loading em nível de componente no Svelte resolve isso adiando essas importações pesadas até que sejam realmente necessárias.
Diferentemente do React, o Svelte não possui um helper lazy() integrado. Em vez disso, o lazy loading depende diretamente da função nativa import() do JavaScript combinada com renderização condicional. É mais manual, mas também é mais flexível.
Principais Conclusões
- O Svelte não possui um helper
lazy()integrado, então o lazy loading usa oimport()nativo do JavaScript com renderização condicional - O SvelteKit lida com code splitting em nível de rota automaticamente, mas o lazy loading em nível de componente ainda é necessário para widgets pesados dentro de uma única página
- O Vite divide imports dinâmicos em chunks separados sem nenhuma configuração
- Três padrões principais cobrem a maioria dos casos de uso: carregar sob demanda com
{#await}, pré-carregar ao passar o mouse e adiar até que o navegador esteja ocioso
Por Que o Lazy Loading em Nível de Componente Ainda Importa no SvelteKit
O SvelteKit já lida com code splitting em nível de rota automaticamente. Cada rota recebe seu próprio chunk, então navegar entre páginas não infla o bundle inicial. Mas dentro de uma única página, tudo que você importa no topo de um arquivo .svelte é empacotado junto e carregado antecipadamente.
É aí que o lazy loading em nível de componente se torna valioso. Se uma página contém um componente de gráfico pesado, um player de vídeo ou um modal que só aparece após interação do usuário, não há razão para carregar esse código na chegada à página.
O SvelteKit é construído com Vite, que lida com imports dinâmicos nativamente. Quando o Vite vê import('./HeavyChart.svelte'), ele automaticamente divide esse módulo em um chunk separado. Nenhuma configuração extra necessária.
Como Fazer Lazy Load de Componentes Svelte: Padrões Principais
Lazy Loading Básico com {#await}
A abordagem mais simples usa o bloco {#await} do Svelte diretamente no template:
<!-- src/routes/+page.svelte -->
<script>
let showChart = false;
let chartData = [1, 2, 3];
</script>
<button onclick={() => showChart = true}>Load Chart</button>
{#if showChart}
{#await import('$lib/components/HeavyChart.svelte')}
<p>Loading chart...</p>
{:then Chart}
<Chart.default data={chartData} />
{:catch error}
<p>Failed to load chart: {error.message}</p>
{/await}
{/if}
Isso funciona tanto no Svelte 4 quanto no Svelte 5. O bloco {:catch} é importante — falhas de rede acontecem, e erros silenciosos tornam a depuração dolorosa. No Svelte 4, a troca dinâmica de componentes normalmente usa <svelte:component this={Component}>. No Svelte moderno, alterar a referência do componente também pode acionar a re-renderização diretamente.
O navegador armazena o módulo em cache após a primeira importação. Renderizações subsequentes do mesmo componente não acionam uma nova requisição de rede.
Discover how at OpenReplay.com.
Carregar ao Passar o Mouse para Melhor Performance Percebida
Um padrão comum é começar a carregar quando o usuário sinaliza intenção — passando o mouse sobre um elemento de gatilho:
<!-- src/routes/+page.svelte -->
<script lang="ts">
import type { Component } from 'svelte';
let HeavyWidget: Component<{ message: string }> | null = $state(null);
async function loadWidget() {
if (!HeavyWidget) {
const module = await import('$lib/components/HeavyWidget.svelte');
HeavyWidget = module.default;
}
}
</script>
<div onmouseenter={loadWidget}>
<p>Hover to preload the widget</p>
</div>
{#if HeavyWidget}
<HeavyWidget message="Ready!" />
{/if}
Isso funciona bem para tooltips, popovers e sidebars. O componente começa a carregar antes que o usuário clique, então quando eles interagem, geralmente já está em cache.
Carregar Quando o Navegador Estiver Ocioso
Para componentes não críticos que melhoram a página mas não são necessários imediatamente, use requestIdleCallback:
<script lang="ts">
import { onMount } from 'svelte';
import type { Component } from 'svelte';
let FeedbackWidget: Component | null = $state(null);
onMount(() => {
const load = () =>
import('$lib/components/FeedbackWidget.svelte').then(
(m) => (FeedbackWidget = m.default)
);
if ('requestIdleCallback' in window) {
requestIdleCallback(load);
} else {
setTimeout(load, 300); // fallback para Safari
}
});
</script>
{#if FeedbackWidget}
<FeedbackWidget />
{/if}
Note que o suporte do Safari para requestIdleCallback historicamente tem sido inconsistente, então o fallback com setTimeout é recomendado.
Quando Não Usar Lazy Loading
Nem todo componente se beneficia do lazy loading. Evite-o para:
- UI acima da dobra — navegação, seções hero, conteúdo primário
- Componentes pequenos — o overhead assíncrono supera a economia
- Componentes necessários imediatamente na montagem — o flash de carregamento degrada a UX
Dividir excessivamente cria muitos chunks assíncronos pequenos. Bundlers modernos como o Vite lidam com isso eficientemente, mas ainda há um ponto de retornos decrescentes.
Conclusão
O lazy loading de componentes Svelte se resume a uma coisa: usar import() em vez de uma importação estática, e então renderizar o resultado condicionalmente. A build baseada em Vite do SvelteKit lida com o code splitting automaticamente. Os três padrões acima — sob demanda, ao passar o mouse e ocioso — cobrem a maioria dos cenários do mundo real. Escolha o gatilho que corresponde a quando os usuários realmente precisam do componente, adicione tratamento de erros, e seu bundle inicial permanece enxuto.
Perguntas Frequentes
O import dinâmico funciona em ambas as versões. No Svelte 4, você normalmente renderiza o componente carregado usando svelte:component com o atributo this. No Svelte 5, você pode usar o componente resolvido diretamente como uma tag no template. O mecanismo de importação subjacente é o mesmo em ambos os casos.
Os imports dinâmicos são executados durante o SSR também, já que o Node.js os suporta. No entanto, o lazy loading é principalmente uma otimização do lado do cliente destinada a reduzir o payload inicial de JavaScript do navegador. Se um componente deve ser renderizado no servidor por razões de SEO ou first-paint, uma importação estática é a melhor escolha.
Verifique a saída da sua build ou use um analisador de bundle para identificar chunks grandes. Componentes que trazem bibliotecas de terceiros pesadas como renderizadores de gráficos, editores de rich text ou widgets de mapas são candidatos fortes. Se um componente adiciona menos de alguns kilobytes, o overhead de uma requisição de rede extra provavelmente supera a economia.
Não. O navegador armazena o módulo em cache após a primeira resolução do import dinâmico. Em renderizações subsequentes, o módulo em cache é retornado imediatamente, então o estado de carregamento aparece apenas na primeira busca. Você também pode pré-carregar o módulo ao passar o mouse ou durante o tempo ocioso para eliminar completamente o atraso visível.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.