Create your own
Lesson illustration

Vinxi SSR and Hydration Configuration

Hello! Welcome back to your course on mastering TanStack Start.

In our first lesson, we successfully initialized a project and established the crucial security boundary between server and client environment variables. This set the stage for building a robust server-rendered application.

Lesson 2: The Role of the Vinxi Bundler

Today's Goal:

Today, we're going to pull back the curtain on the "magic" of TanStack Start. By the end of this lesson, you will be able to configure the Vinxi bundler for Server-Side Rendering (SSR) and client hydration. While TanStack Start provides a seamless setup, understanding the underlying bundler is key to grasping how your code is processed, debugged, and optimized.

What we will cover:

  1. Introducing Vinxi: What it is and why TanStack Start uses it.
  2. Vinxi's Core Concept: Understanding how Vinxi uses different "routers" (build pipelines) to create separate bundles for the server and the client.
  3. The SSR and Hydration Flow: Tracing a request from the server-rendered HTML to a fully interactive client-side application.
  4. Inspecting the Build Output: Seeing the concrete server and client bundles that Vinxi produces.

1. What is Vinxi? The Engine Under the Hood

In the last lesson, you saw the tanstackStart() plugin inside vite.config.ts. While Vite is an excellent build tool, its core focus is on client-side applications. To enable the sophisticated server-side rendering, server functions, and multi-target builds required by a modern meta-framework, TanStack Start relies on Vinxi.

Vinxi is a bundler for web applications that is designed to be framework-agnostic. It orchestrates other bundlers (like Vite) to build your code for different environments simultaneously.

SSRx vs. Vinxi vs. Vike - for SSR with Vite

This article provides excellent context on where Vinxi fits into the ecosystem of modern web development tools. It helps clarify why a tool like Vinxi is necessary on top of Vite.

Please read the introduction, the 'Why Vinxi?' section, and the final section that mentions TanStack Router integration. Focus on understanding Vinxi's role as a tool that adds server-side capabilities to Vite and its deliberate integration with the TanStack ecosystem.

As the article highlights, Vinxi isn't just a simple Vite plugin; it's a powerful layer that allows frameworks like TanStack Start to define complex build pipelines in a simple, declarative way. It's the reason TanStack Start can so elegantly handle code that runs on the server, code that runs on the client, and code that runs on both.


2. Vinxi's "Routers": The Key to Multi-Target Builds

The core concept in Vinxi is its use of routers. It's important to clarify that these are not the same as the URL-based routers you're familiar with (like TanStack Router or React Router). In Vinxi's terminology, a "router" is a self-contained build pipeline that defines an entry point, a target environment, and a specific behavior.

A typical SSR application requires at least three of these pipelines:

  1. public router: Serves static files from the public directory. This is a simple file server.
  2. ssr router: This is the server-side part of your app. It handles incoming HTTP requests, runs server-only code (like data loaders), and renders the initial HTML. Its target is a server environment like Node.js.
  3. client router: This is the client-side part of your app. It produces the JavaScript and CSS bundles that are sent to the browser to make the server-rendered HTML interactive. Its target is the browser.

The following article demonstrates how you would manually configure these routers when building a meta-framework from scratch with Vinxi. This will give you a deep appreciation for the abstraction that tanstackStart() provides.

Building a React Metaframework with Vinxi

This article walks through building a simple React meta-framework using Vinxi. It provides a clear, practical example of how Vinxi's routers are configured.

Read the 'React SSR' section. Pay close attention to the vite.config.ts file. Notice the routers array with the public, ssr, and client configurations. This is the fundamental pattern that TanStack Start uses internally.

When you use tanstackStart() in your vite.config.ts, it's essentially generating a more sophisticated version of this configuration for you, automatically setting up the correct entry points and build settings for SSR and client hydration.


3. The SSR and Hydration Flow

