Skip to content

Add Vite, TanStack Start and Typescript environment setup configuration to the documentation#433

Closed
Dovakeidy wants to merge 7 commits into
react:mainfrom
Dovakeidy:main
Closed

Add Vite, TanStack Start and Typescript environment setup configuration to the documentation#433
Dovakeidy wants to merge 7 commits into
react:mainfrom
Dovakeidy:main

Conversation

@Dovakeidy

@Dovakeidy Dovakeidy commented Dec 4, 2025

Copy link
Copy Markdown
Contributor

cc @necolas @MoOx

This PR is a follow-up to this comment

Description

This pull request introduces several important improvements related to integrating React Strict DOM with modern tooling commonly used across the React ecosystem.

Added documentation

I added new documentation sections covering:

  • Vite
  • TanStack Start
  • TypeScript

The goal is to provide clear guidance on how to set up React Strict DOM with these tools, without requiring developers to piece together information from issues or trial-and-error.

Context: multiple issues related to Vite configuration

Several existing issues report problems with Vite configuration.

Issue #273
Issue #265

This highlights the need for an official, working example, especially since Vite and TanStack Start are among the most widely used tools in the ecosystem outside of Next.js.

Adoption concern

I believe the lack of documentation and examples for these technologies is currently a significant barrier to adopting React Strict DOM.
This PR aims to reduce that friction and provide a straightforward and reproducible setup path.

Renaming .js to .jsx in the example components

I also renamed all example UI components from .js to .jsx because:

  1. .jsx is the standard for React components containing JSX,
  2. Vite does not support JSX syntax in .js files by default, which caused immediate errors and prevented the example from working.

@Dovakeidy Dovakeidy requested a review from necolas as a code owner December 4, 2025 19:56
@meta-cla

meta-cla Bot commented Dec 4, 2025

Copy link
Copy Markdown

Hi @Dovakeidy!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla

meta-cla Bot commented Dec 4, 2025

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@meta-cla meta-cla Bot added the cla signed label Dec 4, 2025

@necolas necolas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! The Vite example and docs look good. But I don't think we need a TanStack app - it looks like it's just a Vite app. The setup instructions are only really needed for bundlers/frameworks

Comment on lines +1 to +25
---
slug: /learn/setup-typescript
---

# Typescript

<p className="text-xl">Learn how to configure Typescript for React Strict DOM.</p>

## About Typescript

