Repository navigation
Nuxt and Analog with void/nitro: missing nodejs_compat on native deploys, incomplete init notes, and test, type and size gaps #418
Description
These apply after #413, which adds the void/nitro module for PostgreSQL and MySQL apps.
Problem
| Area | What happens | |
|---|---|---|
| a | void deploy --platform cloudflare |
A pg/MySQL Nuxt app gets no nodejs_compat unless void.config.ts lists it |
| b | void init |
The printed Nuxt and Analog config does not deploy |
| c | Analog pg without void/nitro |
The build fails on pg-native before Void's hint |
| d | CI | No test runs a Nitro-built pg/MySQL Worker in workerd |
| e | nuxi typecheck |
TS2307 for @schema and TS2561 for cloudflareDev |
| f | Size | Analog MySQL Workers carry 3-4 copies of mysql2 |
a. Native deploys can miss nodejs_compat
void deploy --platform cloudflare writes the Worker config from void.config.ts (cloudflare.compatibility_flags) plus the Nuxt preset flags. The preset adds only nodejs_als. Nothing adds nodejs_compat for pg/MySQL, but the drivers need it. The managed void deploy adds it.
The docs page sets nodejs_compat in void.config.ts, so apps that copy the docs are fine. void init writes only nodejs_als. For pg and MySQL Nuxt apps without the flag, the generated .void-wrangler.jsonc held only nodejs_als.
Nitro itself reads only wrangler.json, wrangler.jsonc or wrangler.toml, never .void-wrangler.jsonc. So every Nuxt build logs:
[nitro] WARN [cloudflare] Node.js compatibility is not enabled.
Nitro then uses unenv's Node stubs. void/nitro works around this only for the driver and Void's own node:async_hooks. Other server code that imports Node modules gets the stubs.
b. void init notes do not give a working config
The Nuxt note prints only nitro: { modules: ["void/nitro"] } and vite: { plugins: [voidPlugin()] }. The Analog note prints only analog({ nitro: { modules: ["nitro-cloudflare-dev", "void/nitro"] } }). Neither has preset: 'cloudflare-module' or cloudflareDev: { configPath: './.void-wrangler.jsonc' }, which the docs pages have.
Applied as printed to fresh create-nuxt and create-analog apps:
- Nuxt dev, pg route: 500
env: Cloudflare env is unavailable. Use void runtime bindings inside ... - Nuxt build:
Nitro preset: node-server. The uploaded Worker fails at start:No such module "unhead/server". - Analog build: also
node-server. The Worker fails at start:No such module "void/_env".
With the preset and cloudflareDev added, both apps work in dev and on a managed deploy (60 of 60 requests ok).
c. Analog pg without void/nitro
An Analog pg app with a .server.ts page load and no void/nitro (the old docs config) fails the Nitro build before Void's runtime hint can show:
[nitro] ERROR Error: Cannot resolve "pg-native" from ".../node_modules/pg/lib/native/client.js" and externals are not allowed!
Nuxt pg/MySQL and Analog MySQL without the module do show the hint ("add 'void/nitro' to the Nitro modules").
d. No CI test for a Nitro-built pg/MySQL Worker
packages/void/test/unit/nitro.test.ts checks the plugin hooks (:94) and runs the request scope in Node (:115). The Nuxt and Analog playgrounds use D1. Nothing builds a Nitro cloudflare-module Worker with pg or MySQL and runs it in workerd. The load checks so far were manual.
e. nuxi typecheck errors in a fresh Nuxt 4 app
Following the docs in a fresh create-nuxt app (Nuxt 4.6.1):
server/api/users.get.ts(1,23): error TS2307: Cannot find module '@schema' or its corresponding type declarations.
nuxt.config.ts(9,5): error TS2561: Object literal may only specify known properties, but 'cloudflareDev' does not exist in type 'ResolveNuxtNitroConfig<NitroConfig>'. Did you mean to write 'cloudflare'?
The TS2307 comes from the app project. Nuxt's typed $fetch routes import server/api/* into it, and that project's paths come from Nuxt's top-level alias, not from nitro.alias. A top-level alias: { '@schema': resolve(import.meta.dirname, 'db/schema.ts') } clears it. Both errors also occur with the docs on main.
f. Several mysql2 copies in Analog MySQL Workers
Managed Worker upload sizes:
| App | Upload | gzip | mysql2 copies |
|---|---|---|---|
| Nuxt MySQL (npm) | 3571.09 KiB | 1236.34 KiB | 3 |
| Analog MySQL (npm) | 4843.69 KiB | 1578.66 KiB | 3 |
| Analog MySQL (pnpm) | 5600.98 KiB | 1899.53 KiB | 4 |
| Analog MySQL (pnpm), driver kept external in Vite's SSR build (prototype) | 4806.03 KiB | 1566.39 KiB | 3 |
The copies are the cron/queue bundle, the migration handler and Nitro's void/db chunk. With pnpm, Analog's Vite SSR build cannot resolve mysql2 from the app root, so it also bundles the driver into the page-load chunk (users.server-*.js). Keeping it external saves about 333 KiB gzip. All sizes are under the Workers Free limit (3 MB compressed), but a growing app gets close.
Repro
- a.
void initin a Nuxt app, setdatabase: 'pg', keep the generatedvoid.config.ts(nodejs_alsonly), addvoid/nitroand the preset, thenvoid deploy --platform cloudflare. - b. Fresh
create-nuxt/create-analogapp,void init, apply the printed note as is,vp devand build. - c. Analog pg app with a
.server.tsload that usesvoid/db,nitro.alias['@schema']and novoid/nitro; build. - e. Fresh
create-nuxtapp, docs config,server/api/users.get.tsimporting@schema; runnpx nuxi typecheck. - f. Build an Analog MySQL app with pnpm and count
mysql2copies in the Worker output.
Cause
- a.
packages/void/src/cli/deploy-cloudflare-static.ts:136passes onlypreset.cloudflareCompatibilityFlags;packages/void/src/cli/preset.ts:125-127gives Nuxt['nodejs_als']. The managed path addsnodejs_compatfor non-D1 dialects inpackages/void/src/cli/deploy-helpers.ts:176-199.packages/void/src/cli/init.ts:1322writes onlynodejs_als. Nitro'sreadWranglerConfig(nitropackdist/presets/cloudflare/utils.mjs:174-176) looks only forwrangler.json,wrangler.jsoncandwrangler.toml;packages/void/src/plugin-drizzle.ts:441-442notes this. - b.
packages/void/src/cli/init.ts:2373-2402. On main the Nuxt note had the same gap, and Analog fell back to the generic Vite note. - c. Nitro bundles
pgwithout Void's driver build, andpg/lib/native/client.jsrequirespg-native. The hint is inpackages/void/src/runtime/db.ts:59-70, which this build never reaches. - d.
packages/void/test/unit/nitro.test.ts;playground/nuxtandplayground/analogare D1 apps. - e. Nuxt types server routes for the app project from
nuxt.options.alias;cloudflareDevis not in Nuxt's Nitro config type. - f. The
void/dbtemplate importsdrizzle-orm/mysql2by path (packages/void/src/plugin-drizzle.ts:18), and its baremysql2import is inlined by Vite's SSR build when it cannot be resolved from the app root.
Suggested fix
- a. In the native framework deploy, add
nodejs_compatfor pg/MySQL as the managed path does. Havevoid initwrite it for pg/MySQL apps. - b. Put
preset: 'cloudflare-module'andcloudflareDevin both notes, or link the framework docs page. - c. Add a short Analog troubleshooting note that names
void/nitro. - d. Add one test that builds a tiny Nitro
cloudflare-moduleapp with PGlite or the fake MySQL server and runs concurrent requests in Miniflare. - e. Docs: use a top-level Nuxt
aliasfor@schema, and say how to typecloudflareDev(or that the error is harmless). - f. For Nitro frameworks, keep the dialect's driver external in Vite's server build so Nitro uses
void/nitro's shared driver bundle.
Evidence
- a. Generated
.void-wrangler.jsoncfor Nuxt pg and MySQL apps held onlynodejs_als; the Nitro warning is in their build logs. Native deploy flags confirmed by code; a native deploy was not run. - b. Runs on fresh apps with the packed head of fix(void): make PostgreSQL and MySQL void/db work across frameworks, builds and deploys #413: outputs above.
- c. Build logs at the head of fix(void): make PostgreSQL and MySQL void/db work across frameworks, builds and deploys #413 and at the commit before
void/nitro: same error. - d. Code read.
- e.
nuxi typecheckruns in a fresh Nuxt 4.6.1 app with no alias, withnitro.alias, and with a top-level alias. - f. Managed deploy captures for npm, pnpm, Yarn and Bun layouts; the prototype kept the driver external in the app's Vite config.
- All items apply after fix(void): make PostgreSQL and MySQL void/db work across frameworks, builds and deploys #413. b (Nuxt), c and e also occur before
void/nitro.
🤖 Generated with Claude Code
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
fix(void): build Nitro pg/MySQL Workers with Node compatibility and e…
fix(void): build Nitro pg/MySQL Workers with Node compatibility and e…
fix(void): build Nitro pg/MySQL Workers with Node compatibility and e…
fix(void): build Nitro pg/MySQL Workers with Node compatibility and e…
fix(void): build Nitro pg/MySQL Workers with Node compatibility and e…
fix(void): build Nitro pg/MySQL Workers with Node compatibility and e…
fix(void): build Nitro pg/MySQL Workers with Node compatibility and e…
fix(void): build Nitro pg/MySQL Workers with Node compatibility and e…
fix(react): keep the visitor's query in useRouter().url on static pag…