Vue-Python

FastAPI siirtyy täyteen stackiin

Tarina siitä, kuinka Vue näki käärmeen ja rakastui siihen.

FastAPI on yksi niistä ohjelmistoista, jotka herättävät minussa epäilyksiä, koska Python-takapään tarina on Liian Miellyttävää. Flaskin/Expressin tyyliin kuuluvat tyypin vihjeet muuttuvat analysoinniksi ja validoinniksi. Asynkroninen toiminta automaattisten uudelleenlatausten kanssa toimii ilman, että kutsuu esiin eldritch-kehyksen konfiguraatiokäsikirjaa. Lisää siihen OpenAPI-skemmat ja automaattiset uudelleenlataukset, ja voit siirtyä eteenpäin git init Respektiablesi API:hen ennen kuin kahvinkeitin on saanut päätökseen käynnistysprosessinsa.

Silloin tarvitset etusivun.

Historiallisesti tämä on paikka, jossa neonvalojen valaisema moottoritie päättyi äkillisesti betoniseinään.

FastAPI Se on hyvin taitava API:ien kanssa, mutta se ei varsinaisesti kykene palvelemaan etusivustoa sivuston juuritasolla, ellei sitä erikseen haluta Kaikki Pyynnöt reititetään StaticFilesJa SPA-tuki on kuin kuuluisi. Voit tarjota tiedostoja, renderoida malleja tai liittää haluamasi laitteiston, mutta viimeinen silta modernin JavaScript-etusivun ja Python-sovelluksen välillä jätettiin lähinnä lukijan harjoitukseksi.

Ja tuo lukija olin yhä enemmän minä.

Sillä välin etusivun maailmassa

Käytän Vuea tähän työhön. Vue toimii kutakuinkin samalla alueella kuin React ja Svelte: komponenttipohjaiset käyttöliittymät, reaktiivinen tila, asiakkaan puolen reititys ja tavalliset modernit työkalut, joilla lähdetiedostojen kasa voidaan muuntaa jotakin, mitä selain pystyy suorittamaan.

Se fastapi-vue Pakettia voidaan kuitenkin käyttää myös muiden kanssa, joten kuvailen ehdokkaita lyhyesti.

React

React on se 400-kiloinen gorilla. Sillä on valtava ekosysteemi, vastaus kaikkeen ja yleensä kolme muuta vastausta, jotka ovat ristiriidassa ensimmäisen kanssa.

Sen suurin käytännöllinen etu on yksinkertaisesti painovoima: monet kehittäjät tuntevat sen, monet kirjastot kohdistuvat siihen, ja monet esimerkkikoodit alkavat sillä npm install reactSe on paljon suositumpi kuin Vue, joten Reactin ja FastAPIn suhteellisen heikko integraatio kertoo paljon itsessään.

Jopa virallinen FastAPI-template – joka julkaistiin vasta muutama viikko sitten – on pohjimmiltaan malli: valmiiksi valittu React-stack, josta aloitat, eikä työkaluja, jotka pystyisivät integroimaan sen olemassa olevaan Python-sovellukseen ja hoitamaan päivitykset.

Svelte

Svelte käyttää enemmän kääntäjään pohjautuvaa lähestymistapaa. Sen sijaan, että se lähettäisi melko paljon käsiteltäväksi selaimeen, se muuntaa komponentit build-vaiheessa. Tulos pystyy silti toimimaan ilman Nodea tuotannossa.

Se vaatii hieman kikkailua oikean reaktiivisuuden saavuttamiseksi, ja sen omassa kielessä käytetään dollari-merkkiä ($) osoittamaan, mikä tarvitsee päivityksen. Toisaalta tämä mukautettu kieli mahdollistaa lyhyemmän koodin kuin kilpailijoiden ratkaisuissa.

Vue

Vuessa on se, josta pidän erityisesti: riittävästi rakennetta suurten sovellusten rakentamiseen, mutta ilman, että HTML katoaa useiden geologisten kerrosten alle JavaScriptin muodossa. Reactiivisuus sen Pinia-varaston kanssa toimii ihan vain niin kuin pitääkin, eikä se ole tiellä. Ja kun tarvitset ehdottoman viimeisen suorituskyvyn, se integroituu hyvin ei-reaktiivisiin rakenteisiin. Ei monimutkaista käärimistä tai useState:a. Ja tällainen boilerplate on tarpeen.

Ja se toimii nopeasti, mikä ei ole useimpien React-sovellusten kohdalla näin.

