18. modulLokális fejlesztés valódi bindingokkal
Nuxt for Devs · 18. modul

Lokális fejlesztés valódi bindingokkal

A fejlesztői környezet mindig hazudik valamennyit — a kérdés csak az, hogy miben és mennyit. Ez a modul felállít egy hűségi létrát a nuxt dev-től az élesig, megmutatja, melyik fokon mi kerül a helyére, és külön kitér a 2026 legfontosabb újdonságára: a bindingonként bekapcsolható távoli módra.

18.1A hűségi létra

Nem az a cél, hogy a legfelső fokon fejlessz — ott lassú és drága. A cél az, hogy tudd, melyik fokon vagy, és hogy a nap végén felmássz egy fokkal, mielőtt kiadod a munkát a kezedből.

hűség → ① nuxt dev HMR, gyors iteráció · Node-ban fut · nincs binding itt töltöd az idő 90%-át ② nuxt dev + emulált bindingok Miniflare-emuláció · HMR megmarad ide érdemes eljutni az első napon ③ wrangler dev a .output-on VALÓDI workerd · nincs HMR · build kell itt bukik ki a hiányzó Node API és a limit ④ remote: true bindingok kód lokálisan · adat élesből · valódi viselkedés amikor az emuláció nem elég hű ⑤ preview deploy valódi Worker, valódi hálózat, forgalom nélkül a 16-17. modul füsttesztje ⑥ éles az egyetlen igazság — de itt már a felhasználó a tesztelő
Minden fok más hibaosztályt fog meg, és mindegyik lassabb az alatta lévőnél. A napi munka az ①–②-n zajlik; a ③–⑤ a kiadás előtti kapuk.

18.2nuxt dev — amit ad, és amit nem

A Nuxt fejlesztői szervere Node-ban fut, HMR-rel. Ez a rövid visszacsatolási hurok, amiért egyáltalán érdemes Nuxtot használni: elmented a fájlt, és a böngészőben azonnal látod. Ezt semmilyen hűségi nyereményért nem szabad feladni a napi munkában.

Ami itt nincs a helyén: a Cloudflare-bindingok (alaphelyzetben), a workerd futásidő korlátai, a bundle-méret, a hidegindítás. Vagyis a hibák egy egész osztálya láthatatlan — pontosan az, amit a 16.1-es ábra a piros vonal alá tett.

18.3② Bindingok a nuxt dev-ben

Régen ehhez kellett a nitro-cloudflare-dev modul, ami a wrangler getPlatformProxy API-jával pótolta a bindingokat a dev szerverben. Ez ma már elavult — a projekt README-je maga írja ki, hogy „ez a modul már nem szükséges a Nitro legújabb verzióihoz”, mert a Nitro beépítve emulálja a Cloudflare-környezetet Miniflare-rel.

Mivel a Nuxt- és Nitro-verziók között ez a képesség éppen most mozdult át, ne higgy se nekem, se a blogbejegyzéseknek: ellenőrizd le harminc másodperc alatt a saját projekteden.

// server/api/_debug-bindings.get.ts — töröld, mielőtt élesbe megy
export default defineEventHandler((event) => {
  const cf = (event.context as any).cloudflare
  return {
    vanBinding: Boolean(cf?.env),
    kulcsok: cf?.env ? Object.keys(cf.env) : [],
  }
})
npx nuxt dev
curl http://localhost:3000/api/_debug-bindings
EredményMit jelentMit tegyél
vanBinding: true, tele van a listaa beépített emuláció működiksemmit — készen vagy
vanBinding: true, üres listaemuláció megy, de nem találja a configotellenőrizd a wrangler.jsonc helyét, vagy add meg inline (lentebb)
vanBinding: falsenincs beépített emuláció ezen a verziónnitro-cloudflare-dev modul, vagy 18.6 szerinti proxy

