T
TanStack•2mo ago
typical-coral

How are we supposed to run the application in non-dev mode?

I'm very confused by this and I've read the getting started docs multiple times. How do I run the tanstack start app in NON-dev mode? In the docs there's a vite build script, but what do we do after we run vite build...? I browsed the dist directory that got created after vite build, and I found a dist/server/server.js, but running node dist/server/server.js doesn't start the server at all.
44 Replies
typical-coral
typical-coralOP•2mo ago
I found this script hidden in a small section in the hosting docs: "start": "node .output/server/index.mjs", however this .output folder does not exist at all for me. vite build creates a dist folder, not a .output folder.
optimistic-gold
optimistic-gold•2mo ago
You should check out the hosting docs. Depending on where you are hosting your production server you will have different outputs in the dist folder (usually) https://tanstack.com/start/latest/docs/framework/react/guide/hosting
typical-coral
typical-coralOP•2mo ago
I'm using node.js with Docker It says I can use the node .output/server/index.mjs command, but that doesn't exist. It also says I should install a nitro plugin? I'm not sure what the point of that is. The basic example at https://tanstack.com/start/latest/docs/framework/react/examples/start-basic uses node .output/server/index.mjs, but it doesn't use a nitro plugin at all in its vite config.
fair-rose
fair-rose•2mo ago
the example is outdated it doesn't have a way to run a prod build yes you may install nitro it will build an optimal server runner for you ts start only builds a fetch handler which is good, because it means the server can be very easily delegated to netlify, vercel, or nitro for example you can create a server entry file yourself if you want using express and/or srvx or Bun.serve, or Deno.serve do whatever you want. but if you want something no brain that just works, then go nitro
typical-coral
typical-coralOP•2mo ago
can it be done with... fastify? 🙂
fair-rose
fair-rose•2mo ago
sure
typical-coral
typical-coralOP•2mo ago
Hmm, I just tried nitro but it always listens on port 3000 and I can't find a way to change that. It seems to ignore the port I set in my vite config's server.port.
fair-rose
fair-rose•2mo ago
in dev or prod? in prod, set PORT env var
fair-rose
fair-rose•2mo ago
typical-coral
typical-coralOP•2mo ago
thanks, didn't think it would be env var, I was looking in the config page of the docs hmm, I took a peek at the source code and it DOES look like the nitro vite plugin is looking at vite config's server.port. It says:
server: {
port:
Number.parseInt(process.env.PORT || "") ||
userConfig.server?.port ||
ctx.nitro.options.devServer?.port ||
3000,
},
server: {
port:
Number.parseInt(process.env.PORT || "") ||
userConfig.server?.port ||
ctx.nitro.options.devServer?.port ||
3000,
},
I'm throwing in some console.log statements in my build to see if I can figure out why that number is still getting overridden by 3000 yeah it's not carrying over into the .output/server/index.mjs file, which reads env vars all over again from scratch:
const port = destr(process.env.NITRO_PORT || process.env.PORT) || 3e3;
const port = destr(process.env.NITRO_PORT || process.env.PORT) || 3e3;
time to clone this repo and tinker! I don't like having to declare my port twice -- once in vite config and again in an env var
fair-rose
fair-rose•2mo ago
why is that an issue? dev server could very well have a different port than prod you could add a define to set process.env.PORT to 3000
typical-coral
typical-coralOP•2mo ago
I have this in my vite.config.ts:
const { SERVER_PORT } = process.env;
const port = parseInt(SERVER_PORT || 15502);

export default defineConfig({
server: { port },
...
});
const { SERVER_PORT } = process.env;
const port = parseInt(SERVER_PORT || 15502);

export default defineConfig({
server: { port },
...
});
I'm in a monorepo with a shared Dockerfile that is used across multiple apps and is setting an env var named SERVER_PORT for production servers. Also, I sometimes want to test the "built" version of my app locally, and my apps work behind a separately running reverse proxy server that operates on port. If the dev mode port and the "built" mode port that is running locally are different, then my local dev workflow no longer works to test the "built" version. We have fastify apps, express apps, and other apps in the monorepo. We built a single Dockerfile to support all of them. When we built it we assumed that every type of app would be able to configure its port in this way.
fair-rose
fair-rose•2mo ago
ok then does the define approach work?
typical-coral
typical-coralOP•2mo ago
I'm trying it right now This doesn't work:
const { SERVER_PORT } = process.env;
const port = parseInt(SERVER_PORT || 15502);

export default defineConfig({
define: {
PORT: port,
},
server: { port },
...
});
const { SERVER_PORT } = process.env;
const port = parseInt(SERVER_PORT || 15502);