Now let's connect these concepts to see how a page is delivered to the user.

  1. Request: A user navigates to a URL in your app. The request hits your server.
  2. Server-Side Render (SSR): Vinxi's ssr router handles the request. It uses TanStack Router to match the URL to a route file. Any loader function in that route is executed on the server. The React components are rendered into an HTML string using React's renderToPipeableStream.
  3. Response: The server sends this HTML to the browser. Crucially, this HTML includes a <script> tag that points to the JavaScript bundle generated by Vinxi's client router.
  4. Paint: The browser receives the HTML and immediately renders it. The user sees the page content, but it's not yet interactive (e.g., buttons don't work).
  5. Hydration: The browser downloads and executes the JavaScript from the <script> tag. React then "hydrates" the static HTML by attaching event listeners and creating the internal component tree, making the page fully interactive without re-rendering the entire DOM.

The following short video clips show the two distinct entry points—server.tsx and client.tsx—that Vinxi uses for the ssr and client routers, respectively.

TanStack Start: A Full-Stack React Framework but Client-First

This video from Dev Leonardo briefly points out the server and client entry files in a TanStack Start project, which directly correspond to Vinxi's ssr and client router handlers.

Watch the two short segments from 03:17 to 04:04. The first part introduces server.tsx as the server entry point, and the second introduces client.tsx as the client entry point, explicitly mentioning hydrateRoot.

This separation is the core of how SSR frameworks work. The server.tsx file is the entry point for the code that runs on the server (Vinxi's ssr router), and client.tsx is the entry point for the code that runs in the browser (Vinxi's client router).

Once the initial page is loaded and hydrated, TanStack Router takes over for subsequent navigations, behaving like a traditional Single-Page Application (SPA) for a fast, smooth user experience.


4. Practical Exploration: Inspecting the Build Output

You don't need to write any code for this section. Instead, let's verify these concepts by looking at the output of a production build.

  1. In your terminal, at the root of your project, stop the development server if it's running.
  2. Run the build command:
    npm run build
    
  3. Once it's finished, you will see a new directory named .vinxi in your project root. This is where Vinxi places the build artifacts.
  4. Inspect the contents of the .vinxi/build directory. You should see two key subdirectories:
    • client/: This folder contains the assets that will be served to the browser. You'll find your JavaScript bundles (with hashed filenames for caching), CSS files, and any other static assets. This is the output of the client router.
    • ssr/: This folder contains the server-side bundle. You'll see an index.mjs file. This is a self-contained module that can be run by Node.js. It contains your server logic, including all the React components and loader functions, ready to render HTML on demand. This is the output of the ssr router.

This directory structure is tangible proof of Vinxi's work. It has taken your single codebase and intelligently split it into two distinct applications—a server application and a client application—that work together to deliver a server-rendered, progressively enhanced user experience.


Conclusion

Great job! You've now looked under the hood of TanStack Start to understand its build process. While you won't often need to modify Vinxi's configuration directly, knowing how it works is invaluable for debugging performance issues, understanding code execution contexts, and appreciating the architecture of modern meta-frameworks.

Key Takeaways:

  • TanStack Start uses Vinxi to orchestrate Vite for building separate server and client applications from a single codebase.
  • Vinxi's core concept is "routers"—build pipelines for specific targets (ssr, client, public, etc.).
  • The tanstackStart() Vite plugin is a high-level abstraction that configures Vinxi for you.
  • SSR is handled by the ssr bundle on the server, which generates the initial HTML.
  • Hydration is the process where the client bundle runs in the browser, making the server-rendered HTML interactive.

Next Lesson Preview:

Now that we understand the build mechanics and how the server and client work together, we can focus on the developer experience of creating pages. In the next lesson, we will "Compare TanStack Router's file-based routing conventions with Next.js App Router patterns." We'll dive into how you define the structure of your application by simply creating files and folders.

Can't find a good explanation? Sign up and we'll make it for you

Sign up