Sen virallinen create-vue työkalu antaa minulle myös jotain erityisen hyödyllistä tässä: se voi kysyä interaktiivisesti, tulisiko sovelluksen käyttää TypeScriptiä, Vue Routeria, Piniaa, Vitestiä, Playwrightia/Cypressiä, ESLintiä, Prettieria ja muita tavallisia työkaluja.

Palaan tähän myöhemmin.

Vue-Svelte-React
Pienen verkkolomakkeen ratkaiseminen, joka esiintyy usein sovelluksissa: avattava valikko, josta valitaan muokattava tietue, sekä sen kenttien syöttöruudut. Svelte tarjoaa lyhyimmän koodin, mutta Vue on tavallinen selainindeksi .html-tiedosto, ja niiden pituus onkin sama. Ja sitten tulee React, jonka koodi on liian pitkä mahtuakseen kuvakaappaukseen. Kaikki työt tehdään Reactissa, ja tämä kuva näyttää syyn tähän.

Miten me oikeastaan otamme tämän käyttöön?

Kun minulla on FastAPI yhdessä päädyssä ja Vue, React tai Svelte toisessa, on olemassa muutamia perustavanlaatuisesti erilaisia tapoja, joilla voin asettaa tuloksen tuottavan sovelluksen palvelimelle.

Vaihtoehto 1: antautuminen Nodeille

Ilmeinen vastaus JavaScript-maailmassa on asettaa myös JavaScript-palvelin tuotantoon.

Siinä on paljon järkeä, jos haluan todella Node-takapäätteen. On todellinen etu, että käytetään yhtä kieltä ja siihen läheistä sukua olevia työkaluja verkon molemmin puolin. Jos tiimini haluaa käyttää TypeScriptiä kaikkialla, se on täysin johdonmukainen arkkitehtuuri.

En tee sitä.

Valitsin FastAPI:n, koska haluan kirjoittaa backendin Pythonilla. Toisen runtime-ympäristön asentaminen sen lisäksi vain etusivun sisältöjen toimittamiseksi tuntuu siltä kuin palkkaisi toisen kokin kantamaan lautasia keittiöstä ruokasaliin.

Kuva
Haluanko gigatavut node_modules-tiedostoja ja tämän tuotantopalvelimelleni? Ei todellakaan.

On myös pieni asia JavaScript-riippuvuuksien maailmassa. Se on liian raskas, ylläpitää vähän yhteensopivuutta ja on usein viallinen. Vaikka nvm Voit helposti asentaa oikean Node-version, mutta se silti vie valtavan määrän tilaa, jota isännöidyt palvelimet eivät usein tarjoa.

Node on hyödyllinen kehityskoneellani. Vite on erinomainen. create-vue Se on erinomainen. Rakennusympäristö tekee työnsä erittäin hyvin.

Se ei tarkoita, että haluaisin sitä tuotantokoneeseeni.

Vaihtoehto 2: Renderoida kaikki palvelimella

Toisessa ääripäässä voin jättää SPA:n kokonaan väliin ja luoda HTML-koodia Pythonilla.

Tämä ansaitsee enemmän kunnioitusta kuin sille joskus annetaan. Kaikki sovellukset eivät tarvitse asiakkaan puolen sovellusympäristöä, reititintä ja useita megatavuja tukevaa infrastruktuuria.

Työkalut, kuten htmx, pystyvät viemään palvelimella renderoidun HTML:n yllättävän pitkälle lisäämällä HTTP-pyyntöjä, vaihdoksset, siirtymät, WebSocketsit ja palvelimen lähettämät tapahtumat suoraan HTML-attribuuttien kautta. Yhdistä html5taggeriin luodaksesi näitä asiakirjoja ja HTML-fragmenteja palvelimella, ja sinulla on sivusto, joka toimii kaikkialla ja jota voidaan lukea sosiaalisessa mediassa, hakukoneissa ja asiamiehillä yhtä hyvin.

Sivustoille, joita hallitsevat asiakirjat, lomakkeet ja suhteellisen yksinkertaiset vuorovaikutukset, pidän tästä arkkitehtuurista. Selain pyytää jotakin, Python tuottaa HTML:tä, eikä kukaan tarvitse rakennusputkea, joka pystyisi lähettämään Mars-luotaimen.

Vasanko.com on rakennettu tämän menetelmän pohjalta, ja siinä käytetään Vue-teknologiaa vain hallintaliittymässä, jossa tarvitaan parempaa interaktiivisuutta. Tämä CMS toimii FastAPI-Vue-asetuksella, mutta kaikki sivut renderoidaan palvelinpuolella Pythonilla.