Ha nem akarsz külön wrangler.jsonc-t a dev-hez, a bindingokat inline is megadhatod a Nuxt-konfigban:

// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    preset: 'cloudflare_module',
    cloudflare: {
      wrangler: {
        vars: { APP_MODE: 'dev' },
        kv_namespaces: [{ binding: 'CACHE', id: 'local' }],
        d1_databases: [{ binding: 'DB', database_name: 'bolt', database_id: 'local' }],
      },
      wranglerEnv: 'preview',
    },
  },
})
Elnevezési figyelmeztetés a jövőre. A jelenlegi Nuxt 4 / Nitro 2 vonalon a bindingok az event.context.cloudflare.env alatt vannak. A Nitro v3 dokumentációja már az event.req.runtime.cloudflare.env utat írja. Ha most írod a kódot, vezesd be egy saját segédfüggvényen keresztüluseCloudflareEnv(event) —, és a v3-ra váltásnál egyetlen fájlt kell átírnod, nem hetvenet. Ez nem elméleti tanács: a 11. modul adatbázis-wrappere pontosan ezért néz ki úgy, ahogy.

18.4A lokális adat: hol lakik és hogyan töltöd fel

Az emulált bindingok mögött valódi, lemezre írt állapot van. Alapból a projekted .wrangler/state könyvtárában, KV / R2 / D1 / Durable Object alkönyvtárakra bontva.

# D1: séma és seed betöltése LOKÁLISAN
npx wrangler d1 execute bolt --file=./db/schema.sql --local
npx wrangler d1 execute bolt --command="SELECT count(*) FROM products" --local

# KV: egy kulcs, illetve tömeges betöltés JSON-ből
npx wrangler kv key put feature:uj-checkout "on" --binding=CACHE --local
npx wrangler kv bulk put ./db/kv-seed.json --binding=CACHE --local

# R2: fájl feltöltése a lokális bucketbe
npx wrangler r2 object put bolt-media/logo.png --file=./assets/logo.png --local

# tiszta lap: az egész lokális állapot eldobása
rm -rf .wrangler/state
A --local elfelejtése drága hiba. Ugyanezek a parancsok --local nélkül az éles erőforráson futnak le. Egy wrangler d1 execute … --file=./db/schema.sql a --local nélkül a termelési adatbázisodon hajtja végre a sémafájlt. Tedd npm-scriptbe őket, hogy a kapcsoló ne múljon az emlékezeteden: "db:seed": "wrangler d1 execute bolt --file=./db/seed.sql --local".
ErőforrásLokális seed
D1wrangler d1 execute --local --file
KVwrangler kv key put --local / kv bulk put --local
R2wrangler r2 object put --local
Durable Objectsnincs CLI — az alkalmazás kódján keresztül kell feltölteni

Ha másik könyvtárba akarod tenni az állapotot, a --persist-to a kapcsoló — de ekkor minden wrangler-parancsnál meg kell ismételned, különben a seed egy másik adatbázisba megy, mint amit a dev szerver olvas. Ez a leggyakoribb „de hát épp most töltöttem fel!” pillanat.

18.5Titkok lokálisan: .dev.vars

Az éles secretek wrangler secret put-tal mennek fel (17.8). Lokálisan viszont fájlból jönnek:

# .dev.vars — dotenv-formátum, .gitignore-ba VELE
NUXT_SESSION_PASSWORD=egy-legalabb-32-karakteres-fejlesztoi-jelszo
STRIPE_SECRET_KEY=sk_test_...
NUXT_OAUTH_GITHUB_CLIENT_SECRET=...
# környezetenként külön fájl
.dev.vars
.dev.vars.staging
A NUXT_ előtag itt is működik. A 12. modulból: a runtimeConfig minden kulcsa felülírható NUXT_-előtagos környezeti változóval, a beágyazott kulcsok aláhúzással. Vagyis a .dev.vars-ba írt NUXT_STRIPE_SECRET a runtimeConfig.stripeSecret-et fogja felülírni — ugyanúgy, ahogy élesben a wrangler secret. Ez a szimmetria az, amiért érdemes minden titkot a runtimeConfig-on keresztül olvasni, és soha közvetlenül process.env-ből.

