Skip to content

Commit e943859

Browse files
make path to rsc bundel and react client manifest configurable
1 parent 6a79df7 commit e943859

File tree

6 files changed

+49
-18
lines changed

6 files changed

+49
-18
lines changed

lib/react_on_rails/configuration.rb

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

1111
DEFAULT_GENERATED_ASSETS_DIR = File.join(%w[public webpack], Rails.env).freeze
12+
DEFAULT_REACT_CLIENT_MANIFEST_FILE = "react-client-manifest.json"
1213

1314
def self.configuration
1415
@configuration ||= Configuration.new(
@@ -18,6 +19,7 @@ def self.configuration
1819
generated_assets_dir: "",
1920
server_bundle_js_file: "",
2021
rsc_bundle_js_file: "",
22+
react_client_manifest_file: DEFAULT_REACT_CLIENT_MANIFEST_FILE,
2123
prerender: false,
2224
auto_load_bundle: false,
2325
replay_console: true,
@@ -57,8 +59,8 @@ class Configuration
5759
:server_render_method, :random_dom_id, :auto_load_bundle,
5860
:same_bundle_for_client_and_server, :rendering_props_extension,
5961
:make_generated_server_bundle_the_entrypoint,
60-
:defer_generated_component_packs, :rsc_bundle_js_file,
61-
:force_load
62+
:defer_generated_component_packs, :force_load, :rsc_bundle_js_file,
63+
:react_client_manifest_file
6264

6365
# rubocop:disable Metrics/AbcSize
6466
def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
@@ -74,7 +76,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
7476
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil, i18n_yml_safe_load_options: nil,
7577
random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil,
7678
components_subdirectory: nil, auto_load_bundle: nil, force_load: nil,
77-
rsc_bundle_js_file: nil)
79+
rsc_bundle_js_file: nil, react_client_manifest_file: nil)
7880
self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
7981
self.generated_assets_dirs = generated_assets_dirs
8082
self.generated_assets_dir = generated_assets_dir
@@ -102,6 +104,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
102104
# Server rendering:
103105
self.server_bundle_js_file = server_bundle_js_file
104106
self.rsc_bundle_js_file = rsc_bundle_js_file
107+
self.react_client_manifest_file = react_client_manifest_file
105108
self.same_bundle_for_client_and_server = same_bundle_for_client_and_server
106109
self.server_renderer_pool_size = self.development_mode ? 1 : server_renderer_pool_size
107110
self.server_renderer_timeout = server_renderer_timeout # seconds
@@ -247,6 +250,8 @@ def ensure_webpack_generated_files_exists
247250
files = ["manifest.json"]
248251
files << server_bundle_js_file if server_bundle_js_file.present?
249252
files << rsc_bundle_js_file if rsc_bundle_js_file.present?
253+
files << react_client_manifest_file if react_client_manifest_file.present?
254+
250255
self.webpack_generated_files = files
251256
end
252257

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
@@ -126,6 +126,10 @@ export interface RenderParams extends Params {
126126
renderingReturnsPromises: boolean;
127127
}
128128

129+
export interface RSCRenderParams extends RenderParams {
130+
reactClientManifestFileName: string;
131+
}
132+
129133
export interface CreateParams extends Params {
130134
componentObj: RegisteredComponent;
131135
shouldHydrate?: boolean;
@@ -185,7 +189,7 @@ export interface ReactOnRails {
185189
getOrWaitForComponent(name: string): Promise<RegisteredComponent>;
186190
serverRenderReactComponent(options: RenderParams): null | string | Promise<RenderResult>;
187191
streamServerRenderedReactComponent(options: RenderParams): Readable;
188-
serverRenderRSCReactComponent(options: RenderParams): Readable;
192+
serverRenderRSCReactComponent(options: RSCRenderParams): Readable;
189193
handleError(options: ErrorOptions): string | undefined;
190194
buildConsoleReplay(): string;
191195
registeredComponents(): Map<string, RegisteredComponent>;

0 commit comments

Comments
 (0)