[TypeScript](https://www.typescriptlang.org/) is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.

## Platform-specific files

React Strict DOM supports creating separate implementations for different platforms—such as web and native using platform-specific file extensions (e.g., `.web.tsx`, `.native.tsx`). This approach allows you to write custom code for each platform while sharing a single codebase. To ensure TypeScript correctly resolves these files during development and builds, you can use the `moduleSuffixes` option in your `tsconfig.json`. The following configuration tells TypeScript to prioritize platform-specific files when resolving imports:

```json title="tsconfig.json"
{
"compilerOptions": {
"moduleSuffixes": [".ios", ".android", ".native", ".web", ""],
// ...
},
// ...
}
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a part of the Expo setup docs that covers the ts configuration needed for cross-platform file extensions. I'm not sure we need a docs page just for ts. If other stacks (only targeting web) still need this ts config, we can put it into their setup docs so everything is in one place.

Comment thread apps/tanstack-start-app/.gitignore Outdated
Comment thread apps/vite-app/.gitignore
include: [
'src/**/*.{js,jsx,mjs,ts,tsx}',
'../../node_modules/example-ui/**/*.js'
'../../node_modules/example-ui/**/*.jsx'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this were an actual node_module we'd probably expect everything to have js extensions rather than jsx, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to include all potential extensions?

'../../node_modules/example-ui/**/*.{js,jsx,mjs,ts,tsx}'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure. As far I'm aware the norm is publishing js or mjs files to npm. Maybe needing to add source file extensions like jsx is a quirk of the monorepo

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I completely overlooked the fact that it was the Expo app's postcss configuration and not the documentation. I changed it to .jsx here because I had to modify all the extensions of the “example-ui” app to .jsx in order to align with React and Vite conventions (Vite does not accept JSX on a .js file).

So, in my opinion, we should leave .jsx here so that the example apps work, but use .js in the documentation:

'node_modules/<package-name>/*.js'

What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah let's do that for now

@Dovakeidy

Copy link
Copy Markdown
Contributor Author

Thanks! The Vite example and docs look good. But I don't think we need a TanStack app - it looks like it's just a Vite app. The setup instructions are only really needed for bundlers/frameworks

Would you prefer that I completely remove the app / the TanStack Start documentation, and the TypeScript documentation?

@necolas

necolas commented Dec 5, 2025

Copy link
Copy Markdown
Contributor

Yes please

Thanks for figuring out how to integrate RSD with Vite and creating the Vite example. Really good for the library and a big help

Still open to things like having dedicated TS docs if there is more to document. (And TS help in general. Meta doesn't use them and this repo doesn't test them

@Dovakeidy

Copy link
Copy Markdown
Contributor Author

Okay @necolas , anything else to change before merging?

@necolas necolas closed this in 2db20e0 Dec 5, 2025
@necolas

necolas commented Dec 5, 2025

Copy link
Copy Markdown
Contributor

Merged! Thanks again!

@MoOx

MoOx commented Dec 15, 2025

Copy link
Copy Markdown
Contributor

I was about to do some testing because I am having performance issue currently (mostly postcss plugin being REALLY slow) and wanted to see how the vite example from this PR works and I am getting this issues:

> vite-app@0.0.54 dev
> vite


  VITE v7.2.6  ready in 228 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help
(!) Failed to run dependency scan. Skipping dependency pre-bundling. Error:   Failed to scan for dependencies from entries:
  /Users/moox/dev/react-strict-dom/apps/vite-app/index.html

  ✘ [ERROR] The JSX syntax extension is not currently enabled

    ../example-ui/Button/index.jsx:16:9:
      16 │   return <button data-element-src="Button/index.jsx:16" {..._rsdMe...
         ╵          ^

  The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able to parse JSX syntax. You can use "loader: { '.js': 'jsx' }" to do that.


✘ [ERROR] The JSX syntax extension is not currently enabled

    ../example-ui/NativeForkButton/index.jsx:16:9:
      16 │   return <button data-element-src="NativeForkButton/index.jsx:16" ...
         ╵          ^

  The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able to parse JSX syntax. You can use "loader: { '.js': 'jsx' }" to do that.


✘ [ERROR] The JSX syntax extension is not currently enabled

    ../example-ui/PlatformButton/index.web.jsx:15:9:
      15 │   return <button style={styles.pressable} type="button">
         ╵          ^

  The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able to parse JSX syntax. You can use "loader: { '.js': 'jsx' }" to do that.


✘ [ERROR] The JSX syntax extension is not currently enabled

    ../example-ui/PlatformShell/index.web.jsx:10:9:
      10 │   return <div>
         ╵          ^

  The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able to parse JSX syntax. You can use "loader: { '.js': 'jsx' }" to do that.


✘ [ERROR] The JSX syntax extension is not currently enabled

    ../example-ui/WebForkButton/index.web.jsx:14:9:
      14 │   return <button style={styles.pressable} type="button">
         ╵          ^

  The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able to parse JSX syntax. You can use "loader: { '.js': 'jsx' }" to do that.


    at failureErrorWithLog (/Users/moox/dev/react-strict-dom/node_modules/esbuild/lib/main.js:1467:15)
    at /Users/moox/dev/react-strict-dom/node_modules/esbuild/lib/main.js:926:25
    at runOnEndCallbacks (/Users/moox/dev/react-strict-dom/node_modules/esbuild/lib/main.js:1307:45)
    at buildResponseToResult (/Users/moox/dev/react-strict-dom/node_modules/esbuild/lib/main.js:924:7)
    at /Users/moox/dev/react-strict-dom/node_modules/esbuild/lib/main.js:936:9
    at new Promise (<anonymous>)
    at requestCallbacks.on-end (/Users/moox/dev/react-strict-dom/node_modules/esbuild/lib/main.js:935:54)
    at handleRequest (/Users/moox/dev/react-strict-dom/node_modules/esbuild/lib/main.js:628:17)
    at handleIncomingPacket (/Users/moox/dev/react-strict-dom/node_modules/esbuild/lib/main.js:653:7)
    at Socket.readFromStdout (/Users/moox/dev/react-strict-dom/node_modules/esbuild/lib/main.js:581:7)
    at Socket.emit (node:events:508:28)
    at addChunk (node:internal/streams/readable:559:12)
    at readableAddChunkPushByteMode (node:internal/streams/readable:510:3)
    at Readable.push (node:internal/streams/readable:390:5)
    at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)

@Dovakeidy

Copy link
Copy Markdown
Contributor Author

@MoOx

It's strange that it worked one day, I don't understand. You can fix this by including example-ui in the babel configuration.

Can you confirm that it works so that I can make the change? Thank you!

vite.config.ts

    react({
      babel: {
        configFile: true
      },
      include: ['example-ui'] // <===
    }),

@MoOx

MoOx commented Dec 15, 2025

Copy link
Copy Markdown
Contributor

Just to let you know, I had to add

  esbuild: {
    loader: "tsx",
    include: /.*\.[tj]sx?$/,
  },

into vite.config.ts. Also, not sure why but HMR isn't working and even remove property with current setup. I was just trying to add a borderRadius, didn't see it, killed vite, restarted, radius was here, I edited the file, vite says "hmr update /@fs/Users/moox/dev/react-strict-dom/apps/example-ui/Button/index.jsx" but after that radius is gone. what a mess.

I found what caused my performance issue (misconfigured postcss glob with */ which cause a terrible experience).

I have no issue with my current setup which includes some tweaks (probably unncessary in RSD repo since I guess RSD itself isn't really a normal "node_modules)

export default defineConfig({
  // ...
  plugins: [
    //...
    viteReact({
      babel: { configFile: true },
      exclude: [/\/node_modules\/(?!react-strict-dom)/], // necessary
    }),
  ],
  ssr: {
    noExternal: ["react-strict-dom"], // necessary
  },
  optimizeDeps: {
    exclude: ["react-strict-dom"], // necessary
  },
});

Any reason you skipped those ? I suspect this could cause trouble to new comers.

@Dovakeidy

Copy link
Copy Markdown
Contributor Author

@MoOx
Does the example you sent use TanStack Start? Otherwise, I don't see the point of using this configuration (especially SSR). I think what I sent just before should be sufficient for the Vite example. Can you confirm?

@MoOx

MoOx commented Dec 16, 2025

Copy link
Copy Markdown
Contributor

Yeah it's working but hot reloading isn't but it seems related to the internal setup.
I have tried a fresh vite app following actual docs and (beside minor adjustments I am going to push in a PR) it's working with your recommendation.
What I missed is the use of vite-plugin-babel in addition to viteReact which handle babel exclude + optimizeDeps above.
SSR is required for tanstack tho, and I guess it should be mentioned in docs (going to add a "tanstack" mention in docs).

@necolas not sure if that's the case but maybe "apps" folder should be part of CI at some point to be sure the actual example works ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants