FastAPI a ir para Full Stack
A história de como Vue viu a cobra e se apaixonou.
O FastAPI é um daqueles softwares que me deixa desconfiado porque a história do back-end Python é Demasiado Agradável. Dicas de tipo em manipuladores de estilo Flask/Express tornam-se de análise e validação. Async com auto-recarregamentos funciona sem invocar um manual de configuração de framework eldritch. Junte os seus esquemas OpenAPI e auto-recarregamentos e você pode ir de git init Para uma API respeitável antes que a máquina de café tenha terminado a sua sequência de arranque.
Então, tu precisas de um frontend.
Historicamente, este é o local onde a autoestrada iluminada por neon terminava abruptamente num muro de betão.
FastAPI É muito bom em APIs, mas não pode realmente servir o seu frontend na raiz do site, a menos que você queira Tudo Os seus pedidos são encaminhados para StaticFilesE o suporte a SPA é inédito. Você poderia servir ficheiros, renderizar templates, ou anexar qualquer mecanismo que desejasse, mas a última etapa entre uma frontend moderna em JavaScript e a aplicação Python foi, em grande parte, deixada como um exercício para o leitor.
E esse leitor era cada vez mais eu.
Entretanto, na área do frontend
Eu uso o Vue para este trabalho. O Vue vive aproximadamente na mesma área que o React e o Svelte: interfaces baseadas em componentes, estado reativo, roteamento do lado do cliente e a habitual maquinaria moderna para transformar uma pilha de ficheiros de origem em algo que um navegador possa executar.
O fastapi-vue No entanto, o pacote também pode ser usado com outros, por isso estou a descrever brevemente os concorrentes.
Reagir
O React é o gorila de 800 libras. Tem um ecossistema colossal, uma resposta para tudo e, geralmente, três respostas adicionais a discutir com a primeira.
A sua maior vantagem prática é simplesmente a gravidade: muitos desenvolvedores conhecem-no, muitas bibliotecas têm-no como alvo, e muito código de exemplo começa com npm install reactÉ muito mais popular do que o Vue, o que torna a integração relativamente fraca entre o React e o FastAPI bastante reveladora por si só.
Até mesmo a solução full-stack oficial do FastAPI - lançada pela primeira vez há apenas algumas semanas - é fundamentalmente um repositório de modelos: uma pilha React pré-selecionada a partir da qual você começa, em vez de ferramentas que podem entrar numa aplicação Python existente e integrar um frontend nela.
Esguio
Svelte adota uma abordagem mais orientada para o compilador. Em vez de enviar bastante maquinaria de framework para o navegador, transforma os componentes no momento da compilação. O resultado ainda pode funcionar sem o Node em produção.
Isso requer um pouco de astúcia para uma reatividade correta, exigindo $ na sua linguagem personalizada para indicar o que necessita de uma atualização. Por outro lado, esta linguagem personalizada permite um código mais curto do que o dos seus concorrentes.
Vue
Vue encontra-se num lugar que eu gosto bastante: estrutura suficiente para construir aplicações substanciais, mas sem fazer o HTML desaparecer sob várias camadas geológicas de JavaScript. A reactividade com a sua loja Pinia simplesmente funciona, e não interfere. E quando você precisa daquele último pedacinho de desempenho, integra-se bem com estruturas não-reativas. Sem envolvimentos complicados ou useState E tal boilerplate é necessário.
E funciona rapidamente, o que não é o caso da maioria das aplicações React.
É oficial create-vue A ferramenta também me dá algo particularmente útil aqui: não tenho de inventar A minha A ideia de como um projeto Vue deve ser. Pode perguntar interativamente se a aplicação deve usar TypeScript, Vue Router, Pinia, Vitest, Playwright/Cypress, ESLint, Prettier e o resto do equipamento habitual.
Isso torna-se importante mais tarde.
Como é que realmente implementamos esta coisa?
Uma vez que tenho FastAPI de um lado e Vue, React ou Svelte do outro, existem algumas formas fundamentalmente diferentes de colocar a criatura resultante num servidor.
Opção 1: render-se a Node
A resposta óbvia do mundo JavaScript é colocar um servidor JavaScript em produção também.
Isso faz muito sentido se eu realmente quiser um back-end Node. Há uma vantagem genuína em ter uma linguagem e ferramentas estreitamente relacionadas em ambos os lados da rede. Se a minha equipa quiser TypeScript em todo o lado, essa é uma arquitectura perfeitamente coerente.
Eu não.
Eu escolhi FastAPI porque quero escrever o backend em Python. Instalar outro runtime ao lado dele apenas para fornecer ativos frontend parece contratar um segundo chef para transportar pratos da cozinha para a sala de jantar.
Há também a pequena questão do universo de dependências JavaScript. É demasiado pesado, mantém pouca compatibilidade e é frequentemente problemático. Embora nvm Pode instalar facilmente a versão correcta do Node, mas ainda assim, ocupa uma quantidade enorme de espaço que os servidores alojados muitas vezes não têm.
O Node é útil na minha máquina de desenvolvimento. O Vite é excelente. create-vue É excelente. O ecossistema de compilação faz o seu trabalho extremamente bem.
Isso não significa que eu queira nada disso na máquina de produção.
Opção 2: renderizar tudo no servidor
No extremo oposto, posso ignorar o SPA completamente e gerar HTML em Python.
Isto merece mais respeito do que por vezes recebe. Nem todas as aplicações necessitam de um runtime de aplicação do lado do cliente, um router e vários megabytes de civilização de suporte.
Ferramentas como o htmx podem levar o HTML renderizado pelo servidor surpreendentemente longe, adicionando pedidos HTTP, trocas, transições, WebSockets e eventos enviados pelo servidor diretamente através de atributos HTML. Combine com o html5tagger para criar esses documentos e fragmentos HTML no servidor, e terá um site que funciona em todo o lado e que pode ser lido pelas redes sociais, motores de busca e agentes, indistintamente.
Para sites dominados por documentos, formulários e interações relativamente simples, eu gosto desta arquitectura. O navegador solicita algo, o Python produz HTML, e ninguém precisa de um pipeline de compilação capaz de lançar uma sonda de Marte.
Vasanko.com é construído com base neste método, apenas utilizando Vue para a interface de administração, onde é necessária uma interatividade mais forte. Este CMS é executado na configuração FastAPI-Vue, mas processa todas as páginas do lado do servidor em Python.
Opção 3: executar dois servidores
O compromisso comum é, portanto:
- O FastAPI executa a API.
- Vite ou outro servidor JavaScript executa o frontend
- Um proxy reverso coloca ambos sob um único nome de host.
- A produção tem agora duas aplicações, duas pilhas de dependências, dois processos e outro ficheiro de configuração que mantém tudo unido.
Isto funciona, mas não é bonito.
O navegador não se importa se app.js Foi emitido por Python, Node, Caddy, nginx ou uma torradeira suficientemente determinada. Uma vez que o frontend foi construído, o resultado é HTML estático, CSS, JavaScript, fontes e imagens.
Então, por que manter a fábrica em funcionamento depois de o produto já ter saído da linha de montagem?
Construir com JavaScript, executar com Python
Isso tornou-se a ideia central por trás de fastapi-vue-setup.
Eu quero ferramentas JavaScript onde elas são realmente úteis:
create-vuepara criar o frontend- Vite para o servidor de desenvolvimento
- Recarregamentos instantâneos a quente em alterações
- A compilação normal do Vue no Node, Bun ou Deno
E depois quero que desapareça.
O artefacto de produção deve ser um pacote Python que contém um frontend já construído. A instalação desse pacote não deve exigir Node, npm, Vite, código-fonte Vue, ou a anomalia gravitacional tradicionalmente armazenada em node_modules.
É exactamente assim que fastapi-vue-setup Cria projetos hoje: uv build Executa a compilação do frontend e inclui os ativos resultantes dentro do pacote Python. A configuração Hatch gerada trata frontend-build Como um artefacto e liga a compilação da distribuição de código-fonte, limitando o conteúdo do pacote ao próprio pacote Python.
A distinção é importante, especialmente para um sdist. Eu não quero que uma distribuição de código-fonte signifique ”aqui está algum Python, aqui está uma árvore de desenvolvimento Vue completa, agora, por favor, instale o Node e reconstrua a aplicação real sozinho”. O frontend já está compilado antes de a distribuição sair da minha máquina.
O pacote contém o que é necessário para executar, não tudo o que eu precisei para o construir.
Isso deixa a implantação parecendo maravilhosamente chata:
uvx my-app
Nenhuma cerimónia de instalação do Node na máquina alvo. Nenhuma npm installNenhum servidor frontend. Nenhuma árvore de dependências JavaScript a acordar três meses depois e a pedir para ser alimentada.
O pacote inicia o FastAPI, e o FastAPI serve a aplicação.
O outro problema feio
Construir o frontend era apenas metade disso.
O StaticFiles não é exactamente um servidor de frontend
O FastAPI expõe o Starlette’s StaticFiles, e para ativos estáticos comuns, faz exatamente o que diz na descrição:
app.mount("/static", StaticFiles(directory="static"))
O problema começa quando o frontend é o próprio site.
Uma aplicação Vue normalmente quer /. Também pode querer /login, /settings, /dashboard/coffee-reactor/7, e qualquer outra coisa que pertença ao router do lado do cliente.
Mas montando StaticFiles em / Efetivamente, isso entrega a aplicação montada para todo o espaço de URL restante. O próprio mantenedor do FastAPI explicou o problema há anos: montá-lo na raiz e a aplicação estática assume o controlo, por isso as operações de caminho normais por baixo dele já não funcionam como esperado.
E nós precisamos:
- Construção do frontend em
/* - O FastAPI ainda lida com
/api/.../openapi.json- Quaisquer outras rotas arbitrárias
Este não é o mesmo problema que servir /static/logo.svg.
O FastAPI melhorou recentemente o seu próprio suporte front-end, e a documentação atual agora aponta explicitamente as aplicações front-end para app.frontend() Em vez de simples StaticFilesMas fastapi-vue Precede essa solução e também tem uma função um pouco diferente: é a pequena metade de tempo de execução deste sistema de embalagem completo.
Tempo de execução fastapi-vue
O companheiro fastapi-vue O pacote fornece um Frontend Handler em vez de montar StaticFiles Sobre a aplicação.
No modo SPA, pode retornar index.html Para caminhos pertencentes ao router do lado do cliente, em vez de exigir um ficheiro físico com esse nome.
Note
Devido à forma como o roteamento do FastAPI funciona, as montagens de aplicações consomem tudo abaixo desse caminho. O resto das rotas são tentadas por ordem e a primeira ganha. Portanto, no modo SPA, devemos colocar o catch-all por último no módulo da aplicação.
Com o modo SPA desativado, ele apenas se liga aos caminhos dos ficheiros reais, permitindo que as suas rotas, depois disso, ainda apanhem tudo o que passa por elas.
Também lida com os detalhes menos glamourosos que eu particularmente não sinto vontade de reimplementar todas as terças-feiras:
ETageLast-Modified- Armazenamento em cache imutável para ativos construídos
- Armazenamento em cache de RAM com compressão zstd
- Redirecionamento SPA de contingência e
/favicon.icoQuando necessário - Não sirva uma compilação obsoleta acidental no modo de desenvolvimento
Esta é a dependência de tempo de execução da produção. É minúscula e apenas em Python.
Toda a maquinaria para construir e desenvolver a aplicação Vue permanece no projeto fonte.
Enter fastapi-vue-setup
Com essas peças no lugar, fastapi-vue-setup Está principalmente preocupado em remover a fiação repetitiva.
O comando básico é deliberadamente pouco entusiasmante: aponte-o para a sua pasta de aplicações, ou . Se você já está lá.
uvx fastapi-vue-setup my-app
Precisa alterar os números de porta que o seu produto, o Vite e o backend de desenvolvimento usam por predefinição? Execute com --ports. Sem isso, mantém as portas que você configurou anteriormente. E você pode sempre --listen No seu CLI ou scripts/devserver.py Para alterar isso em tempo de execução.
Mas há dois casos bastante diferentes escondidos por trás disso.
E fornece utilitários de suporte para o ponto de entrada CLI que a sua aplicação obtém, que pode também aceitar as suas próprias opções de linha de comando, algo que fastapi run Não pode fornecer.
Criando uma nova aplicação
Para um novo projeto, eu não quero fastapi-vue-setup Para impor um modelo Vue congelado da minha própria criação. Eu quero que ele crie um projeto Python configurado com o nome que eu dei, e a configuração Vue que eu escolhi:
- JavaScript ou TypeScript
- Vue Router ou nenhum router
- Pinia ou não
- Testes, linting e opções de formatação
- As outras opções suportadas pelo atual
create-vue
A ferramenta então constrói a integração FastAPI em torno da aplicação que o desenvolvedor realmente escolheu.
Isso é importante porque um modelo inevitavelmente fossiliza as preferências de alguém. Seis meses depois, a sua ideia de uma pilha completa moderna pode já pertencer a uma exposição de museu, e você fica preso com o que tem.
Eu preferiria ter a escolha.
Já tem uma aplicação?
Aqui, eu posso já ter um projeto real contendo código que eu preferiria não vaporizar. Ele pode ser criado com o mesmo script ou de forma independente, e o script irá corrigi-lo quando necessário.
O script de configuração deteta o projeto Python e o módulo back-end, deteta ou cria o front-end Vue, e corrige as partes que pode integrar com segurança com alterações mínimas.
Note
Mova o seu Vue existente completamente para baixo frontend/ Primeiro. Nós colocamos o Vue lá para evitar poluir a raiz com coisas do Node. Colocamo-lo lá para que o script corrija a aplicação existente em vez de criar uma nova.
Precisa atualizar para a versão mais recente? Basta executar fastapi-vue-setup Novamente, e irá instalar as novas funcionalidades que obteve.
Essa é uma das principais diferenças entre isto e um repositório de modelos.
Um modelo diz:
Garfo este repositório para começar o seu projetoEu precisava de ferramentas que também pudessem dizer:
Tudo bem, já estás em 30.000 linhas. Mostra-me onde está o paciente.
A sua aplicação está pronta para ser executada
uv run scripts/devserver.py
vite.config.js
Configure quais caminhos são proxyados para o backend. Por predefinição, isto apenas /apiEsta configuração apenas afeta a configuração de desenvolvimento, na produção tudo é encaminhado para o FastAPI.
JS_RUNTIME
Environment with value bun/deno/node or path to one of them (otherwise we find one).
Isso lança o servidor de desenvolvimento Vue/Vite e FastAPI com suporte de recarregamento. A integração Vite gerada encaminha os pedidos de back-end para o servidor de desenvolvimento Python. O seu navegador liga-se ao Vite.
Portanto, durante o desenvolvimento, eu ainda obtenho as coisas que realmente gosto sobre o ecossistema JavaScript.
Quando o desenvolvimento estiver concluído:
uv build # Installs and (re)builds everything
my-app # CLI entry point provided (in .venv)
O Vue é compilado, o resultado é incorporado na distribuição Python, e a máquina de compilação completou a sua missão. Pode uv publish O seu pacote, se assim o desejar, ou apenas copie para prod a partir de dist/Em seguida, instale e execute com:
uv tool install my-app-0.1.0.tar.gz
my-app
Tudo o que eu precisava de instalar previamente era UV E no sistema de desenvolvimento Nó Por si só. Eu não precisava de tocar npm De todo, e agora eu posso instalar ou executá-lo noutro lugar sem levar o workshop de JavaScript comigo.
Uma aplicação, finalmente
O que eu queria, em última análise, não era particularmente exótico.
- Eu queria escrever o backend em Python.
- Eu queria escrever o frontend em Vue.
- Eu queria Vite enquanto o estava a desenvolver.
E eu queria configurar e implementar uma coisa rapidamente.
Não é uma aplicação Python, mais uma aplicação JavaScript. Não são dois contentores unidos por nginx e suspeita mútua.
Um pacote Python de
Ele contém o frontend. FastAPI serve-o a partir da raiz do site sem engolir o resto da aplicação. O roteamento Vue funciona quando eu quero um SPA, e o roteamento de ficheiros simples permite que o meu backend mantenha os catch-alls para si mesmo, por exemplo, lidando com qualquer URL bonita com conteúdo renderizado do lado do servidor, como neste site. Isso, por sua vez, pode usar o Vue nos locais onde é necessário, dois mundos em perfeita harmonia.
A cadeia de ferramentas JavaScript faz o que uma cadeia de ferramentas é suposta fazer:
Ele constrói o software e, em seguida, sai do caminho.
A seguir, a sua pilha completa precisa de uma base de dados e o Kanta tem tudo coberto. Com esta cadeia de ferramentas, terá a sua aplicação a funcionar em pouco tempo.