T
TanStack3mo ago
flat-fuchsia

Monorepo + Cloudflare workers

Hey all! Looking to bounce some ideas and possibly guidence on how to make the setup in title work. We run and NX monorepo and want to host on cloudflare workers. Running into some config issues. We could not find any documentation about the config options for the tanstackStart vite plugin and all previous examples refer to an app.config.ts file, which seems irrelevant? (https://developers.cloudflare.com/workers/framework-guides/web-apps/tanstack/) (https://tanstack.com/start/latest/docs/framework/react/hosting#cloudflare-pages) We have this vite.config.ts:
import { defineConfig } from 'vite'
import tsConfigPaths from 'vite-tsconfig-paths'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { workspaceRoot } from '@nx/devkit'
import { join } from 'path'

export default defineConfig({
root: __dirname,
cacheDir: '../../node_modules/.vite/apps/insights',

server: {
port: 4204,
host: 'localhost',
fs: {
allow: [workspaceRoot],
},
},

preview: {
port: 4301,
host: 'localhost',
},

plugins: [
tsConfigPaths({
root: workspaceRoot,
}),
tanstackStart({
tsr: {
srcDirectory: join(__dirname, 'src')
},
}),
],

build: {
outDir: './dist/apps/insights',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
},
})
import { defineConfig } from 'vite'
import tsConfigPaths from 'vite-tsconfig-paths'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { workspaceRoot } from '@nx/devkit'
import { join } from 'path'

export default defineConfig({
root: __dirname,
cacheDir: '../../node_modules/.vite/apps/insights',

server: {
port: 4204,
host: 'localhost',
fs: {
allow: [workspaceRoot],
},
},

preview: {
port: 4301,
host: 'localhost',
},

plugins: [
tsConfigPaths({
root: workspaceRoot,
}),
tanstackStart({
tsr: {
srcDirectory: join(__dirname, 'src')
},
}),
],

build: {
outDir: './dist/apps/insights',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
},
})
Keep in mind that the node cwd is located in repo root, while this config is in /apps/insights/. The app seems to build fine, locally everything is running, except that the outDir of the build config is not respected and the files are placed in a .tanstack folder in root. Any idea how that could be changed? Besides the dist location, is there any working examples or pointers on how to make it work with cloudflare workers using the vite approach? (Assuming the app.config.ts approach is outdated)
9 Replies
flat-fuchsia
flat-fuchsiaOP3mo ago
Alright, I've updated the vite config to the following:
import { defineConfig } from 'vite'
import tsConfigPaths from 'vite-tsconfig-paths'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { workspaceRoot } from '@nx/devkit'

export default defineConfig({
root: __dirname,
cacheDir: '../../node_modules/.vite/apps/insights',

server: {
port: 4204,
host: 'localhost',
fs: {
allow: [workspaceRoot],
},
},

preview: {
port: 4301,
host: 'localhost',
},

plugins: [
tsConfigPaths({
root: workspaceRoot,
}),
tanstackStart({
target: 'cloudflare-module',
}),
],

build: {
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
},
})
import { defineConfig } from 'vite'
import tsConfigPaths from 'vite-tsconfig-paths'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { workspaceRoot } from '@nx/devkit'

export default defineConfig({
root: __dirname,
cacheDir: '../../node_modules/.vite/apps/insights',

server: {
port: 4204,
host: 'localhost',
fs: {
allow: [workspaceRoot],
},
},

preview: {
port: 4301,
host: 'localhost',
},

plugins: [
tsConfigPaths({
root: workspaceRoot,
}),
tanstackStart({
target: 'cloudflare-module',
}),
],

build: {
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
},
})
And also set the cwd of the vite commands to be from the application folder. Everything seems to work. But running wrangler dev gives some errors. Heres the wrangler.jsonc:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "foo-insights",
"main": "./.output/server/index.mjs",
"compatibility_date": "2025-04-14",
"observability": {
"enabled": true
},
"assets": {
"directory": "./.output/public/"
},
"compatibility_flags": ["nodejs_compat"]
}
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "foo-insights",
"main": "./.output/server/index.mjs",
"compatibility_date": "2025-04-14",
"observability": {
"enabled": true
},
"assets": {
"directory": "./.output/public/"
},
"compatibility_flags": ["nodejs_compat"]
}
For example:
✘ [ERROR] Could not resolve
"unenv/node/internal/process/hrtime"

../../node_modules/@cloudflare/unenv-preset/dist/runtime/node/process.mjs:1:38:
1 │ ... hrtime as UnenvHrTime } from "unenv/node/internal/process/hrtime";
╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The path "./node/internal/process/hrtime" is not exported by package "unenv":

