react icon indicating copy to clipboard operation
react copied to clipboard

[React 19] React Compiler is stripping spaces

Open Curetix opened this issue 1 year ago • 9 comments

Summary

I tested the React Compiler by starting with the Vite React TS Template, updating to React 19 and adding the compiler plugin as described in the docs. With the compiler enabled, the component is missing spaces in some strings (count is0 and Editsrc/App.tsx):

image

The relevant code is:

<div className="card">
  <button onClick={() => setCount((count) => count + 1)}>
    count is {count}
  </button>
  <p>
    Edit <code>src/App.tsx</code> and save to test HMR
  </p>
</div>

Stackblitz: https://stackblitz.com/edit/vitejs-vite-y8oj4e

Curetix avatar May 16 '24 08:05 Curetix

i think To address the issue with the React Compiler stripping spaces, you might need to adjust the configuration of the React Compiler or update the compiler plugin settings. npm install @vitejs/plugin-react@latest

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
});

HoseinKhanBeigi avatar May 16 '24 15:05 HoseinKhanBeigi

This could be unrelated but disabling Babel's retainLines option inside @vitejs/plugin-react fixes it for me. When the option is enabled (!isProduction && isJSX && opts.jsxRuntime !== 'classic') a simple component like this:

import { useState } from 'react';

function App() {
  const [count, setCount] = useState(0);

  return (
    <div className="card">
      <button onClick={() => setCount((count) => count + 1)}>
        count is {count}
      </button>
      <p>
        Edit <code>src/App.tsx</code> and save to test HMR
      </p>
    </div>
  );
}

export default App;

... gets transformed into:

import { c as _c } from "react/compiler-runtime";

import { useState } from 'react';



function App() {const $ = _c(6);
  const [count, setCount] = useState(0);let t0;if ($[0] === Symbol.for("react.memo_cache_sentinel")) {




    t0 = () => setCount((count_0) => count_0 + 1);$[0] = t0;} else {t0 = $[0];}let t1;if ($[1] !== count) {t1 = <button onClick={t0}>count is
      {count}
    </button>;$[1] = count;$[2] = t1;} else {t1 = $[2];}let t2;if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
    t2 = <p>Edit
      <code>src/App.tsx</code> and save to test HMR
    </p>;$[3] = t2;} else {t2 = $[3];}let t3;if ($[4] !== t1) {t3 = <div className="card">{t1}{t2}
    </div>;$[4] = t1;$[5] = t3;} else {t3 = $[5];}return t3;}




export default App;

and then ESBuild transforms it and we lose whitespace due to how the above output is split into multiple lines:

// shortened for brevity
t1 = /* @__PURE__ */ jsxDEV("button", { onClick: t0, children: [
  "count is",
  count
] }, void 0, true, {
  fileName: "src/App.tsx",
  lineNumber: 13,
  columnNumber: 113
}, this);

damianstasik avatar May 16 '24 18:05 damianstasik

Spaces are not stripped on build. The issue seems to be with ESBuild.

abizek avatar May 17 '24 08:05 abizek

It happens before the step with ESBuild – it's something that Babel does when the retainLines option is enabled. I've checked running the code from the playground through ESBuild with Vite's internal config and the output was correct.

damianstasik avatar May 18 '24 08:05 damianstasik

Hi there. I think retains line doesn't make sense when the compiler is enabled, lines get move around too much. I'll publish a fix for that tomorrow.

ArnaudBarre avatar May 19 '24 21:05 ArnaudBarre

Thanks for reporting this! It sounds like this is an issue with how React Compiler and other tools are interacting. You can see from the playground that the compiler is retaining the space: https://playground.react.dev/#N4Igzg9grgTgxgUxALhAMygOzgFwJYSYAEAYhBABQCURwAOsUTAjrMRQ0V0QDwAmeAG5E4AGwCGYMADlxAWwREAvETog44mHzVEAfJ14AjKDhyEihAMKi8cANZLg1ZbqJgWl6JhwUKcLzg0Sq7+WDhEANREAIxUAL76jFyh3kR4YLQpOHEGPAD0xqaEiVw8AA4l3ACiAuE8-nwIumDweQCCZWUAdDhgAB75DU1E4ph8buKCimZEOAhg4QASALIASrl5FQz5AoK6VADcDHEgcUA

but we definitely want to make sure that it also just works with other tools. We’ll take a look!

josephsavona avatar May 19 '24 22:05 josephsavona

how did you guys fix it? I tried disabling retainLines but it didnt work

Facug03 avatar May 20 '24 19:05 Facug03

@Facug03 if this lands retainLines will be disabled automatically if your Babel config includes babel-plugin-react-compiler.

damianstasik avatar May 22 '24 14:05 damianstasik

Just released in 4.3.0.

@josephsavona You probably want to remove this line too. I think this Babel option was made to avoid using source maps on light transformation, but I don't think it's enough robust to support AST re-ordering like the compiler is doing. I think this is fine to say that this is incompatible (maybe a warning could be logged when the option is enabled)

ArnaudBarre avatar May 22 '24 18:05 ArnaudBarre

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

github-actions[bot] avatar Aug 20 '24 19:08 github-actions[bot]

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!

github-actions[bot] avatar Aug 27 '24 19:08 github-actions[bot]