Jack Hsu 45c458e677
fix(react): generate valid Vite + JSX setup for React (#27130)
The current `@nx/react:app` generator does not take the `--js` option
into account. There are two problems:

1. `index.html` includes `main.tsx` not `main.jsx`.
2. `.js` files with JSX are invalid in Vite, and must be named `.jsx`.

This PR adds a new option to the `toJS` devkit util to preserve `.jsx`
rather than renaming them to `.js`. The vast majority of non-Vite React
projects will use `.js` and not `.jsx` (e.g. Next.js, Expo, Remix, etc.)
so we just want to apply this change to Vite only for now.

In the future we could enhance React generators to support `--jsx`, for
example.

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #20810
2024-07-26 08:30:16 -04:00

48 lines
1.4 KiB
TypeScript

import type { Tree } from 'nx/src/devkit-exports';
import type { ModuleKind, ScriptTarget } from 'typescript';
import { typescriptVersion } from '../utils/versions';
import { ensurePackage } from '../utils/package-json';
export type ToJSOptions = {
extension?: '.js' | '.mjs' | '.cjs';
module?: ModuleKind;
target?: ScriptTarget;
useJsx?: boolean;
};
/**
* Rename and transpile any new typescript files created to javascript files
*/
export function toJS(tree: Tree, options?: ToJSOptions): void {
const { JsxEmit, ScriptTarget, transpile, ModuleKind } = ensurePackage(
'typescript',
typescriptVersion
) as typeof import('typescript');
for (const c of tree.listChanges()) {
if (
(c.path.endsWith('.ts') || c.path.endsWith('tsx')) &&
c.type === 'CREATE'
) {
tree.write(
c.path,
transpile(c.content.toString('utf-8'), {
allowJs: true,
jsx: JsxEmit.Preserve,
target: options?.target ?? ScriptTarget.ESNext,
module: options?.module ?? ModuleKind.ESNext,
})
);
tree.rename(c.path, c.path.replace(/\.ts$/, options?.extension ?? '.js'));
if (options?.useJsx) {
tree.rename(c.path, c.path.replace(/\.tsx$/, '.jsx'));
} else {
tree.rename(
c.path,
c.path.replace(/\.tsx$/, options?.extension ?? '.js')
);
}
}
}
}