Remix vs Next.js Comparison
Static Site Generation
Next.js has built-in support for SSG using the
getStaticPaths methods in a page module.
Remix doesn't support SSG, you could run your Remix app and use something like Puppeteer to prerender the HTML and server that, another option is to use the Cache-Control HTTP header to cache the HTML in a CDN or user browser and you will get a similar result. However you may want to double check if you really want to do SSG and if so maybe try another tool like Next.js.
Incremental Static Regeneration
Next.js has built-in support for ISR using the
revalidate attribute in the result of
Remix doesn't support ISR, but due the lack of support for SSG it's not necessary. If you use the Cache-Control HTTP header you can use the stale while revalidate strategy to get the same functionality as ISR.
Server Side Rendering
Next.js has built-in support for SSR using the getServerSideProps method or the old getInitialProps method in a page module.
Remix also has built-in support for this using the loader function in a route module. Remix always do SSR even if you are not defining a loader. Note than SSR React takes a few ms so most probably the larger wait time will be in the loader and not the SSR.
Next.js has built-in support to define API routes by creating a function inside the
pages/api directoy exporting a Node.js HTTP request listener.
Remix doesn't support yet API-only routes, however because Remix is just a route inside your server you can easily add any custom route you want to your server depending on what you are using as your server.
A feature is coming.
Next.js doesn't come with some built-in utility to handle forms, you need to either manually point to an API route or use Fetch to do a POST/PUT/PATCH/DELETE request against an API route, everything manually.
Remix comes with built-in support to handle forms, a route module can export an action function which will receive any non GET request against that route, this will be used by forms doing a non GET submit.
Remix also has a useful Form component you can use as a drop-in replacement for the form HTML tag and it will change the submit to be done via Fetch instead of reloading the page, when using this component you can use other methods aside of POST and GET, like PATCH and DELETE, but you will need to handle the case JS didn't load and the form worked as a POST instead.
Remix also has a useSubmit hook you can use to submit your form programmatically and correctly call your action via Fetch. This hook is useful when you need to call the action outside a form submit, e.g. after keystroke or in an interval or if you want to submit after the user mark a checkbox.
Next.js comes with a built-in custom router which uses the file system to define routes. It also has an API used to navigate your app programatically.
Remix also uses your file system to define your routes, however since it's built on top of React Router v6 it let you define your routes in a custom way and you can also use all the React Router hooks and components in your application. Anything that works with React Router works in Remix.
Next.js doesn't come with built-in support for working with cookies, there are popular libraries in the community thought.
Remix has built-in support to work with cookies using the
createCookie function provided by the framework.
Next.js doesn't come with built-in support for working with sessions, there are popular libraries in the community thought.
Remix has built-in support to work with sessions using cookies, the file system, the server memory, or a custom storage. The latest one lets you use your database or something like Redis to store your session.
Next.js uses the Node.js HTTP Request and Response interfaces, when using the serverless deployment it expects the platform to support this or the user manually transform the platform request/response interface to the expected by Next.js. There are popular libraries in the community thought.
Remix uses the Fetch API Request and Response interfaces and it comes with built-in adapters to some deployment platforms, with an Express adapter useful to deploy it to any platform supporting Node.js deployments. For serverless it supports Vercel, Architect for AWS Lambda and Fly.io. More adapters are coming and you can write your own.
Next.js lets you add content to your page
<head> by using the
next/head component to wrap what you want to render there.
Remix lets you export a links and meta functions on any route module and return a list of links/metas to add a simple array of plain objects. It also has documentation on how to use PostCSS, TailwindCSS and any CSS in JS which doesn't require Babel. This functions will access your route data got in a loader function as a way to use it to define the content.
Next.js comes with styled-jsx as a default CSS in JS solution and has support for importing global CSS and CSS Modules.
Remix doesn't come with built-in support for any CSS in JS solution or another styling technique. It has support to import CSS files and it provides a unique hashed URL. This URLs can be returned from the links function in a route module to load that specific stylesheet. This lets you load different stylesheets based on the route instead of creating a single huge CSS file, that you can still do if you prefer.
Support for PostCSS is coming.
Page and Data Preload
next/link component. You can manually disable this in a per link basis.
Remix doesn't preload anything automatically, but it lets you return a list of assets to preload in the links function of any route module. Along the usual link with the
rel="preload" you can add there a an object with the property
data: true and then Remix will preload the data for the page along the assets for instant page navigation.
Remix also has support for client-side only blocking navigation assets, this lets you define which assets you are adding as links you want to ensure they are loaded by the user browser before completing the navigation to that page. This way you can block the navigation to a route until images or another asset is completely loaded. This last feature only works when navigating client-side, on the first render there's no way to enforce it.
Next.js has a special
_app page you can use to wrap your whole application in a consistent layout, if you want to add more nested layouts you need to either render the layout on each page manually and implement some logic to add it from the
_app page based on some condition. Community documented approaches exists.
Remix has built-in support for nested layouts, any route created inside a folder will be nested inside a route with the same name as folder in the parent folder. This is thanks to the power of React Router.
A parent route (layout) can also load their own data using a loader so you can have a layout loading what it needs and the leaf route (the nested one) load what it needs without having to load both things in the same layout, when navigating client-side to another nested route Remix will load run the loader of the nested and keep the data of the parent.
Next.js has built-in support for internationalized routing and can use popular libraries for content i18n.
Remix doesn't has built-in support for internationalized routing, however thank to the possibility to completely replace file system routing with something custom it's possible to add it.
Next.js has built-in automatic image optimization support when using the
Remix lets you import images and get a URL back or use the
img: prefix in the import path and get the image URL and perform some simple transformation, algo get multiple URLs to use in
srcset, a placeholder URL and change the quality.
Next.js lets you define some special pages for 500, 404 and any error, then renders that in case of an error.
Remix lets you export an ErrorBoundary component inside any route module which will handle any error of that specific route. If a route is nested it will only handle errors on that part, the parent route will continue to work.
Live Reload vs Fash Refresh
Next.js has support for React Fash Refresh wich will update your components as you save files without reloading the whole page and losing UI state.
Remix has support to enable Live Reload (not enabled by default) which will reload the page as you save files. This will cause the UI state to be lost but will allow you to easily see updates on loaders. Fast Refresh support is coming.
Next.js is zero config by default, you can still customize the webpack and Babel if needed, together with other parts of the internal stack.
Remix is also zero config by default, it comes with everything you need to run it after installing it.
Both, Next.js and Remix has built-in support for TypeScript without any special setup.
Next.js comes with
.env support out of the box, it also has a convention to prefix environment variables you want to expose to the client-side code. There's additionally a way to avoid the convention and manually expose a variable.
Remix doesn't comes with
.env support out of the box too, and it exposes
process.env.NODE_ENV to the client-side code, it has a guide in the docs on their recommended approach to expose environment variables to the client. Adding
.env support is rather simple by using the
Next.js automatically polyfill
URL in servers so you can use it inside API routes, getStaticProps, getStaticPaths and getServerSideProps.
Remix automatically polyfill
fetch in the server so you can use it inside your loaders and actions.
Next.js has out of the box support for AMP, you can enable it in a per page basis.
Remix doesn't come with any special support for AMP.