18.6Szkriptek a Workeren kívül: getPlatformProxy()

Van egy egész munkakategória, ami nem a Workerben fut, mégis a bindingokra van szüksége: adatbázis-seedelés, egyszeri adatjavítás, migrációs eszközök, riportgenerálás. Ezekre a wrangler egy Node-ból hívható API-t ad, ami a háttérben ugyanazt a workerd-t indítja el.

// scripts/seed.ts — sima Node-szkript, mégis valódi bindingokkal
import { getPlatformProxy } from 'wrangler'

const { env, dispose } = await getPlatformProxy({
  configPath: './wrangler.jsonc',
  environment: 'staging',     // melyik env bindingjai
  persist: true,              // ugyanaz az állapot, mint a dev szerveré
})

await env.DB.prepare('INSERT INTO products (id, name) VALUES (?, ?)')
  .bind('p1', 'Bögre')
  .run()

await env.CACHE.put('feature:uj-checkout', 'on')

await dispose()          // FONTOS: leállítja a workerd folyamatot
Visszaadott mezőMi ez
enva bindingok proxyjai — ugyanúgy használhatók, mint élesben
cfa request.cf mockja, éles-szerű adatokkal
ctxwaitUntil és passThroughOnException implementáció
cachesa Workers caches API emulációja
dispose()leállítja a workerd folyamatot — enélkül a szkript nem lép ki
Ez az, amivel a Drizzle Kit is dolgozik. A migrációs eszközök nem a Workerben futnak, tehát nem érik el a bindingot — a getPlatformProxy a híd. A persist: true a kulcs: ettől ugyanazt a lokális állapotot látja, mint a nuxt dev. Ha elfelejted, a szkript egy külön, üres adatbázisba fog dolgozni, és percekig fogod keresni, hova tűnt a seed.

18.7wrangler dev a .output-on

Ez az első fok, ahol a kódod valódi workerd-ben fut — ugyanabban a binárisban, ami élesben is. Cserébe elveszíted a HMR-t: minden változtatás után újra kell buildelni.

npx nuxt build && npx wrangler dev

Nem fejlesztésre való, hanem kapunak. Ezen a fokon bukik ki:

# hasznos kapcsolók ezen a fokon
npx wrangler dev --test-scheduled     # /__scheduled útvonal a cron-handlerhez
npx wrangler dev --log-level debug
npx wrangler dev --local              # minden távoli binding ideiglenes kikapcsolása
# futás közben: D billentyű → Chrome DevTools (16.8)
Egy apró, de értékes részlet: a lokális futásidő TZ=UTC-vel indul, hogy a dátum- és időkezelő API-k ugyanúgy viselkedjenek, mint élesben — függetlenül attól, hogy a te géped budapesti időzónában van. Ez pont a 6. modul hidratálási eltéréseinek egyik forrását zárja ki: nem fordulhat elő, hogy lokálisan jó a dátum, élesben meg két órával elcsúszik. Cserébe: ha helyi időt akarsz megjeleníteni, azt neked kell explicit kezelned, mert a szerver mindenhol UTC-ben gondolkodik.

18.8④ Távoli bindingok: "remote": true

Ez a legfontosabb újdonság a lokális fejlesztésben, és sokan még nem tudnak róla. Eddig a választás így nézett ki: vagy minden lokálisan emulált (gyors, de hazudik), vagy az egész Worker felmegy a felhőbe (hű, de lassú). A távoli bindingokkal bindingonként dönthetsz.

// wrangler.jsonc — a kód lokálisan fut, EZ a binding élesre kapcsolódik
{
  "r2_buckets": [{
    "bucket_name": "bolt-media",
    "binding": "MEDIA",
    "remote": true
  }]
}