Vaihtoehto 3: käytä kaksi palvelinta

Yleinen kompromissi on näin ollen seuraava:

  • FastAPI suorittaa API:n.
  • Vite tai jokin muu JavaScript-palvelin suorittaa etusivun
  • Käänteinen välityspalvelin yhdistää ne molemmat yhden verkkotunnuksen alle.
  • Tuotannossa on nyt kaksi sovellusta, kaksi riippuvuusketjua, kaksi prosessia ja toinen konfiguraatiotiedosto, joka pitää ne yhdessä.

Tämä toimii, mutta se ei ole kovin kaunis.

Selain ei välitä, onko app.js Se lähetettiin Pythonin, Node.js:n, Caddyn, Nginxin tai riittävän päättäväisen leivänpaahtimen toimesta. Kun etusivu on rakennettu, tulokseksi saadaan staattista HTML:tä, CSS:tä, JavaScriptiä, fontteja ja kuvia.

Joten miksi pitää tehdas käynnissä sen jälkeen, kun tuote on jo lähtenyt kokoonpanolinjalta?

Rakenna JavaScriptilla, käytä Pythonia

Siitä tuli keskeinen ajatus fastapi-vue-setup.

Haluan JavaScript-työkalut, jotka ovat todella hyödyllisiä:

  • create-vue luoda etusivu
  • Vite kehitysserverille
  • Välittömät kuumat uudelleenlataukset muutosten jälkeen
  • Tavallinen Vue-kokoontelu Node-, Bun- tai Deno-alustalla

Ja sitten haluan sen pois.

Tuotantotuotteen tulisi olla Python-paketti, joka sisältää jo kootun etuosan. Paketin asentaminen ei vaadi Nodea, npm:ää, Viteä, Vue-lähdekoodia tai Gravitational Anomalyn, joka on perinteisesti säilytetty hakemistossa node_modules.

Se on juuri sitä, kuinka fastapi-vue-setup Rakentaa projekteja tänään: uv build Suorittaa frontend-rakennuksen ja sisällyttää sen tulokset Python-pakettiin. Generoidun Hatch-konfiguraation käsittelee frontend-build Se toimii artefaktina ja kytkee lähdekoodin jakelun rakentamiseen, rajoittaen samalla paketin sisältöä itse Python-pakettiin.

Ero on erityisen tärkeä sdistille. En halua, että lähdekoodin jakelu tarkoittaa sitä, että “tässä on Python, tässä on koko Vue-kehityspuu, nyt asenna Node ja kokoa sovellus itse”. Etuosa on jo koottu ennen kuin jakelu lähtee koneeltani.

Paketti sisältää sen, mitä sen toimintaan tarvitaan, ei kaikkea, mitä minä satun tarvitsemaan sen rakentamiseen.

Se jättää käyttöönoton näyttämään ihan tylsältä:

uvx my-app

Ei Node-asennusseremoniaa kohdekoneella. Ei npm installEi frontend-palvelinta. Ei JavaScript-riippuvuuspuuta, joka herää kolme kuukautta myöhemmin ja pyytää ruokkimista.

Paketti käynnistää FastAPI:n, ja FastAPI tarjoaa sovelluksen.

Se toinen inhottava ongelma

Etusivun rakentaminen oli vain puolet koko jutusta.

StaticFiles ei ole varsinaisesti frontend-palvelin

FastAPI paljastaa Starletten StaticFilesJa tavallisten staattisten resurssien osalta se tekee juuri sen, mitä sen nimi lupaa:

app.mount("/static", StaticFiles(directory="static"))

Ongelmat alkavat, kun etusivu on itse verkkosivusto.

Vue-sovellus haluaa tavallisesti /Se saattaa myös haluta /login, /settings, /dashboard/coffee-reactor/7ja kaikki muu, joka kuuluu asiakkaan puolen reitittimelle.

Mutta asentaminen StaticFiles kello / Käytännössä tämä antaa asennetulle sovellukselle koko jäljellä olevan URL-tilan. FastAPIn oma ylläpitäjä selitti ongelman vuosia sitten: asenna se juurihakemistoon, ja staattinen sovellus ottaa sen haltuunsa, joten sen alapuolella olevat normaalit polkuoperaatiot eivät enää toimi odotetusti.