export default defineConfig({
define: {
PORT: port,
},
server: { port },
...
});
It still listens on 3000
fair-rose
fair-rose•2mo ago
try this
define: {
`process.env.PORT`: JSON.stringify(port),
},
define: {
`process.env.PORT`: JSON.stringify(port),
},
typical-coral
typical-coralOP•2mo ago
ah, that did work This also worked:
define: {
'process.env.NITRO_PORT': port,
},
define: {
'process.env.NITRO_PORT': port,
},
fair-rose
fair-rose•2mo ago
you could also just run start inside fastify, if this is what you have right now have a look at this example that shows how to embed into an express server https://github.com/TanStack/router/blob/main/e2e/react-start/custom-basepath/express-server.ts
typical-coral
typical-coralOP•2mo ago
Hmmm, I don't have a strong reason to do that since this is a greenfield brand new app. I do however need to define some healthz-endpoints so kubernetes can ping them. I defined them as a vite plugin thinking that the vite server would run in prod, but I guess that's wrong and I need to redefine them in nitro?
fair-rose
fair-rose•2mo ago
vite server does not run in prod you can define them as server routes in Start
typical-coral
typical-coralOP•2mo ago
vite server does not run in prod
Ah, so does that mean I can move vite from dependencies to devDependencies?
fair-rose
fair-rose•2mo ago
or as a separate API service in nitro yes
typical-coral
typical-coralOP•2mo ago
you can define them as server routes in Start
I didn't do that because I have a custom base route
fair-rose
fair-rose•2mo ago
or, if you embed in a custom server, then there what do you mean?
typical-coral
typical-coralOP•2mo ago
my vite config has:
export default defineConfig({
base: '/temp/h2-initiative',
// ...
});
export default defineConfig({
base: '/temp/h2-initiative',
// ...
});
Therefore I thought all the routes I define in Start would be prefixed with /temp/h2-initiative
fair-rose
fair-rose•2mo ago
they will, yes
typical-coral
typical-coralOP•2mo ago
and I wanted to listen to /livez, /readyz and not /temp/h2-initiative/livez
fair-rose
fair-rose•2mo ago
well then dont set the base in vite
typical-coral
typical-coralOP•2mo ago
these would be the only endpoints that need to be outside the base
fair-rose
fair-rose•2mo ago
and move the other routes in a folder that expresses the base?
typical-coral
typical-coralOP•2mo ago
Yeah I thought about that option as well, but I wanted to keep these routes separate from the application routes since they exist purely for kubernetes healthchecks and not actual business stuff. There are some pretty good advantages of setting the base.
or as a separate API service in nitro
Is this a robust feature in Nitro or would you recommend that I avoid it?
fair-rose
fair-rose•2mo ago
nitro3 overall is still alpha, so i cant say really
typical-coral
typical-coralOP•2mo ago
Thanks. I’ll try the fastify option Might also tinker with nitro @Manuel Schiller I spent some time thinking about this. In the example you showed me: https://github.com/TanStack/router/blob/main/e2e/react-start/custom-basepath/express-server.ts I'm not sure I understand why the express-server is being used in development mode at all. Wouldn't it be a lot simpler to continue to use vite dev in development and ONLY use the express server in production mode?
fair-rose
fair-rose•2mo ago
it's just an example to show capabilities you can strip the dev part and use the entrypoint only for prod
typical-coral
typical-coralOP•2mo ago
thank you all for your help!
fair-rose
fair-rose•2mo ago
using express in dev makes sense when you actually use other express routes during dev, e.g. API routes and you need to call them from client/server during dev
typical-coral
typical-coralOP•2mo ago
fair-rose
fair-rose•2mo ago
nice! want to create an example in the router github repo?
typical-coral
typical-coralOP•2mo ago
I was thinking about turning this into a fastify plugin and publishing on npm first I already got started on that, hopefully get some time this weekend to continue
afraid-scarlet
afraid-scarlet•2mo ago
would be awesome to see it in action, I am using it with fastify as well, awesome combo!
typical-coral
typical-coralOP•2mo ago
Here's how far I got so far, haven't published to npm yet though before I ran out of time: https://github.com/onlywei/fastify-tanstack-start
GitHub
GitHub - onlywei/fastify-tanstack-start: Convenience plugin to serv...
Convenience plugin to serve Tanstack Start apps on a Fastify server - onlywei/fastify-tanstack-start
typical-coral
typical-coralOP•2mo ago
typical-coral
typical-coralOP•2mo ago
starting to make some small PRs to update docs based on what I've learned here: https://github.com/TanStack/router/pull/5547
equal-aqua
equal-aqua•2mo ago
i have a problem here it give this error " {"level":50,"time":1761323412845,"pid":11608,"hostname":"BILU","err":{"type":"Error","message":"Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'","stack":"Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'\n at throwIfUnsupportedURLScheme (node:internal/modules/esm/load:209:11)\n at defaultLoad (node:internal/modules/esm/load:107:3)\n at ModuleLoader.load (node:internal/modules/esm/loader:800:12)\n at ModuleLoader.loadAndTranslate (node:internal/modules/esm/loader:580:43)\n at #createModuleJob (node:internal/modules/esm/loa der:604:36)\n at #getJobFromResolveResult (node:internal/modules/esm/loader:338:34)\n at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:306:41)\n at process.processTicksAndRe jections (node:internal/process/task_queues:105:5)\n at async onImport.tracePromise.proto (node:internal/modules/esm/loader:643:25)","code":"ERR_UNSUPPORTED_ESM_URL_SCHEME"},"msg":"Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'"} " and i'm using solidJs with tanstack start is it compatible?
fair-rose
fair-rose•2mo ago
please create a new question, including a complete example reproducer project

Did you find this page helpful?