A lényeg: a Workered továbbra is lokálisan fut, csak az adott binding mögötti erőforrás változik lokális szimulációról valódira. Megmarad a gyors iteráció, de az adat és a viselkedés igazi.

KategóriaBindingok
Ajánlott távoli módbanBrowser Rendering, Workers AI, Vectorize, mTLS-tanúsítványok, Images, Dispatch Namespaces
Nem támogatottDurable Objects, Workflows, vars, secretek, statikus assetek, verzió-metaadat, Analytics Engine, Hyperdrive, Rate Limiting
A Hyperdrive hiánya közvetlenül érint téged, ha a 4. modul útját járod. Postgres + Hyperdrive esetén a bindinget nem tudod távoli módba kapcsolni — lokálisan a localConnectionString alapján közvetlenül csatlakozol az adatbázishoz, pooling és Hyperdrive-cache nélkül. Ez azt jelenti, hogy a Hyperdrive két legfontosabb tulajdonságát (kapcsolat-pooling és lekérdezés-cache) lokálisan sosem látod működni. Ha a teljesítménye vagy a cache-viselkedése a kérdés, arra csak a preview deploy (⑤ fok) ad választ.

A távoli bindingok környezetekkel kombinálva a helyes minta: ne az éles adatra kapcsolódj, hanem a stagingére.

{
  "env": {
    "staging": {
      "r2_buckets": [{
        "bucket_name": "bolt-media-staging",
        "binding": "MEDIA",
        "remote": true
      }]
    }
  }
}
npx wrangler dev -e staging   # lokális kód, staging-erőforrások
Három dolog, amivel tisztában kell lenned. (1) A távoli binding valódi adatot módosít — egy elgépelt DELETE a fejlesztői gépeden éles következménnyel jár. (2) Számlázódik: a műveletek a szokásos díjszabás szerint mennek. (3) Hálózati késleltetés lesz, tehát a lokális fejlesztés érezhetően lassul. Ezért érdemes a távoli módot célzottan, egy-két bindingre bekapcsolni, nem elvből mindenre — és a wrangler dev --local az a kapcsoló, amivel ideiglenesen mindet visszakapcsolod lokálisra.

18.9A régi teljes távoli mód: wrangler dev --remote

Ez a távoli bindingoktól különálló, régebbi mechanizmus: az egész Workeredet feltölti a Cloudflare preview környezetébe, és ott futtatja. Semmi nem emulálódik, minden binding automatikusan távoli.

--remote"remote": true binding
Hol fut a kódCloudflarea te gépeden
Iterációs sebességlassú (feltöltés minden változásnál)gyors
Mit hitelesíthálózati viselkedés, valódi élsebességegy-egy erőforrás valódi viselkedése
Korlátzónánként 50 route a munkamenet alatta 18.8-as tiltólista

Egy Nuxt-appnál a --remote ritkán a helyes válasz — általában vagy a ③ fok (valódi workerd lokálisan), vagy az ⑤ fok (preview deploy) a jobb üzlet. Akkor jön szóba, ha kifejezetten hálózat-specifikus viselkedést vizsgálsz: a request.cf valódi mezőit, geolokációt, TLS-részleteket, vagy a Cloudflare-hálózat cache-viselkedését.

18.10Amiben a lokális környezet hazudik — a teljes lista

A 16.7-ben már láttál egy rövidebb változatot. Itt a teljes, mert ez a modul erről szól:

TerületLokálisanÉlesbenSúly
KV konzisztenciaazonnal konzisztenseventually consistentmagas
Hyperdriveközvetlen kapcsolat, nincs pool, nincs cachepooling + lekérdezés-cachemagas
Isolate-életciklusegy folyamat, kiszámíthatóújrahasznált isolate-ek, hidegindításmagas
CPU-limitnincs10 ms / 30 s a csomagtól függőenmagas
Bundle-méretnem számít3 / 10 MB gzipmagas
Subrequest-limitnincs50 / 1000 kérésenkéntközepes
D1helyi SQLite, nulla latenciahálózat, elsődleges régióközepes
R2helyi fájlrendszerhálózat, valódi objektumméret-kezelésközepes
Queuesemulált batch és retryeltérő időzítés és csoportosításközepes
Cache APIemulációPoP-onként külön cacheközepes
request.cfmockolt mezőkvalódi geo- és TLS-adatokalacsony
IdőzónaUTC (mint élesben)UTC
Workers AImindig távolitávoli
Az utolsó két sor a jó hír. Az időzóna szándékosan UTC lokálisan is, és az AI-bindingok mindig valódiak, mert a modellek úgyis távol futnak. Ez két olyan eltérés, amivel nem kell számolnod — a többivel igen.

18.11Típusok: wrangler types

A bindingokat a TypeScript alapból nem ismeri. A wrangler ki tudja generálni őket a konfigból, és ezt érdemes a build-lánc részévé tenni, nem kézzel karbantartani:

npx wrangler types --env-interface CloudflareEnv
npx wrangler types --env staging --check   # CI: elavult-e a generált fájl
// package.json — hogy sose felejtsd el
"scripts": {
  "postinstall": "wrangler types && nuxt prepare",
  "typecheck": "wrangler types --check && nuxt typecheck"
}
A --check kapcsoló a CI-barát rész: nem generál, hanem ellenőrzi, hogy a bekommitolt típusfájl naprakész-e a konfighoz képest. Ha valaki felvesz egy bindinget és elfelejti újragenerálni, a CI szól — nem pedig három héttel később egy futásidejű undefined.

18.12Egy működő napi workflow

Összerakva a modult, így néz ki egy Nuxt + Cloudflare projekt package.json-je úgy, hogy a hűségi létra minden foka egy paranccsal elérhető legyen:

{
  "scripts": {
    // ① napi munka
    "dev": "nuxt dev",

    // lokális adat
    "db:reset": "rm -rf .wrangler/state && npm run db:migrate && npm run db:seed",
    "db:migrate": "wrangler d1 execute bolt --file=./db/schema.sql --local",
    "db:seed": "tsx scripts/seed.ts",

    // ③ valódi workerd — kiadás előtti kapu
    "dev:worker": "nuxt build && wrangler dev",

    // ④ staging-erőforrásokkal, lokális kóddal
    "dev:staging": "nuxt build && wrangler dev -e staging",

    // mérés (15. modul) és típusok
    "check:size": "wrangler deploy --dry-run --outdir=.bundle",
    "check:startup": "wrangler check startup",
    "typecheck": "wrangler types --check && nuxt typecheck",

    // ⑤ preview deploy + füstteszt (16-17. modul)
    "deploy:preview": "nuxt build && wrangler versions upload --preview-alias dev"
  }
}

A ritmus, ami ebből adódik: napközben dev; a feature végén egyszer dev:worker, hogy a workerd-specifikus hibák még nálad derüljenek ki; PR előtt check:size és check:startup; a merge után pedig a CI viszi tovább az ⑤ fokra.

Az egyetlen szokás, ami a legtöbbet fogja megspórolni: a dev:worker lefuttatása mielőtt PR-t nyitsz. Két perc, és megfogja a hibák azon osztályát, amit a teljes Node-alapú tesztkészleted (16. modul) elvileg sem lát. Ha a csapatban csak egy szabályt vezetsz be ebből a modulból, ez legyen az.