Ja tarvitsemme:

  • Etusivun rakentaminen osoitteessa /*
  • FastAPI käsittelee silti
    • /api/...
    • /openapi.json
    • minkä tahansa muun mielivaltaisen reitin

Tämä ei ole sama ongelma kuin tarjoilu /static/logo.svg.

FastAPI on hiljattain parantanut omaa etusivustotukeaan, ja nykyinen dokumentaatio ohjaa nyt etusivustosovellukset selkeästi kohti app.frontend() Eikä pelkästään tavallista StaticFilesMutta fastapi-vue Se edeltää kyseistä ratkaisua, ja sen tehtävät ovat hieman erilaiset: se on tämän kokonaan paketoidun järjestelmän pieni suorituskykyinen osa.

Fastapi-Vuen suoritusaika

Seuralainen fastapi-vue Paketti tarjoaa mukautetun Frontend Käsittelijä asentamisen sijasta StaticFiles Sovelluksen yli.

SPA-tilassa se voi palauttaa index.html SPA-tilassa se voi palauttaa polkuja, jotka kuuluvat asiakkaan puolen reitittimeen, eikä vaadi fyysistä tiedostoa kyseisellä nimellä.

Note

Siitä syystä, miten FastAPI-reititys toimii, sovelluksen asennukset kattavat kaiken kyseisen polun alapuolella olevan sisällön. Loput reitit kokeillaan järjestyksessä, ja ensimmäinen voittaa. Siksi SPA-tilassa meidän on sijoitettava catch-all viimeiseksi sovellusmoduuliin.

Kun SPA-tila on pois päältä, se sitoutuu vain varsinaisten tiedostojen polkuihin, jolloin reitit sen jälkeen pystyvät silti nappaamaan kaiken, mikä jää läpi.

Se huolehtii myös vähemmän miellyttävistä yksityiskohdista, joita en erityisemmin haluaisi toteuttaa uudelleen joka tiistai:

  • ETag ja Last-Modified
  • Muuttumaton välimuisti rakennetuille resursseille
  • RAM-välimuisti zstd-pakkauksella
  • SPA-reitityksen varakäyttö ja /favicon.ico Tarvittaessa
  • Älä tarjoile vahingossa vanhentunutta koodia kehitysympäristössä

Tämä on tuotannon aikakeston riippuvuus. Se on pieni ja vain Pythonia varten.

Kaikki Vue-sovelluksen rakentamiseen ja kehittämiseen tarvittavat koneet pysyvät lähdeprojektissa.

Kirjoita fastapi-vue-setup

Kun nämä osat ovat paikallaan, fastapi-vue-setup Kyse on lähinnä toistuvien johdotusten poistamisesta.

Peruskomento on tarkoituksellisen tylsä: osoita se sovellusten kansioon, tai . Jos olet jo siellä.

uvx fastapi-vue-setup my-app

Tarvitseeko muuttaa portinumeroita, joita tuotanto- ja Vite-ympäristö sekä kehitysbackend käyttävät oletusarvoisesti? Suorita komento --portsIlman sitä se säilyttää aiemmin määrittämäsi portit. Ja voit aina --listen CLI-liittymässäsi tai scripts/devserver.py Muuttaaksesi sen suoritusajan aikana.

Mutta sen takana on kaksi melko erilaista tapausta.

Ja se tarjoaa tukityökaluja sovelluksesi CLI-sisäänkäynnille, joka voi sitten ottaa vastaan myös omat komentorivivaihtoehtosi, jotain, mitä fastapi run Ei voi tarjota.

Uuden sovelluksen luominen

Uuden projektin kohdalla en halua fastapi-vue-setup En halua määrätä uuden projektin käyttämään omaa jäädytettyä Vue-mallia. Haluan, että se luo Python-projektin, joka on määritetty antamallani nimellä, ja käyttämällä haluamani Vue-asetuksia:

  • JavaScript vai TypeScript
  • Vue Router vai ei reititintä
  • Pinia vai ei
  • Testaus, linting ja muotoiluvalinnat
  • Muut vaihtoehdot, joita nykyinen create-vue tukee

Työkalu sitten rakentaa FastAPI-integraation sen sovelluksen ympärille, jonka kehittäjä on itse asiassa valinnut.

Tällä on merkitystä, koska malli väistämättä kiteyttää jonkun mieltymykset. Kuusi kuukautta myöhemmin sen käsitys modernista täysipalveluista saattaa jo kuulua museon näyttelyyn, ja joudut tyytymään siihen, mitä sinulla on.

Hankkisin mieluummin valinnanvapauden.

Asennus valmis

Onko sinulla jo sovellus?

Tässä vaiheessa minulla saattaa jo olla todellinen projekti, joka sisältää koodia, jota en haluaisi hävittää. Se voidaan luoda samalla skriptillä tai erillisenä, ja skripti korjaa sen tarvittaessa.

Asennusskripti tunnistaa Python-projektin ja taustamoduulin, tunnistaa tai luo Vue-etusivun ja korjaa osia, jotka voidaan integroida turvallisesti pienin muutoksin.

Note

Siirrä olemassa oleva Vue kokonaan alkuperäisen hakemiston alle frontend/ Ensinnäkin asetamme Vue:n sinne, jotta se ei saastuttaisi rootia Node-asioilla. Asetamme sen sinne, jotta skripti voi korjata olemassa olevaa sovellusta sen sijaan, että luotaisiin uuden.

Tarvitsee päivittää uusimpaan versioon? Aja vain fastapi-vue-setup Uudelleen, ja se päivittää saamansa uudet ominaisuudet.

Se on yksi tämän ja mallipankin välisistä merkittävistä eroista.

Malli sanoo:
Kloonaa tämä repository aloittaaksesi projektisi

Tarvitsin työkaluja, jotka pystyvät myös sanomaan:
Hyvä on, sinulla on jo 30 000 riviä koodia. Näytä minulle, missä potilas on.

Sovelluksesi on valmis käyttöön

uv run scripts/devserver.py

vite.config.js

Määritä, mitkä polut välitetään backkikselle. Oletusarvoisesti tämä on vain /api. Tämä konfiguraatio vaikuttaa vain kehitysympäristöön. Tuotannossa kaikki päätyy FastAPI:lle.

JS_RUNTIME

Envimuuttuja arvolla bun/deno/node tai polku johonkin niistä (muussa tapauksessa etsimme sellaisen).

Se käynnistää Vue/Vite-kehityspalvelimen ja FastAPI:n uudelleenlataustuen kanssa. Generoidut Vite-integraatioproxiet välittävät taustapyynnöt Python-kehityspalvelimelle. Selaimesi muodostaa yhteyden Viteen.

Joten kehityksen aikana saan silti asioita, joista todella pidän JavaScript-ekosysteemissä.

Hei maailma, yhdistän FastAPI:n

Kun kehitys on päättynyt:

uv build  # Installs and (re)builds everything
my-app    # CLI entry point provided (in .venv)

Vue on käännetty, build on sisällytetty Python-pakettiin, ja koneisto on suorittanut tehtävänsä. Voit nyt uv publish pakettisi, mikäli niin haluat, tai kopioi se vain tuotantoon dist/-kansiosta. Sen jälkeen asenna ja suorita näin:

uv tool install my-app-0.1.0.tar.gz
my-app

Ainoa asia, joka tarvitsi asentaa etukäteen, oli UV ja devikoneella Node. Ei ollut tarvetta koskea npm:ään ollenkaan, ja nyt voin asentaa tai käyttää sitä jossakin muualla tarvitsematta ottaa JavaScript-työkaluja mukaan.

Vihdoinkin yksi sovellus

Se, mitä lopulta halusin, ei ollut erityisen eksoottista.

  • Halusin kirjoittaa backendin Pythonilla.
  • Halusin kirjoittaa frontin Vuella.
  • Halusin käyttää Viteä kehityksen aikana.

Ja halusin asentaa ja ottaa käyttöön yhden asian nopeasti.

En Python-sovellus plus JavaScript-sovellus. Ei kahden kontin yhdistämistä nginxillä keskinäisessä sotkussa.

Alle megan Python-paketti, joka Vain Toimii™.

Se sisältää frontin. FastAPI tarjoaa sen sivuston juuresta nielemättä samalla loppua sovelluksesta. Vue-reititys toimii, kun haluan SPA:n, ja tavallinen tiedostoreititys mahdollistaa backendin pitämään catch-all-routet itsellään, esimerkiksi tarjoamalla kaikissa pretty URLeissa palvelimella renderöityjä dokumentteja, kuten tällä sivustolla. Tämä puolestaan saattaa käyttää Vuea tarpeen mukaan – kaksi maailmaa täydellisessä harmoniassa.

JavaScript-toolchain tekee sen, mitä työkaluketjun oletetaan tekevän:

Se kääntää ohjelmiston ja sitten poistuu tieltä.

Seuraavaksi Full Stack tarvitsee tietokannan, ja Kanta tarjoaa ratkaisun. Tämän frameworkin avulla saat sovelluksesi toimimaan kahvitauon aikana.