Skip to content

Commit 01fc8af

Browse files
committed
Move require into .cts
1 parent a503a07 commit 01fc8af

File tree

5 files changed

+51
-52
lines changed

5 files changed

+51
-52
lines changed

eslint.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ const config = tsEslint.config([
149149
},
150150
},
151151
{
152-
files: ['**/*.ts', '**/*.tsx'],
152+
files: ['**/*.ts{x,}', '**/*.[cm]ts'],
153153

154154
extends: tsEslint.configs.strictTypeChecked,
155155

node_package/src/ClientSideRenderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type { RailsContext, RegisteredComponent, RenderFunction, Root } from './
77
import { getRailsContext, resetRailsContext } from './context.ts';
88
import createReactOutput from './createReactOutput.ts';
99
import { isServerRenderHash } from './isServerRenderResult.ts';
10-
import { supportsRootApi } from './reactApis.ts';
10+
import { supportsRootApi } from './reactApis.cts';
1111
import reactHydrateOrRender from './reactHydrateOrRender.ts';
1212
import { debugTurbolinks } from './turbolinksUtils.ts';
1313
import * as StoreRegistry from './StoreRegistry.ts';

node_package/src/reactApis.cts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import * as ReactDOM from 'react-dom';
2+
import type { ReactElement } from 'react';
3+
import type { RenderReturnType } from './types/index.ts' with { 'resolution-mode': 'import' };
4+
5+
const reactMajorVersion = Number(ReactDOM.version?.split('.')[0]) || 16;
6+
7+
// TODO: once we require React 18, we can remove this and inline everything guarded by it.
8+
export const supportsRootApi = reactMajorVersion >= 18;
9+
10+
// TODO: once React dependency is updated to >= 18, we can remove this and just
11+
// import ReactDOM from 'react-dom/client';
12+
let reactDomClient: typeof import('react-dom/client');
13+
if (supportsRootApi) {
14+
// This will never throw an exception, but it's the way to tell Webpack the dependency is optional
15+
// https://github.com/webpack/webpack/issues/339#issuecomment-47739112
16+
// Unfortunately, it only converts the error to a warning.
17+
try {
18+
// eslint-disable-next-line global-require,@typescript-eslint/no-require-imports
19+
reactDomClient = require('react-dom/client') as typeof import('react-dom/client');
20+
} catch (_e) {
21+
// We should never get here, but if we do, we'll just use the default ReactDOM
22+
// and live with the warning.
23+
reactDomClient = ReactDOM as unknown as typeof import('react-dom/client');
24+
}
25+
}
26+
27+
type HydrateOrRenderType = (domNode: Element, reactElement: ReactElement) => RenderReturnType;
28+
29+
/* eslint-disable @typescript-eslint/no-deprecated,@typescript-eslint/no-non-null-assertion --
30+
* while we need to support React 16
31+
*/
32+
const hydrateProp = 'hydrate';
33+
const renderProp = 'render';
34+
35+
export const reactHydrate: HydrateOrRenderType = supportsRootApi
36+
? reactDomClient!.hydrateRoot
37+
: (domNode, reactElement) => ReactDOM[hydrateProp](reactElement, domNode);
38+
39+
export function reactRender(domNode: Element, reactElement: ReactElement): RenderReturnType {
40+
if (supportsRootApi) {
41+
const root = reactDomClient!.createRoot(domNode);
42+
root.render(reactElement);
43+
return root;
44+
}
45+
46+
return ReactDOM[renderProp](reactElement, domNode);
47+
}
48+
/* eslint-enable @typescript-eslint/no-deprecated,@typescript-eslint/no-non-null-assertion */

node_package/src/reactApis.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

node_package/src/reactHydrateOrRender.ts

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,6 @@
11
import type { ReactElement } from 'react';
2-
import * as ReactDOM from 'react-dom';
32
import type { RenderReturnType } from './types/index.ts';
4-
import { supportsRootApi } from './reactApis.ts';
5-
6-
type HydrateOrRenderType = (domNode: Element, reactElement: ReactElement) => RenderReturnType;
7-
8-
// TODO: once React dependency is updated to >= 18, we can remove this and just
9-
// import ReactDOM from 'react-dom/client';
10-
let reactDomClient: typeof import('react-dom/client');
11-
if (supportsRootApi) {
12-
// This will never throw an exception, but it's the way to tell Webpack the dependency is optional
13-
// https://github.com/webpack/webpack/issues/339#issuecomment-47739112
14-
// Unfortunately, it only converts the error to a warning.
15-
try {
16-
// eslint-disable-next-line global-require,@typescript-eslint/no-require-imports
17-
reactDomClient = require('react-dom/client') as typeof import('react-dom/client');
18-
} catch (_e) {
19-
// We should never get here, but if we do, we'll just use the default ReactDOM
20-
// and live with the warning.
21-
reactDomClient = ReactDOM as unknown as typeof import('react-dom/client');
22-
}
23-
}
24-
25-
/* eslint-disable @typescript-eslint/no-deprecated,@typescript-eslint/no-non-null-assertion --
26-
* while we need to support React 16
27-
*/
28-
const hydrateProp = 'hydrate';
29-
const renderProp = 'render';
30-
31-
const reactHydrate: HydrateOrRenderType = supportsRootApi
32-
? reactDomClient!.hydrateRoot
33-
: (domNode, reactElement) => ReactDOM[hydrateProp](reactElement, domNode);
34-
35-
function reactRender(domNode: Element, reactElement: ReactElement): RenderReturnType {
36-
if (supportsRootApi) {
37-
const root = reactDomClient!.createRoot(domNode);
38-
root.render(reactElement);
39-
return root;
40-
}
41-
42-
return ReactDOM[renderProp](reactElement, domNode);
43-
}
44-
/* eslint-enable @typescript-eslint/no-deprecated,@typescript-eslint/no-non-null-assertion */
3+
import { reactHydrate, reactRender } from './reactApis.cts';
454

465
export default function reactHydrateOrRender(
476
domNode: Element,

0 commit comments

Comments
 (0)