Deploying built assets to CDN/S3
I run a pretty big site and we're slowly implementing TanStack Start on it.
We have around 8 web boxes in a load balancer, and the way we typically handle deploys is we build the the app on every one of those boxes, and have a copy of client-side assets/modules on S3.
This allows us to properly leverage Cloudflare caching and whatnot for the user, while still allowing all server-side JS to run on the box properly.
I've kinda got it working by specifying the
base
option in vite.config.js
, and then kind of "undoing" that in nitro.config.ts
by setting runtimeConfig.app.baseURL
to /
so that it still uses /
for server stuff, but the S3 URL for vite public asset paths.
That more or less works, but it feels pretty "hacky"? I guess. In addition, the <link preload=
scripts added to the html have misformated URLs: http:/<cdn>/<asset>
(notice one slash after http: and not two), this is due to the use of path.join(APP_BASE..
vs. joinURL
in the start-plugin-core
and that causes 404s for the user.
Can go more in detail if anyone from the TS team is willing to lend some input, but basically just trying to understand if there's a more stable kind of first party way of doing this.10 Replies
eastern-cyanOP•3mo ago
Giving this a quick bump as a last try -- completely understand it's a new framework so not many scenarios like the above, but just in case!
optimistic-gold•3mo ago
so what would be needed here? a separate config for asset paths?
eastern-cyanOP•3mo ago
Yep! Just to clarify so we're on the same page: I'm also talking about client JS build files.
What I am doing is running
npm run build
, taking all the public files (js/assets/etc...) and hosting those on s3, and then running npm run build
on all my web boxes again, and keeping the server files stored on each individual box.
This is our ideal scenario because we then are not forced to drop our whole site's cache after a change/deploy, and users on cached pages are still able to look at "older" build files (since the cached server files will request older files) because we don't delete those from s3.
tldr, ideally there would be two separate configs, one for client, and one for server. Let me know if that makes sense, and whether you need me to open up a gh issue with some more explanation/examples and whatnotoptimistic-gold•3mo ago
we could also look into whether an API like vite's
renderBuiltUrl
https://vite.dev/guide/build.html#advanced-base-options makes senseoptimistic-gold•3mo ago
so yes, definitely add a gh issue for this with a complete example and then we can discuss in detail
optimistic-gold•3mo ago
This sounds like something we would definitely want to make easier
eastern-cyanOP•3mo ago
Yep! Planning to take a deeper look myself in the coming days/week and if I'm able to find a nice solution then will submit a PR for it. Will revert back!
genetic-orange•4w ago
This is very important. No serious use case will want nitro serving assets.
Other solutions typically have an asset prefix as the simplest option. Next.js does and so does Vike: https://vike.dev/base-url#baseassets
Base URL | Vike
The Modular Framework — Next.js & Nuxt alternative for unprecedented flexibility and stability.
genetic-orange•4w ago
@happy your solution with the nitro config seems to work well for me. Thanks.
Considering Tanstack Start is thinking about being more agnostic about how it's served, it should probably handle this itself though.
optimistic-gold•4w ago
we absolutely should