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.
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.
nuxt dev — amit ad, és amit nemA 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.
nuxt dev-benRé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ény | Mit jelent | Mit tegyél |
|---|---|---|
vanBinding: true, tele van a lista | a beépített emuláció működik | semmit — készen vagy |
vanBinding: true, üres lista | emuláció megy, de nem találja a configot | ellenőrizd a wrangler.jsonc helyét, vagy add meg inline (lentebb) |
vanBinding: false | nincs beépített emuláció ezen a verzión | nitro-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',
},
},
})
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ül — useCloudflareEnv(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.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
--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ás | Lokális seed |
|---|---|
| D1 | wrangler d1 execute --local --file |
| KV | wrangler kv key put --local / kv bulk put --local |
| R2 | wrangler r2 object put --local |
| Durable Objects | nincs 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.
.dev.varsAz é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
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.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 |
|---|---|
env | a bindingok proxyjai — ugyanúgy használhatók, mint élesben |
cf | a request.cf mockja, éles-szerű adatokkal |
ctx | waitUntil és passThroughOnException implementáció |
caches | a Workers caches API emulációja |
dispose() | leállítja a workerd folyamatot — enélkül a szkript nem lép ki |
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.wrangler dev a .output-onEz 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:
nodejs_compat ellenére is van ilyen);process, __dirname és társaik használata, amit a dev szerver elnézett.# 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)
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."remote": trueEz 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ória | Bindingok |
|---|---|
| Ajánlott távoli módban | Browser Rendering, Workers AI, Vectorize, mTLS-tanúsítványok, Images, Dispatch Namespaces |
| Nem támogatott | Durable Objects, Workflows, vars, secretek, statikus assetek, verzió-metaadat, Analytics Engine, Hyperdrive, Rate Limiting |
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
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.wrangler dev --remoteEz 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ód | Cloudflare | a te gépeden |
| Iterációs sebesség | lassú (feltöltés minden változásnál) | gyors |
| Mit hitelesít | hálózati viselkedés, valódi élsebesség | egy-egy erőforrás valódi viselkedése |
| Korlát | zónánként 50 route a munkamenet alatt | a 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.
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ület | Lokálisan | Élesben | Súly |
|---|---|---|---|
| KV konzisztencia | azonnal konzisztens | eventually consistent | magas |
| Hyperdrive | közvetlen kapcsolat, nincs pool, nincs cache | pooling + lekérdezés-cache | magas |
| Isolate-életciklus | egy folyamat, kiszámítható | újrahasznált isolate-ek, hidegindítás | magas |
| CPU-limit | nincs | 10 ms / 30 s a csomagtól függően | magas |
| Bundle-méret | nem számít | 3 / 10 MB gzip | magas |
| Subrequest-limit | nincs | 50 / 1000 kérésenként | közepes |
| D1 | helyi SQLite, nulla latencia | hálózat, elsődleges régió | közepes |
| R2 | helyi fájlrendszer | hálózat, valódi objektumméret-kezelés | közepes |
| Queues | emulált batch és retry | eltérő időzítés és csoportosítás | közepes |
| Cache API | emuláció | PoP-onként külön cache | közepes |
request.cf | mockolt mezők | valódi geo- és TLS-adatok | alacsony |
| Időzóna | UTC (mint élesben) | UTC | — |
| Workers AI | mindig távoli | távoli | — |
wrangler typesA 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"
}
--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.Ö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.
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.nitro-cloudflare-dev modult telepítenéd egy friss Nuxt 4 projektbe. Jó ötlet?
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.
wrangler d1 execute bolt --file=./db/schema.sql. Mi történik?
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.
nuxt dev üres táblát lát. Két lehetséges ok?
(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.
wrangler dev --remote és a bindingonkénti "remote": true között?
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.
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.
TZ=UTC-vel, és ez mit old meg?
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.
Az AI-bindingok — a modellek mindig távol futnak, nincs lokális szimulációjuk.
getPlatformProxy(), és mi az a két opció, amit szinte mindig meg kell adni?
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).
nuxt build && wrangler dev, amit a nuxt dev nem?
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.
wrangler types --check, és miért CI-be való?
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.