Remix is a wonderful, sane framework that I highly recommend for React developers. No monkey patching, no global context imports, no undocumented functionality etc etc. Had a hell of a time trying to wrangle Next and it was terrible. Next still doesn't have a way to completely disable prefetches on hovering over Next links unless you use a plain anchor tag which is the kind of insidious, undocumented behaviour that makes for weird bugs (setting prefetch to false does not disable prefetch on hovers). Remix just sends you browser and node objects like a standard request object in all the arguments and just uses the platform with the framework extensions acting as a nice layer on top
Very interesting. Another Next victim here.
One of my anecdotes is the bonkers caching / fetch deduplication. Yes, set cache: no-store. But that only works for fetch requests. If you have a 3rd party lib doing the fetching (say, Google Firestore), then you have to declare export const dynamic = 'force-dynamic' at the top of your route segment: https://nextjs.org/docs/app/api-reference/file-conventions/r...
That behaviour wasn't documented when I got started with NextJS 13...imagine the fun I had trying to work out why I can't get updated data from the server. It was nuts.
Another insidious thing in Next: their middleware is completely sandboxed and you can't use any standard Node functionality. It doesn't matter if you're using vercel now or not, and there's no way to disable this.
This is pretty important for things like sessions with httpOnly cookies. And it forces you make an API call to yourself to resolve.
Remix has improved substantially since Shopify took over the project. Remix adopting Vite makes it a real choice. Prior to that acquisition, they made some, what I believe to be, bizarre API choices.
now you can simply use the full power of Vite, which means you aren't locked into Remix having to make choices for you.
This is the 3rd time they migrated the underlying tech though, first it was rollup, then esbuild, and now Vite, which is effectively rollup again. I hope they stick with Vite for the foreseeable future though
I placed their Link component within a polymorphic wrapper which could switch between Link and plain anchor elements depending on the props given. The typing was gnarly, but it worked well. By default it would be a Link as I recall, but things like a non-relative href or use=“a” props would swap it for an anchor. And maybe other things, I’m not sure. It would reject Link props if it knew it was using an anchor element, though.
I’m ashamed to say this took way too long to get working nicely. It was worth it because our linting otherwise went crazy over misuse of Link and anchor, and people on the team weren’t respecting it. This made it so we could say “only use Link” and make it easy for that to be accomplished.
Trust me, it’s way easier to get stuff done with Next :)
Once you get past the day or three spent making it so links do what you wish they did… And you discover it handles cache headers differently than it’s supposed to… And middleware doesn’t work in several contexts with no explanation… And on and on.
Interestingly, I no longer see Next Link prefetching on hover when the prefetch prop is set to false. At some point in Next 13 it was doing that, but in Next 14.1.0 I no longer see it. I’m not sure when or why it stopped.
Can anyone who has used Remix comment on the API stability?
AFAIK it’s built by the same folks as React-Router, and I have a distrust of that project because of the tendency to make large breaking changes in order to make things “better” according to some criteria. I’ve been through a few RR upgrades that required a lot of extra work because we were using some previously supported pattern that then disappeared. I like the look of Remix but I don’t want to get trapped in that kind of situation again.
I don’t know anything about Remix but I was around when React Router was first launched. I remember strongly disliking the API and concluding that it got popular not because of any particular quality, but because its name was exactly what everybody typed into Google. That’s a nasty thing to say, but bear with me. Thing is, today, doesn’t suck at all!
I suspect the original author might’ve very much learned how to do API design on the fly when those first major versions of RR were shipped. Ie: the hard way, because every change they made caused a lot of complaining (for good reason maybe, but still! People complaining about your open source project is not fun)
So maybe if anyone has a nuanced and wise view of API design and versioning, it’s the RR people :-)
Just migrated a couple of projects from remix 1 to remix 2. It wasn't a walk in the park, but it was well planned by their team, by first adding feature flags to v1 where you could slowly adopt v2 APIs, and then switch. I think you can even run v2 with a v1 API backport layer. So I think they have a good approach to stability vs improving their product.
The really hard part has been migrating other stuff like CJS to ESM, or upgrading other dependencies like cypress, but that is not related to remix.
This makes me think back to the Next Conf when Vercel announced Turbopack and threw out some questionable metrics and reasons why they couldn't adopt Vite. That was the most marketing hype I've seen from a tech conf. Watched the Microsoft Ignite conf afterwards and it was night and day: one looked like a marketing event, the other looked like a nerdy engineering event.
Vite and webpack (and thus turbopack, which is advertised as a webpack successor) are two different beasts.
While vite is perfect for most users, there are just some usecases that are not doable with meaningful performance. Without boring you with details why, let me assure you that having a performant webpack replacement for those 10% who need it, helps vite staying lean, as they are not bothered with feature creep.
If you want a small detail why: Vite is built on esbuild. Esbuild is carried by a single developer (https://github.com/evanw/esbuild/graphs/contributors) thus every nut and bolt that vite does for you on top is built in javascript, so you are in slow-land again.
webpack and turbopacks promise (and complexity) is that it treats these extras (plugins and loaders) as first class citizens and thus tries to make them as fast as possible by applying tons of caching. E.g. if you'd throw a webpack workflow at vite, you might end up with a slower build then webpack. And this is where turbopack tries to improve.
i love love love remix, am so glad i chose it a couple of years ago and now use it for everything
that said, i wonder if anyone has advice on a couple of things
1. typesafe routing and fetching, e.g. using useFetcher then fetcher.submit({title: 'hi'}, {action: '/blog'}). i would love both the {title: 'hi'} and the 'blog' to be typesafe (as safe as you can get in typescript)
2. i still haven't got onboard with using uncontrolled inputs, so i end up using react hook form again. i feel like eventually i need to "watch" one of the inputs, and the main thing again is the typesafety. with react hook form, i can declare my form with zod and be sure it's exactly what i'm then submitting to the server, and revalidate it there. any good ideas here? i would love to get the progressive enhancement from not using js
I like using https://www.remix-validated-form.io/, which you would use to get a type safe validated object before doing the submit. And then you could reuse the validator on the backend as well.
Remix is great and it's my favorite meta framework. I've used it on some quick MVPs and a blog but when it comes to production apps as one-man-shop, I always go back to my safety zone of Rails. For those running robust Remix apps: can you share your stack and where you deploy? How are you doing auth? Are you on a team or doing solo work? I'm genuinely curious because I would love to leverage so much of React (UI components, etc.).
I'm on Remix / Drizzle ORM / Render.com / Render Postgres / Cloudflare R2 / DaisyUI + shadcn/ui these days.
Drizzle can be a bit tricky if you're coming from ActiveRecord but once you have your own helpers with a base class that implements common method such as find_by({ key: value}) / create({ data }) / update(id, { data }) / delete(id), things get better.
Render is really good - you don't need any specific configs, just set env vars on their dashboard and git push to deploy. Simpler and better than Heroku workflow.
My stack is Remix + Hasura + FastAPI + Postgres, with Apollo client and Tailwind. In my opinion this is the best in slot loadout for the majority of web apps in 2024.
At work we are using Inertia.js as an interface between React and Rails (inertia is just a tiny library/protocol that lets you use React or Vue replacing your mvc framework templates)
I've been looking at Remix a bit recently and it looks really cool, but the part I'm not too fond of is having to use Node on the backend. I moved to writing all of my backends in Go after I was burned by the whole ESM/CJS/TS disaster. But there doesn't seem to be any true way to get reliable/feature full SSR with a backend that is not javascript based.
I do see that has has a BFF mode, but I can't really find any instances of many people using it, or at least writing about it. Does anyone have experience with BFF mode?
I think I may just stick with React + Tanstack router + Tanstack query + zustand for now and try the BFF model eventually?
React is a JS library, so it needs a JS runtime to execute outside the browser.
It's hypothetically possible to use a JS runtime as a subprocess from another language to use React for plain HTML SSR, but it probably wouldn't work for React's streaming HTML generation (or at least would likely be very difficult to get working).
SPA mode (what I assume you mean by BFF mode) is brand new, so almost nobody has used it. However, a close example would be the Oxide web console, which we build as an SPA because we want to serve it as static assets from a Rust backend. It's very close to your suggested stack: React + React Router + Tanstack query + zustand, though importantly we also use React Router's loaders to give the app a better-than-SPA feel on navigations. I do plan on moving it to Remix SPA mode when I get a chance, but like I said the result should be very similar so it's not that high a priority for me. If I were starting from scratch I'd probably use Remix SPA.
This is awesome news. Remix has become my standard go-to for all new projects.
They have really sane defaults and together with stuff like their indie-stacks etc developing apps goes really super fast.
I have never been so productive as I have been with Remix and it's really good that the finally have embraced Vite so I can use all the different plugins etc that exist for it.
React Router is still great, and in fact has gotten dramatically better as a result of its place at the core of Remix. Data router eliminates loading spinners and makes your SPA feel like a real application.
I haven't tried Remix, but the sentiments in the comments makes me feel it's another framework that sounds like it's sick of the current complexity around stuff like SvelteKit and Next, but that's exactly how I felt when Svelte came out 3-4 years back, so what's to stop this from going down the exact same route where "just one more feature" snowballs into something unrecognizable?
I maybe don't understand the parallels being drawn at the moment, so this view is subject to change when I dig in a little deeper.
Finding the right abstraction is hard. To me in seems clear Next is tuned for Vercel Now. If you build in a compatible way it works great, it's a nice "serverless" setup for serving pages. There's a whole range of use cases this doesn't work for: eg realtime apps, apps that care more than average about security, etc.
> It is an explicit goal of ours to design APIs that are high-level enough to help you just get the job done, but close enough to the web to backfill your fundamental knowledge of Kung Fu the web.
I’m one of those using remix and I do like it a lot, but I don’t have much hope. I wish I’m wrong but probably in a couple years we’ll be all hating it. I also liked next a lot in the early days. Somehow they always manage to fuck yo and nothing reaches “Rails” levels of stability/popularity in the js world.
I've just started playing with Remix since it seems to be the recommended route for Shopify app development.
I must say I'm not entirely blown away by it. It's unique feature (frontend/backend coupling) kind of feels like it's just a re-engagement with the traditional web app. Or even just akin to a mono repo for a modern frontend/backend.
Beyond that, it's main let down (which is in no way unique to it) is not having a straight forward application entry point that allows you to wire things up as you see fit (composition root). Instead we get a request handler that we hook into another server technology that in turn makes their controller equivalents work like magic.
My struggle with it, as of this afternoon, was to figure out how to bundle raw SQL files in the build until it became apparent that you have to unbox all the Vite functionality and do it that way (which seems to have some depth) or literally have a parallel step outside the build for copying the files into the build dir. Not the greatest experience for what is a pretty basic step (embedding resource files in the build output).
Very much feels like a project that is just a small twist on what already exists in the ecosystem and will fall into the growing black hole of JS web frameworks. Sorry to be glum :/
clicking the link all the text seems to restyle multiple times - the fontsize seems to flash 'bigger' at least twice before settling. looks very unsettling.
I definitely can appreciate this sentiment, but I will also add that for me Remix feels like a simplification more than something that's added complexity. It also leans heavily into the Web APIs so you get a lot of non-framework knowledge when you use it.
Personally, I haven't experienced that kind of "this is simpler" feeling since jQuery.
[+] [-] aniforprez|2 years ago|reply
[+] [-] throwaway77384|2 years ago|reply
That behaviour wasn't documented when I got started with NextJS 13...imagine the fun I had trying to work out why I can't get updated data from the server. It was nuts.
[+] [-] robust-cactus|2 years ago|reply
This is pretty important for things like sessions with httpOnly cookies. And it forces you make an API call to yourself to resolve.
[+] [-] no_wizard|2 years ago|reply
now you can simply use the full power of Vite, which means you aren't locked into Remix having to make choices for you.
This is the 3rd time they migrated the underlying tech though, first it was rollup, then esbuild, and now Vite, which is effectively rollup again. I hope they stick with Vite for the foreseeable future though
[+] [-] steve_adams_86|2 years ago|reply
I’m ashamed to say this took way too long to get working nicely. It was worth it because our linting otherwise went crazy over misuse of Link and anchor, and people on the team weren’t respecting it. This made it so we could say “only use Link” and make it easy for that to be accomplished.
Trust me, it’s way easier to get stuff done with Next :)
Once you get past the day or three spent making it so links do what you wish they did… And you discover it handles cache headers differently than it’s supposed to… And middleware doesn’t work in several contexts with no explanation… And on and on.
[+] [-] selfmodruntime|2 years ago|reply
[+] [-] tshaddox|2 years ago|reply
[+] [-] dimal|2 years ago|reply
AFAIK it’s built by the same folks as React-Router, and I have a distrust of that project because of the tendency to make large breaking changes in order to make things “better” according to some criteria. I’ve been through a few RR upgrades that required a lot of extra work because we were using some previously supported pattern that then disappeared. I like the look of Remix but I don’t want to get trapped in that kind of situation again.
[+] [-] scottcorgan|2 years ago|reply
But, Remix’s breaking changes start as future flags on the current major release and slowly become breaking changes over time.
That means you can incrementally adopt the breaking change so the upgrade isn’t all at once.
[+] [-] skrebbel|2 years ago|reply
I suspect the original author might’ve very much learned how to do API design on the fly when those first major versions of RR were shipped. Ie: the hard way, because every change they made caused a lot of complaining (for good reason maybe, but still! People complaining about your open source project is not fun)
So maybe if anyone has a nuanced and wise view of API design and versioning, it’s the RR people :-)
[+] [-] jackbravo|2 years ago|reply
The really hard part has been migrating other stuff like CJS to ESM, or upgrading other dependencies like cypress, but that is not related to remix.
[+] [-] 0xblinq|2 years ago|reply
[+] [-] CharlieDigital|2 years ago|reply
[+] [-] sod|2 years ago|reply
While vite is perfect for most users, there are just some usecases that are not doable with meaningful performance. Without boring you with details why, let me assure you that having a performant webpack replacement for those 10% who need it, helps vite staying lean, as they are not bothered with feature creep.
If you want a small detail why: Vite is built on esbuild. Esbuild is carried by a single developer (https://github.com/evanw/esbuild/graphs/contributors) thus every nut and bolt that vite does for you on top is built in javascript, so you are in slow-land again.
webpack and turbopacks promise (and complexity) is that it treats these extras (plugins and loaders) as first class citizens and thus tries to make them as fast as possible by applying tons of caching. E.g. if you'd throw a webpack workflow at vite, you might end up with a slower build then webpack. And this is where turbopack tries to improve.
[+] [-] davedx|2 years ago|reply
[+] [-] reducesuffering|2 years ago|reply
Turbopack is made with that in mind.
That's not Vite's priority, it wants to have a novel approach without backwards-compatibility in mind.
[+] [-] willsmith72|2 years ago|reply
that said, i wonder if anyone has advice on a couple of things
1. typesafe routing and fetching, e.g. using useFetcher then fetcher.submit({title: 'hi'}, {action: '/blog'}). i would love both the {title: 'hi'} and the 'blog' to be typesafe (as safe as you can get in typescript)
2. i still haven't got onboard with using uncontrolled inputs, so i end up using react hook form again. i feel like eventually i need to "watch" one of the inputs, and the main thing again is the typesafety. with react hook form, i can declare my form with zod and be sure it's exactly what i'm then submitting to the server, and revalidate it there. any good ideas here? i would love to get the progressive enhancement from not using js
[+] [-] jackbravo|2 years ago|reply
[+] [-] clivestaples|2 years ago|reply
[+] [-] kenn|2 years ago|reply
I'm on Remix / Drizzle ORM / Render.com / Render Postgres / Cloudflare R2 / DaisyUI + shadcn/ui these days.
Drizzle can be a bit tricky if you're coming from ActiveRecord but once you have your own helpers with a base class that implements common method such as find_by({ key: value}) / create({ data }) / update(id, { data }) / delete(id), things get better.
Render is really good - you don't need any specific configs, just set env vars on their dashboard and git push to deploy. Simpler and better than Heroku workflow.
You can take a look at https://github.com/remix-run/blues-stack to learn how you'd manually implement cookie-based auth on this framework.
Remix is the closest thing to Rails in the JS ecosystem IMO
[+] [-] CuriouslyC|2 years ago|reply
[+] [-] 0xblinq|2 years ago|reply
Check it out, it’s really nice.
[+] [-] JoshGlazebrook|2 years ago|reply
I do see that has has a BFF mode, but I can't really find any instances of many people using it, or at least writing about it. Does anyone have experience with BFF mode?
I think I may just stick with React + Tanstack router + Tanstack query + zustand for now and try the BFF model eventually?
[+] [-] acemarke|2 years ago|reply
It's hypothetically possible to use a JS runtime as a subprocess from another language to use React for plain HTML SSR, but it probably wouldn't work for React's streaming HTML generation (or at least would likely be very difficult to get working).
[+] [-] dcre|2 years ago|reply
Repo: https://github.com/oxidecomputer/console/
Live demo here with in-browser MSW mock API: https://oxide-console-preview.vercel.app
[+] [-] ecmascript|2 years ago|reply
I have never been so productive as I have been with Remix and it's really good that the finally have embraced Vite so I can use all the different plugins etc that exist for it.
[+] [-] rpastuszak|2 years ago|reply
[+] [-] klysm|2 years ago|reply
[+] [-] AprilArcus|2 years ago|reply
[+] [-] dcre|2 years ago|reply
[+] [-] lowboy|2 years ago|reply
[+] [-] WuxiFingerHold|2 years ago|reply
[+] [-] h4ch1|2 years ago|reply
I maybe don't understand the parallels being drawn at the moment, so this view is subject to change when I dig in a little deeper.
[+] [-] ulimn|2 years ago|reply
It's not simpler as in less features.
[+] [-] robust-cactus|2 years ago|reply
[+] [-] jackbravo|2 years ago|reply
Summary: Learn Remix, Accidentally Learn the Web
> It is an explicit goal of ours to design APIs that are high-level enough to help you just get the job done, but close enough to the web to backfill your fundamental knowledge of Kung Fu the web.
That's something I really like about remix.
[+] [-] 0xblinq|2 years ago|reply
[+] [-] azemetre|2 years ago|reply
Genuinely curious as I’m burnt out of the react ecosystem entirely. Svelte seems good but haven’t done much out of demo projects.
[+] [-] aswerty|2 years ago|reply
I must say I'm not entirely blown away by it. It's unique feature (frontend/backend coupling) kind of feels like it's just a re-engagement with the traditional web app. Or even just akin to a mono repo for a modern frontend/backend.
Beyond that, it's main let down (which is in no way unique to it) is not having a straight forward application entry point that allows you to wire things up as you see fit (composition root). Instead we get a request handler that we hook into another server technology that in turn makes their controller equivalents work like magic.
My struggle with it, as of this afternoon, was to figure out how to bundle raw SQL files in the build until it became apparent that you have to unbox all the Vite functionality and do it that way (which seems to have some depth) or literally have a parallel step outside the build for copying the files into the build dir. Not the greatest experience for what is a pretty basic step (embedding resource files in the build output).
Very much feels like a project that is just a small twist on what already exists in the ecosystem and will fall into the growing black hole of JS web frameworks. Sorry to be glum :/
[+] [-] 0xblinq|2 years ago|reply
[+] [-] jackbravo|2 years ago|reply
[+] [-] Jenk|2 years ago|reply
[+] [-] no_wizard|2 years ago|reply
[+] [-] daef|2 years ago|reply
[+] [-] azangru|2 years ago|reply
[+] [-] boringuser2|2 years ago|reply
[+] [-] whoishiringbrad|2 years ago|reply
Personally, I haven't experienced that kind of "this is simpler" feeling since jQuery.
[+] [-] SwiftyBug|2 years ago|reply
[+] [-] zwily|2 years ago|reply
[+] [-] twojobsoneboss|2 years ago|reply