Skip to content

Commit c20576d

Browse files
make path to rsc bundel and react client manifest configurable
1 parent 26e11ba commit c20576d

File tree

6 files changed

+50
-18
lines changed

6 files changed

+50
-18
lines changed

lib/react_on_rails/configuration.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def self.configure
1010

1111
DEFAULT_GENERATED_ASSETS_DIR = File.join(%w[public webpack], Rails.env).freeze
1212
DEFAULT_RSC_RENDERING_URL = "rsc/".freeze
13+
DEFAULT_REACT_CLIENT_MANIFEST_FILE = "react-client-manifest.json".freeze
1314

1415
def self.configuration
1516
@configuration ||= Configuration.new(
@@ -19,6 +20,7 @@ def self.configuration
1920
generated_assets_dir: "",
2021
server_bundle_js_file: "",
2122
rsc_bundle_js_file: "",
23+
react_client_manifest_file: DEFAULT_REACT_CLIENT_MANIFEST_FILE,
2224
prerender: false,
2325
auto_load_bundle: false,
2426
replay_console: true,
@@ -59,8 +61,8 @@ class Configuration
5961
:server_render_method, :random_dom_id, :auto_load_bundle,
6062
:same_bundle_for_client_and_server, :rendering_props_extension,
6163
:make_generated_server_bundle_the_entrypoint,
62-
:defer_generated_component_packs, :rsc_bundle_js_file,
63-
:force_load, :auto_load_server_components, :rsc_rendering_url
64+
:defer_generated_component_packs, :force_load, :auto_load_server_components,
65+
:rsc_rendering_url, :rsc_bundle_js_file, :react_client_manifest_file
6466

6567
# rubocop:disable Metrics/AbcSize
6668
def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
@@ -76,7 +78,8 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
7678
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil,
7779
random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil,
7880
components_subdirectory: nil, auto_load_bundle: nil, force_load: nil,
79-
rsc_bundle_js_file: nil, auto_load_server_components: nil, rsc_rendering_url: nil)
81+
auto_load_server_components: nil, rsc_rendering_url: nil, rsc_bundle_js_file: nil,
82+
react_client_manifest_file: nil)
8083
self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
8184
self.generated_assets_dirs = generated_assets_dirs
8285
self.generated_assets_dir = generated_assets_dir
@@ -103,6 +106,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
103106
# Server rendering:
104107
self.server_bundle_js_file = server_bundle_js_file
105108
self.rsc_bundle_js_file = rsc_bundle_js_file
109+
self.react_client_manifest_file = react_client_manifest_file
106110
self.same_bundle_for_client_and_server = same_bundle_for_client_and_server
107111
self.server_renderer_pool_size = self.development_mode ? 1 : server_renderer_pool_size
108112
self.server_renderer_timeout = server_renderer_timeout # seconds
@@ -250,6 +254,8 @@ def ensure_webpack_generated_files_exists
250254
files = ["manifest.json"]
251255
files << server_bundle_js_file if server_bundle_js_file.present?
252256
files << rsc_bundle_js_file if rsc_bundle_js_file.present?
257+
files << react_client_manifest_file if react_client_manifest_file.present?
258+
253259
self.webpack_generated_files = files
254260
end
255261

lib/react_on_rails/utils.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ def self.rsc_bundle_js_file_path
109109
@rsc_bundle_path = bundle_js_file_path(bundle_name)
110110
end
111111