../../node_modules/unenv/package.json:8:13:
8 │ "exports": {
╵ ^

You can mark the path "unenv/node/internal/process/hrtime" as external to exclude it from the
bundle, which will remove this error and leave the unresolved path in the bundle.
✘ [ERROR] Could not resolve
"unenv/node/internal/process/hrtime"

../../node_modules/@cloudflare/unenv-preset/dist/runtime/node/process.mjs:1:38:
1 │ ... hrtime as UnenvHrTime } from "unenv/node/internal/process/hrtime";
╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The path "./node/internal/process/hrtime" is not exported by package "unenv":

../../node_modules/unenv/package.json:8:13:
8 │ "exports": {
╵ ^

You can mark the path "unenv/node/internal/process/hrtime" as external to exclude it from the
bundle, which will remove this error and leave the unresolved path in the bundle.
Running npm ls unenv seems to show some conflicts:
➜ npm ls unenv
@bar/root@5.579.2 /Users/foo/bar/nx-mono
├─┬ @tanstack/react-start@1.121.35
│ ├─┬ @tanstack/react-start-plugin@1.121.35
│ │ └─┬ @tanstack/start-plugin-core@1.121.35
│ │ └─┬ nitropack@2.11.12
│ │ └── unenv@2.0.0-rc.17
│ └─┬ @tanstack/react-start-server@1.121.34
│ └─┬ h3@1.13.0
│ └── unenv@1.10.0 deduped invalid: "2.0.0-rc.17" from node_modules/@cloudflare/unenv-preset
└─┬ wrangler@4.21.0
├─┬ @cloudflare/unenv-preset@2.3.3
│ └── unenv@1.10.0 invalid: "2.0.0-rc.17" from node_modules/@cloudflare/unenv-preset
└── unenv@2.0.0-rc.17
➜ npm ls unenv
@bar/root@5.579.2 /Users/foo/bar/nx-mono
├─┬ @tanstack/react-start@1.121.35
│ ├─┬ @tanstack/react-start-plugin@1.121.35
│ │ └─┬ @tanstack/start-plugin-core@1.121.35
│ │ └─┬ nitropack@2.11.12
│ │ └── unenv@2.0.0-rc.17
│ └─┬ @tanstack/react-start-server@1.121.34
│ └─┬ h3@1.13.0
│ └── unenv@1.10.0 deduped invalid: "2.0.0-rc.17" from node_modules/@cloudflare/unenv-preset
└─┬ wrangler@4.21.0
├─┬ @cloudflare/unenv-preset@2.3.3
│ └── unenv@1.10.0 invalid: "2.0.0-rc.17" from node_modules/@cloudflare/unenv-preset
└── unenv@2.0.0-rc.17
Could this be issue?
sensitive-blue
sensitive-blue3mo ago
I have a sample project that works with cloudflare workers and the latest start. https://github.com/bonadio/tanstack-start-cloudflare-workers
GitHub
GitHub - bonadio/tanstack-start-cloudflare-workers
Contribute to bonadio/tanstack-start-cloudflare-workers development by creating an account on GitHub.
flat-fuchsia
flat-fuchsiaOP3mo ago
I've seen this one, and seemingly we have basically same setup, except a few monorepo adjustments in vite config. Maybe some diff in package versions I need to test with.
sensitive-blue
sensitive-blue3mo ago
I personally think this will just be one of many issues. Pages isn't the same as workers and I can you're trying to use the alpha vite plugin. Tanstack start isn't ready for cf workers imo. A simple example will work but then anything meaningful will start presenting many issues. I moved to react router 7 instead. But I'm thinking of moving to a docker based Hosting service so I can move back to tan stack start. Basically I'm waiting for non alpha version with official cf worker support
sensitive-blue
sensitive-blue3mo ago
I am migrating a Remix dashboard to TSS running on workers, I had some problems with Better-Auth, but so far everything is working. Not a smooth ride but I was able to solve everything up to now.
sensitive-blue
sensitive-blue3mo ago
any reason why you migrated to tss?
sensitive-blue
sensitive-blue3mo ago
I like Remix, but my apps usually have many function in one page and having a single "action" per route is not ideal, have to pass some additional atributes and switch inside the action or create separate resource routes. TSS with server functions seems to solve this.
sensitive-blue
sensitive-blue3mo ago
so no real reason then. is this a production app the have paying customers?
flat-fuchsia
flat-fuchsiaOP3mo ago
Kinda made same conclusion tbh, need to probably wait a few month until things settle down before we get going. We don't wanna go Next or Remix but we need SSR for certain things, so, waiting it is. Or we look at other hosting solutions for now.

Did you find this page helpful?