18.13Ellenőrizd magad

  1. A nitro-cloudflare-dev modult telepítenéd egy friss Nuxt 4 projektbe. Jó ötlet?
    ▸ Válasz

    Valószínűleg nem: a modul saját README-je szerint „már nem szükséges a Nitro legújabb verzióihoz”, mert a Nitro beépítve emulál Miniflare-rel. Előbb ellenőrizd le a 18.3-as debug-végponttal, hogy a te verziódon működik-e a beépített emuláció, és csak akkor nyúlj a modulhoz, ha nem.

  2. Lefuttatod: wrangler d1 execute bolt --file=./db/schema.sql. Mi történik?
    ▸ Válasz

    Az éles adatbázisodon fut le, mert lemaradt a --local. Ezért kell npm-scriptbe tenni ezeket a parancsokat: a kapcsoló ne az emlékezeteden múljon.

  3. Beseedelted a lokális D1-et, de a nuxt dev üres táblát lát. Két lehetséges ok?
    ▸ Válasz

    (1) A seed-parancsnál más --persist-to könyvtárat használtál (vagy megadtad az egyiknél és a másiknál nem), így két külön állapotba dolgoztok. (2) A getPlatformProxy-s szkriptben elfelejtetted a persist: true-t, így a szkript külön, ideiglenes állapotba írt.

  4. Mi a különbség a wrangler dev --remote és a bindingonkénti "remote": true között?
    ▸ Válasz

    A --remote az egész Workert feltölti és a Cloudflare-en futtatja (lassú iteráció, minden binding távoli). A "remote": true esetén a kód lokálisan fut, csak az adott binding mögötti erőforrás valódi — gyors marad az iteráció, és bindingonként döntesz.

  5. Postgres + Hyperdrive van a projektedben. Be tudod kapcsolni rá a távoli módot?
    ▸ Válasz

    Nem — a Hyperdrive a nem támogatott bindingok listáján van. Lokálisan a localConnectionString-gel közvetlenül csatlakozol, vagyis a pooling és a lekérdezés-cache lokálisan sosem látszik. Ha ezek viselkedése a kérdés, csak a preview deploy ad választ.

  6. Miért indul a lokális futásidő TZ=UTC-vel, és ez mit old meg?
    ▸ Válasz

    Hogy a dátum- és időkezelő API-k ugyanúgy viselkedjenek, mint élesben, függetlenül a géped időzónájától. Ezzel kiesik a 6. modul hidratálási eltéréseinek egyik klasszikus forrása: nem fordulhat elő, hogy lokálisan jó a dátum, élesben elcsúszik.

  7. Melyik binding fut mindig távolról, még lokális fejlesztésben is?
    ▸ Válasz

    Az AI-bindingok — a modellek mindig távol futnak, nincs lokális szimulációjuk.

  8. Mire jó a getPlatformProxy(), és mi az a két opció, amit szinte mindig meg kell adni?
    ▸ Válasz

    Arra, hogy Workeren kívüli Node-szkriptből (seed, migráció, adatjavítás, Drizzle Kit) elérd a bindingokat. A két opció: persist: true (hogy ugyanazt a lokális állapotot lássa, mint a dev szerver) és a dispose() hívása a végén (különben a workerd folyamat futva marad, és a szkript nem lép ki).

  9. Mit fog meg a nuxt build && wrangler dev, amit a nuxt dev nem?
    ▸ Válasz

    Mindent, ami a valódi workerd futásidőhöz kötődik: hiányzó vagy nem támogatott Node API, túl hosszú modul-scope inicializálás (1 s indulási keret), nem workerd-kompatibilis függőség, process/__dirname használat. Cserébe elvész a HMR — ezért ez kapu, nem fejlesztői mód.

  10. Mit csinál a wrangler types --check, és miért CI-be való?
    ▸ Válasz

    Nem generál, hanem ellenőrzi, hogy a bekommitolt binding-típusfájl naprakész-e a wrangler-konfighoz képest. Ha valaki felvett egy bindinget és elfelejtette újragenerálni, a CI azonnal szól — nem futásidejű undefined formájában derül ki hetekkel később.

Előző17. modul — Deploy Cloudflare Workers-re Következő 19. modul — Ami Workers-en máshogy megy