Kit Svelte é o mais recente do que eu chamaria de estruturas de aplicativos de última geração. É claro que ele monta um aplicativo para você, com o roteamento baseado em arquivo, a implantação e a renderização do lado do servidor que o Next sempre fez. Mas o SvelteKit também oferece suporte a layouts aninhados, mutações de servidor que sincronizam os dados em sua página e algumas outras sutilezas que abordaremos.
Este post pretende ser uma introdução de alto nível para criar algum entusiasmo para quem nunca usou o SvelteKit. Será um passeio descontraído. Se você gosta do que vê, o os documentos completos estão aqui.
De certa forma, este é um post desafiador para escrever. SvelteKit é um framework de aplicação. Ele existe para ajudá-lo a construir… bem, aplicativos. Isso dificulta a demonstração. Não é viável criar um aplicativo inteiro em uma postagem de blog. Em vez disso, usaremos um pouco nossa imaginação. Construiremos o esqueleto de um aplicativo, teremos alguns espaços reservados de interface do usuário vazios e dados estáticos codificados permanentemente. O objetivo não é criar um aplicativo real, mas mostrar como as peças móveis do SvelteKit funcionam para que você possa criar seu próprio aplicativo.
Para esse fim, criaremos o aplicativo To-Do testado e comprovado como exemplo. Mas não se preocupe, isso será muito, muito mais sobre ver como o SvelteKit funciona do que criar outro aplicativo de tarefas.
O código para tudo neste post é disponível no GitHub. Este projeto também é implantado no Vercel para uma demonstração ao vivo.
Criando seu projeto
Criar um novo projeto SvelteKit é bastante simples. Corre npm create your-app-name
no terminal e responda às perguntas. Certifique-se de escolher “Skeleton Project”, mas, caso contrário, faça as seleções que desejar para TypeScript, ESLint, etc.
Uma vez que o projeto é criado, execute npm i
e npm run dev
e um servidor de desenvolvimento deve começar a funcionar. Acenda localhost:5173
no navegador e você obterá a página de espaço reservado para o aplicativo esqueleto.
Roteamento básico
Observe a routes
pasta sob src
. Isso contém o código para todas as nossas rotas. já existe um +page.svelte
arquivo lá com conteúdo para a raiz /
rota. Não importa onde você esteja na hierarquia de arquivos, a página real desse caminho sempre terá o nome +page.svelte
. Com isso em mente, vamos criar páginas para /list
, /details
, /admin/user-settings
e admin/paid-status
e também adicione alguns espaços reservados de texto para cada página.
O layout do seu arquivo deve ficar mais ou menos assim:
Você deve ser capaz de navegar alterando os caminhos de URL na barra de endereços do navegador.
Layouts
Queremos links de navegação em nosso aplicativo, mas certamente não queremos copiar a marcação para eles em cada página que criamos. Então, vamos criar um +layout.svelte
arquivo na raiz do nosso routes
pasta, que o SvelteKit tratará como um modelo global para todas as páginas. Vamos adicionar algum conteúdo a ele:
<nav> <ul> <li> <a href="/pt/">Home</a> </li> <li> <a href="/pt/list">To-Do list</a> </li> <li> <a href="/pt/admin/paid-status">Account status</a> </li> <li> <a href="/pt/admin/user-settings">User settings</a> </li> </ul>
</nav> <slot /> <style> nav { background-color: beige; } nav ul { display: flex; } li { list-style: none; margin: 15px; } a { text-decoration: none; color: black; }
</style>
Alguma navegação rudimentar com alguns estilos básicos. De particular importância é a <slot />
marcação. Isso é não o slot que você usa com componentes da web e shadow DOM, mas sim um recurso Svelte indicando onde colocar nosso conteúdo. Quando uma página é renderizada, o conteúdo da página deslizará para onde está o slot.
E agora temos alguma navegação! Não vamos ganhar nenhum concurso de design, mas não estamos tentando.
Layouts aninhados
E se quiséssemos que todas as nossas páginas de administração herdassem o layout normal que acabamos de criar, mas também compartilhassem algumas coisas comuns a todas as páginas de administração (mas apenas páginas de administração)? Sem problemas, adicionamos outro +layout.svelte
arquivo em nossa raiz admin
diretório, que será herdado por tudo abaixo dele. Vamos fazer isso e adicionar este conteúdo:
<div>This is an admin page</div> <slot /> <style> div { padding: 15px; margin: 10px 0; background-color: red; color: white; }
</style>
Adicionamos um banner vermelho indicando que esta é uma página de administração e, como antes, um <slot />
denotando onde queremos que o conteúdo da nossa página vá.
Nosso layout raiz antes da renderização. Dentro do layout raiz há um <slot />
marcação. O conteúdo do layout aninhado vai para o layout raiz <slot />
. E, finalmente, o layout aninhado define seu próprio <slot />
, no qual o conteúdo da página é renderizado.
Se você navegar para as páginas de administração, deverá ver o novo banner vermelho:
Definindo nossos dados
OK, vamos renderizar alguns dados reais — ou pelo menos, ver como podemos renderizar alguns dados reais. Existem centenas de maneiras de criar e conectar-se a um banco de dados. Este post é sobre o SvelteKit, e não sobre o gerenciamento do DynamoDB, então vamos “carregar” alguns dados estáticos. Mas usaremos o mesmo maquinário para lê-lo e atualizá-lo que você usaria para dados reais. Para um aplicativo da Web real, troque as funções que retornam dados estáticos por funções que conectam e consultam qualquer banco de dados que você usar.
Vamos criar um módulo bem simples em lib/data/todoData.ts
que retorna alguns dados estáticos junto com atrasos artificiais para simular consultas reais. você vai ver isso lib
pasta importada em outro lugar via $lib
. Este é um recurso do SvelteKit para essa pasta específica e você pode até adicione seus próprios apelidos.
let todos = [ { id: 1, title: "Write SvelteKit intro blog post", assigned: "Adam", tags: [1] }, { id: 2, title: "Write SvelteKit advanced data loading blog post", assigned: "Adam", tags: [1] }, { id: 3, title: "Prepare RenderATL talk", assigned: "Adam", tags: [2] }, { id: 4, title: "Fix all SvelteKit bugs", assigned: "Rich", tags: [3] }, { id: 5, title: "Edit Adam's blog posts", assigned: "Geoff", tags: [4] },
]; let tags = [ { id: 1, name: "SvelteKit Content", color: "ded" }, { id: 2, name: "Conferences", color: "purple" }, { id: 3, name: "SvelteKit Development", color: "pink" }, { id: 4, name: "CSS-Tricks Admin", color: "blue" },
]; export const wait = async amount => new Promise(res => setTimeout(res, amount ?? 100)); export async function getTodos() { await wait(); return todos;
} export async function getTags() { await wait(); return tags.reduce((lookup, tag) => { lookup[tag.id] = tag; return lookup; }, {});
} export async function getTodo(id) { return todos.find(t => t.id == id);
}
Uma função para retornar uma matriz plana de nossos itens de tarefas, uma pesquisa de nossas tags e uma função para buscar uma única tarefa (usaremos essa última em nossa página Detalhes).
Carregando nossos dados
Como colocamos esses dados em nossas páginas Svelte? Há várias maneiras, mas, por enquanto, vamos criar um +page.server.js
arquivo em nosso list
pasta e coloque este conteúdo nela:
import { getTodos, getTags } from "$lib/data/todoData"; export function load() { const todos = getTodos(); const tags = getTags(); return { todos, tags, };
}
Nós definimos um load()
função que extrai os dados necessários para a página. Observe que nós somos não await
-ing chamadas para o nosso getTodos
e getTags
funções assíncronas. Isso criaria uma cascata de carregamento de dados enquanto esperamos que nossos itens de tarefas cheguem antes de carregar nossas tags. Em vez disso, retornamos as promessas brutas de load
, e SvelteKit faz o trabalho necessário para await
Eles.
Então, como acessamos esses dados de nosso componente de página? SvelteKit fornece um data
prop para nosso componente com dados nele. Vamos acessar nossos itens de tarefas e tags usando um atribuição reativa.
Nosso componente de página de lista agora se parece com isso.
<script> export let data; $: ({ todo, tags } = data);
</script> <table cellspacing="10" cellpadding="10"> <thead> <tr> <th>Task</th> <th>Tags</th> <th>Assigned</th> </tr> </thead> <tbody> {#each todos as t} <tr> <td>{t.title}</td> <td>{t.tags.map((id) => tags[id].name).join(', ')}</td> <td>{t.assigned}</td> </tr> {/each} </tbody>
</table> <style> th { text-align: left; }
</style>
E isso deve renderizar nossos itens de tarefas!
Grupos de layout
Antes de passarmos para a página Detalhes e modificarmos os dados, vamos dar uma olhada em um recurso SvelteKit realmente interessante: grupos de layout. Já vimos layouts aninhados para todas as páginas de administração, mas e se quiséssemos compartilhar um layout entre páginas arbitrárias no mesmo nível de nosso sistema de arquivos? Em particular, e se quiséssemos compartilhar um layout apenas entre nossa página de lista e nossa página de detalhes? Já temos um layout global nesse nível. Em vez disso, podemos criar um novo diretório, mas com um nome entre parênteses, assim:
Agora temos um grupo de layout que cobre nossas páginas Lista e Detalhes. eu o nomeei (todo-management)
mas você pode nomeá-lo como quiser. Para ser claro, este nome será não afetam os URLs das páginas dentro do grupo de layout. As URLs permanecerão as mesmas; grupos de layout permitem que você adicione layouts compartilhados a páginas sem que todos eles compreendam a totalidade de um diretório em routes
.
We poderia adicione um +layout.svelte
arquivo e alguns bobos <div>
banner dizendo: "Ei, estamos gerenciando tarefas". Mas vamos fazer algo mais interessante. Os layouts podem definir load()
funções para fornecer dados para todas as rotas abaixo delas. Vamos usar essa funcionalidade para carregar nossas tags — já que usaremos nossas tags em nosso details
página — além do list
página que já temos.
Na realidade, forçar um grupo de layout apenas a fornecer um único dado quase certamente não vale a pena; é melhor duplicar esses dados no load()
função para cada página. Mas para esta postagem, ela fornecerá a desculpa de que precisamos para ver um novo recurso do SvelteKit!
Primeiro, vamos entrar em nosso list
Páginas +page.server.js
arquivo e remova as tags dele.
import { getTodos, getTags } from "$lib/data/todoData"; export function load() { const todos = getTodos(); return { todos, };
}
Nossa página de lista agora deve produzir um erro, pois não há tags
objeto. Vamos corrigir isso adicionando um +layout.server.js
arquivo em nosso grupo de layout, então defina um load()
função que carrega nossas tags.
import { getTags } from "$lib/data/todoData"; export function load() { const tags = getTags(); return { tags, };
}
E, assim, nossa página List está renderizando novamente!
Estamos carregando dados de vários locais
Vamos colocar um ponto fino sobre o que está acontecendo aqui:
- Nós definimos um
load()
função para o nosso grupo de layout, que colocamos em+layout.server.js
. - Isso fornece dados para todos os das páginas servidas pelo layout — que, neste caso, significa nossas páginas Lista e Detalhes.
- Nossa página de lista também define um
load()
função que vai em seu+page.server.js
arquivo. - O SvelteKit faz o trabalho pesado de pegar os resultados dessas fontes de dados, mesclá-los e disponibilizar ambos em
data
.
Nossa página de detalhes
Usaremos nossa página Detalhes para editar um item de tarefa. Primeiro, vamos adicionar uma coluna à tabela em nossa página Lista que vincula à página Detalhes com o ID do item de tarefa na string de consulta.
<td><a href="/pt/details?id={t.id}">Edit</a></td>
Agora vamos construir nossa página Detalhes. Primeiro, adicionaremos um carregador para pegar o item de tarefa que estamos editando. Crie um +page.server.js
in /details
, com este conteúdo:
import { getTodo, updateTodo, wait } from "$lib/data/todoData"; export function load({ url }) { const id = url.searchParams.get("id"); console.log(id); const todo = getTodo(id); return { todo, };
}
Nosso carregador vem com um url
propriedade da qual podemos obter valores de string de consulta. Isso facilita a pesquisa do item de tarefa que estamos editando. Vamos renderizar essa tarefa, juntamente com a funcionalidade para editá-la.
O SvelteKit possui recursos de mutação integrados maravilhosos, desde que você use formulários. Lembra dos formulários? Aqui está a nossa página Detalhes. Eliminei os estilos por questões de brevidade.
<script> import { enhance } from "$app/forms"; export let data; $: ({ todo, tags } = data); $: currentTags = todo.tags.map(id => tags[id]);
</script> <form use:enhance method="post" action="?/editTodo"> <input name="id" type="hidden" value="{todo.id}" /> <input name="title" value="{todo.title}" /> <div> {#each currentTags as tag} <span style="{`color:" ${tag.color};`}>{tag.name}</span> {/each} </div> <button>Save</button>
</form>
Estamos pegando as tags como antes do carregador do nosso grupo de layout e o item de tarefa do carregador da nossa página. Estamos pegando o real tag
objetos da lista de tarefas de IDs de tags e, em seguida, renderizando tudo. Criamos um formulário com uma entrada oculta para o ID e uma entrada real para o título. Exibimos as tags e fornecemos um botão para enviar o formulário.
Se você notou o use:enhance
, que simplesmente diz ao SvelteKit para usar aprimoramento progressivo e Ajax para enviar nosso formulário. Você provavelmente sempre usará isso.
Como salvamos nossas edições?
Observe a action="?/editTodo"
atributo no próprio formulário? Isso nos diz onde queremos enviar nossos dados editados. Para o nosso caso, queremos submeter a um editTodo
"açao."
Vamos criá-lo adicionando o seguinte ao +page.server.js
arquivo que já temos para Detalhes (que atualmente tem um load()
função, para pegar nossa tarefa):
import { redirect } from "@sveltejs/kit"; // ... export const actions = { async editTodo({ request }) { const formData = await request.formData(); const id = formData.get("id"); const newTitle = formData.get("title"); await wait(250); updateTodo(id, newTitle); throw redirect(303, "/list"); },
};
Ações de formulário nos dão uma request
objeto, que fornece acesso ao nosso formData
, que tem um get
método para nossos vários campos de formulário. Adicionamos essa entrada oculta para o valor de ID para que possamos pegá-la aqui para procurar o item de tarefa que estamos editando. Simulamos um atraso, chamamos um novo updateTodo()
método e, em seguida, redirecione o usuário de volta para o /list
página. o updateTodo()
o método apenas atualiza nossos dados estáticos; na vida real, você executaria algum tipo de atualização em qualquer armazenamento de dados que estiver usando.
export async function updateTodo(id, newTitle) { const todo = todos.find(t => t.id == id); Object.assign(todo, { title: newTitle });
}
Vamos experimentar. Iremos primeiro para a página Lista:
Agora vamos clicar no botão Editar para um dos itens de tarefa para abrir a página de edição em /details
.
Vamos adicionar um novo título:
Agora, clique em Salvar. Isso deve nos levar de volta ao nosso /list
página, com o novo título de tarefa aplicado.
Como o novo título apareceu assim? Foi automático. Assim que redirecionamos para o /list
página, o SvelteKit reexecutou automaticamente todos os nossos carregadores, exatamente como teria feito independentemente. Este é o principal avanço que as estruturas de aplicativos de próxima geração, como SvelteKit, Remix e Próxima 13 fornecer. Em vez de fornecer uma maneira conveniente de renderizar páginas e desejar boa sorte ao buscar quaisquer pontos de extremidade que você possa ter para atualizar os dados, eles integram a mutação de dados ao carregamento de dados, permitindo que os dois trabalhem em conjunto.
Algumas coisas que você deve estar se perguntando…
Esta atualização de mutação não parece muito impressionante. Os carregadores serão executados novamente sempre que você navegar. E se não tivéssemos adicionado um redirecionamento em nossa ação de formulário, mas permanecido na página atual? O SvelteKit realizaria a atualização na ação do formulário, como antes, mas ainda execute novamente todos os carregadores para a página atual, incluindo os carregadores no(s) layout(s) de página.
Podemos ter meios mais direcionados de invalidar nossos dados? Por exemplo, nossas tags não foram editadas, portanto, na vida real, não desejaríamos consultá-las novamente. Sim, o que mostrei é apenas o comportamento padrão dos formulários no SvelteKit. Você pode desativar o comportamento padrão ao fornecendo um retorno de chamada para use:enhance
. Então SvelteKit fornece manual funções de invalidação.
Carregar dados em cada navegação é potencialmente caro e desnecessário. Posso armazenar em cache esses dados como faço com ferramentas como react-query
? Sim, apenas diferente. O SvelteKit permite definir (e respeitar) os cabeçalhos de controle de cache que a Web já fornece. E abordarei os mecanismos de invalidação de cache em uma postagem subsequente.
Tudo o que fizemos ao longo deste artigo usa dados estáticos e modifica valores na memória. Se precisar reverter tudo e recomeçar, pare e reinicie o npm run dev
Processo de nó.
Resumindo
Mal arranhamos a superfície do SvelteKit, mas esperamos que você tenha visto o suficiente para ficar animado com isso. Não me lembro da última vez que achei o desenvolvimento web tão divertido. Com coisas como empacotamento, roteamento, SSR e implantação, tudo pronto para uso, passo mais tempo codificando do que configurando.
Aqui estão mais alguns recursos que você pode usar como próximas etapas para aprender o SvelteKit:
- Conteúdo com tecnologia de SEO e distribuição de relações públicas. Seja amplificado hoje.
- Platoblockchain. Inteligência Metaverso Web3. Conhecimento Ampliado. Acesse aqui.
- Fonte: https://css-tricks.com/getting-started-with-sveltekit/
- 1
- 10
- 100
- 11
- 7
- 9
- 98
- a
- Capaz
- Sobre
- sobre isso
- Acesso
- Conta
- Açao Social
- ações
- Adam
- adicionado
- Adição
- endereço
- admin
- avançado
- afetar
- Todos os Produtos
- Permitindo
- ao lado de
- já
- sempre
- quantidade
- e
- Outro
- responder
- qualquer um
- app
- Aplicação
- aplicações
- aplicado
- por aí
- Ordem
- artigo
- artificial
- atribuído
- Automático
- automaticamente
- disponível
- aguardam
- em caminho duplo
- fundo
- bandeira
- Barra
- basic
- antes
- MELHOR
- Melhor
- entre
- Pouco
- Preto
- Blog
- Posts do Blog
- Azul
- Caixa
- trazer
- navegador
- erros
- construir
- construído
- construídas em
- botão
- Esconderijo
- chamada
- chamadas
- capacidades
- casas
- certamente
- desafiante
- mudança
- remover filtragem
- código
- Codificação
- cor
- Coluna
- como
- comum
- Competições
- componente
- componentes
- conferências
- Contato
- Conexão de
- cônsul
- conteúdo
- Conveniente
- poderia
- Para
- cobertura
- Covers
- crio
- criado
- Criar
- Atual
- Atualmente
- dados,
- banco de dados
- Padrão
- Define
- atraso
- atrasos
- desenvolvimento
- Design
- detalhes
- Dev
- Desenvolvimento
- DID
- Ecrã
- Não faz
- fazer
- não
- cada
- em outro lugar
- suficiente
- Todo
- totalidade
- erro
- etc.
- Mesmo
- Cada
- tudo
- exemplo
- animado
- Excitação
- existe
- caro
- exportar
- factível
- Característica
- poucos
- Campos
- Envie o
- Arquivos
- Finalmente
- final
- Fogo
- Primeiro nome
- Fixar
- plano
- seguinte
- para sempre
- formulário
- formato
- formas
- encontrado
- enquadramentos
- da
- cheio
- Diversão
- função
- funcionalidade
- funções
- ter
- obtendo
- OFERTE
- Dando
- Global
- Go
- meta
- vai
- vai
- agarrar
- Grupo
- Do grupo
- acontecer
- Queijos duros
- cabeçalhos
- ajudar
- SUA PARTICIPAÇÃO FAZ A DIFERENÇA
- oculto
- hierarquia
- de alto nível
- detém
- Esperançosamente
- Horizontal
- Como funciona o dobrador de carta de canal
- HTML
- HTTPS
- EU VOU
- imaginações
- importar
- importância
- impressionante
- in
- Incluindo
- do estado inicial,
- entrada
- em vez disso
- integrar
- interessante
- Introdução
- IT
- Unid
- se
- JavaScript
- Chave
- Sobrenome
- mais recente
- traçado
- aprendizagem
- Permite
- Nível
- Li
- vida
- leve
- Provável
- Links
- Lista
- viver
- carregar
- carregador
- carregamento
- cargas
- longo
- olhar
- OLHARES
- pesquisa
- sorte
- maquinaria
- fazer
- FAZ
- Fazendo
- gestão
- manual
- Margem
- Importância
- significa
- Memória
- apenas
- fusão
- método
- poder
- mente
- Módulo
- mais
- mover
- em movimento
- múltiplo
- nome
- Nomeado
- nav
- Navegar
- Navegação
- necessário
- você merece...
- Novo
- Próximo
- nó
- normal
- número
- objeto
- objetos
- ONE
- ordem
- Outros
- de outra forma
- próprio
- particular
- caminho
- Realizar
- escolher
- peça
- peças
- espaço reservado
- platão
- Inteligência de Dados Platão
- PlatãoData
- ponto
- Publique
- POSTAGENS
- potencialmente
- Preparar
- Problema
- processo
- produzir
- progressivo
- projeto
- promessas
- propriedade
- protegido
- fornecer
- fornece
- Pullover
- colocar
- questão
- Cru
- Leia
- reais
- vida real
- Realidade
- Vermelho
- redirecionar
- Independentemente
- permanecem
- lembrar
- remover
- representação
- torna
- solicitar
- Recursos
- Resultados
- retorno
- voltar
- Retorna
- reverter
- Rico
- raiz
- Rota
- rotas
- Execute
- corrida
- mesmo
- Salvar
- visto
- serve
- conjunto
- Shadow
- Partilhar
- compartilhado
- rede de apoio social
- mostrar
- simples
- simplesmente
- desde
- solteiro
- slide
- So
- alguns
- algo
- Fontes
- gastar
- começo
- começado
- fiquei
- Passos
- Dê um basta
- enviar
- suportes
- superfície
- .
- mesa
- TAG
- Tire
- tomar
- Converse
- Tandem
- visadas
- conta
- modelo
- terminal
- A
- coisas
- todo
- tempo
- Título
- para
- juntos
- também
- ferramentas
- excursão
- tratar
- verdadeiro
- VIRAR
- Datilografado
- ui
- para
- Atualizar
- Atualizações
- URL
- us
- usar
- Utilizador
- valor
- Valores
- vário
- via
- Ver
- esperar
- querido
- maneiras
- web
- componentes da web
- Desenvolvimento web
- O Quê
- qual
- branco
- precisarão
- ganhar
- sem
- Maravilhoso
- Atividades:
- trabalho
- Equivalente há
- seria
- escrever
- Vocês
- investimentos
- zefirnet