112+
def self.react_client_manifest_file_path
113+
return @react_client_manifest_path if @react_client_manifest_path && !Rails.env.development?
114+
115+
file_name = ReactOnRails.configuration.react_client_manifest_file
116+
@react_client_manifest_path = bundle_js_file_path(file_name)
117+
end
118+
112119
def self.running_on_windows?
113120
(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
114121
end

node_package/src/ReactOnRailsRSC.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { renderToPipeableStream } from 'react-server-dom-webpack/server.node';
22
import { PassThrough, Readable } from 'stream';
33
import type { ReactElement } from 'react';
4-
import fs from 'fs';
54

6-
import { RenderParams } from './types';
5+
import { RSCRenderParams } from './types';
76
import ReactOnRails from './ReactOnRails';
87
import buildConsoleReplay from './buildConsoleReplay';
98
import handleError from './handleError';
@@ -14,6 +13,7 @@ import {
1413
convertToError,
1514
createResultObject,
1615
} from './serverRenderReactComponent';
16+
import loadReactClientManifest from './loadReactClientManifest';
1717

1818
const stringToStream = (str: string) => {
1919
const stream = new PassThrough();
@@ -22,10 +22,8 @@ const stringToStream = (str: string) => {
2222
return stream;
2323
};
2424

25-
const getBundleConfig = () => JSON.parse(fs.readFileSync('./public/webpack/development/react-client-manifest.json', 'utf8'))
26-
27-
const streamRenderRSCComponent = (reactElement: ReactElement, options: RenderParams): Readable => {
28-
const { throwJsErrors } = options;
25+
const streamRenderRSCComponent = (reactElement: ReactElement, options: RSCRenderParams): Readable => {
26+
const { throwJsErrors, reactClientManifestFileName } = options;
2927
const renderState: StreamRenderState = {
3028
result: null,
3129
hasErrors: false,
@@ -36,7 +34,7 @@ const streamRenderRSCComponent = (reactElement: ReactElement, options: RenderPar
3634
try {
3735
const rscStream = renderToPipeableStream(
3836
reactElement,
39-
getBundleConfig(),
37+
loadReactClientManifest(reactClientManifestFileName),
4038
{
4139
onError: (err) => {
4240
const error = convertToError(err);
@@ -61,7 +59,7 @@ const streamRenderRSCComponent = (reactElement: ReactElement, options: RenderPar
6159
}
6260
};
6361

64-
ReactOnRails.serverRenderRSCReactComponent = (options: RenderParams) => {
62+
ReactOnRails.serverRenderRSCReactComponent = (options: RSCRenderParams) => {
6563
try {
6664
return streamServerRenderedComponent(options, streamRenderRSCComponent);
6765
} finally {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import path from 'path';
2+
import fs from 'fs';
3+
4+
const loadedReactClientManifests = new Map<string, { [key: string]: unknown; }>();
5+
6+
export default function loadReactClientManifest(reactClientManifestFileName: string) {
7+
// React client manifest is uploaded to node renderer as an asset.
8+
// Renderer copies assets to the same place as the server-bundle.js and rsc-bundle.js.
9+
// Thus, the __dirname of this code is where we can find the manifest file.
10+
const manifestPath = path.resolve(__dirname, reactClientManifestFileName);
11+
if (!loadedReactClientManifests.has(manifestPath)) {
12+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
13+
loadedReactClientManifests.set(manifestPath, manifest);
14+
}
15+
16+
return loadedReactClientManifests.get(manifestPath)!;
17+
}

node_package/src/serverRenderReactComponent.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,14 @@ const streamRenderReactComponent = (reactRenderingResult: ReactElement, options:
298298
return readableStream;
299299
}
300300

301-
export type StreamRenderer<T> = (
301+
export type StreamRenderer<T, P extends RenderParams> = (
302302
reactElement: ReactElement,
303-
options: RenderParams
303+
options: P
304304
) => T;
305305

306-
export const streamServerRenderedComponent = <T>(
307-
options: RenderParams,
308-
renderStrategy: StreamRenderer<T>
306+
export const streamServerRenderedComponent = <T, P extends RenderParams>(
307+
options: P,
308+
renderStrategy: StreamRenderer<T, P>
309309
): T => {
310310
const { name: componentName, domNodeId, trace, props, railsContext, throwJsErrors } = options;
311311

node_package/src/types/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/// <reference types="react/experimental" />
33

44
import type { ReactElement, ReactNode, Component, ComponentType } from 'react';
5-
import type { Readable, PassThrough } from 'stream';
5+
import type { Readable } from 'stream';
66

77
// Don't import redux just for the type definitions
88
// See https://github.com/shakacode/react_on_rails/issues/1321
@@ -122,6 +122,10 @@ export interface RenderParams extends Params {
122122
renderingReturnsPromises: boolean;
123123
}
124124

125+
export interface RSCRenderParams extends RenderParams {
126+
reactClientManifestFileName: string;
127+
}
128+
125129
export interface CreateParams extends Params {
126130
componentObj: RegisteredComponent;
127131
shouldHydrate?: boolean;
@@ -181,7 +185,7 @@ export interface ReactOnRails {
181185
getOrWaitForComponent(name: string): Promise<RegisteredComponent>;
182186
serverRenderReactComponent(options: RenderParams): null | string | Promise<RenderResult>;
183187
streamServerRenderedReactComponent(options: RenderParams): Readable;
184-
serverRenderRSCReactComponent(options: RenderParams): Readable;
188+
serverRenderRSCReactComponent(options: RSCRenderParams): Readable;
185189
handleError(options: ErrorOptions): string | undefined;
186190
buildConsoleReplay(): string;
187191
registeredComponents(): Map<string, RegisteredComponent>;

0 commit comments

Comments
 (0)