Skip to content

Commit

Permalink
make path to rsc bundel and react client manifest configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
AbanoubGhadban committed Dec 23, 2024
1 parent 26e11ba commit c20576d
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 18 deletions.
12 changes: 9 additions & 3 deletions lib/react_on_rails/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def self.configure

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

def self.configuration
@configuration ||= Configuration.new(
Expand All @@ -19,6 +20,7 @@ def self.configuration
generated_assets_dir: "",
server_bundle_js_file: "",
rsc_bundle_js_file: "",
react_client_manifest_file: DEFAULT_REACT_CLIENT_MANIFEST_FILE,
prerender: false,
auto_load_bundle: false,
replay_console: true,
Expand Down Expand Up @@ -59,8 +61,8 @@ class Configuration
:server_render_method, :random_dom_id, :auto_load_bundle,
:same_bundle_for_client_and_server, :rendering_props_extension,
:make_generated_server_bundle_the_entrypoint,
:defer_generated_component_packs, :rsc_bundle_js_file,
:force_load, :auto_load_server_components, :rsc_rendering_url
:defer_generated_component_packs, :force_load, :auto_load_server_components,
:rsc_rendering_url, :rsc_bundle_js_file, :react_client_manifest_file

# rubocop:disable Metrics/AbcSize
def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender: nil,
Expand All @@ -76,7 +78,8 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil,
random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil,
components_subdirectory: nil, auto_load_bundle: nil, force_load: nil,
rsc_bundle_js_file: nil, auto_load_server_components: nil, rsc_rendering_url: nil)
auto_load_server_components: nil, rsc_rendering_url: nil, rsc_bundle_js_file: nil,
react_client_manifest_file: nil)
self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
self.generated_assets_dirs = generated_assets_dirs
self.generated_assets_dir = generated_assets_dir
Expand All @@ -103,6 +106,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
# Server rendering:
self.server_bundle_js_file = server_bundle_js_file
self.rsc_bundle_js_file = rsc_bundle_js_file
self.react_client_manifest_file = react_client_manifest_file
self.same_bundle_for_client_and_server = same_bundle_for_client_and_server
self.server_renderer_pool_size = self.development_mode ? 1 : server_renderer_pool_size
self.server_renderer_timeout = server_renderer_timeout # seconds
Expand Down Expand Up @@ -250,6 +254,8 @@ def ensure_webpack_generated_files_exists
files = ["manifest.json"]
files << server_bundle_js_file if server_bundle_js_file.present?
files << rsc_bundle_js_file if rsc_bundle_js_file.present?
files << react_client_manifest_file if react_client_manifest_file.present?

self.webpack_generated_files = files
end

Expand Down
7 changes: 7 additions & 0 deletions lib/react_on_rails/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ def self.rsc_bundle_js_file_path
@rsc_bundle_path = bundle_js_file_path(bundle_name)
end

def self.react_client_manifest_file_path
return @react_client_manifest_path if @react_client_manifest_path && !Rails.env.development?

file_name = ReactOnRails.configuration.react_client_manifest_file
@react_client_manifest_path = bundle_js_file_path(file_name)
end

def self.running_on_windows?
(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
end
Expand Down
14 changes: 6 additions & 8 deletions node_package/src/ReactOnRailsRSC.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { renderToPipeableStream } from 'react-server-dom-webpack/server.node';
import { PassThrough, Readable } from 'stream';
import type { ReactElement } from 'react';
import fs from 'fs';

import { RenderParams } from './types';
import { RSCRenderParams } from './types';
import ReactOnRails from './ReactOnRails';
import buildConsoleReplay from './buildConsoleReplay';
import handleError from './handleError';
Expand All @@ -14,6 +13,7 @@ import {
convertToError,
createResultObject,
} from './serverRenderReactComponent';
import loadReactClientManifest from './loadReactClientManifest';

const stringToStream = (str: string) => {
const stream = new PassThrough();
Expand All @@ -22,10 +22,8 @@ const stringToStream = (str: string) => {
return stream;
};

const getBundleConfig = () => JSON.parse(fs.readFileSync('./public/webpack/development/react-client-manifest.json', 'utf8'))

const streamRenderRSCComponent = (reactElement: ReactElement, options: RenderParams): Readable => {
const { throwJsErrors } = options;
const streamRenderRSCComponent = (reactElement: ReactElement, options: RSCRenderParams): Readable => {
const { throwJsErrors, reactClientManifestFileName } = options;
const renderState: StreamRenderState = {
result: null,
hasErrors: false,
Expand All @@ -36,7 +34,7 @@ const streamRenderRSCComponent = (reactElement: ReactElement, options: RenderPar
try {
const rscStream = renderToPipeableStream(
reactElement,
getBundleConfig(),
loadReactClientManifest(reactClientManifestFileName),
{
onError: (err) => {
const error = convertToError(err);
Expand All @@ -61,7 +59,7 @@ const streamRenderRSCComponent = (reactElement: ReactElement, options: RenderPar
}
};

ReactOnRails.serverRenderRSCReactComponent = (options: RenderParams) => {
ReactOnRails.serverRenderRSCReactComponent = (options: RSCRenderParams) => {
try {
return streamServerRenderedComponent(options, streamRenderRSCComponent);
} finally {
Expand Down
17 changes: 17 additions & 0 deletions node_package/src/loadReactClientManifest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import path from 'path';
import fs from 'fs';

const loadedReactClientManifests = new Map<string, { [key: string]: unknown; }>();

export default function loadReactClientManifest(reactClientManifestFileName: string) {
// React client manifest is uploaded to node renderer as an asset.
// Renderer copies assets to the same place as the server-bundle.js and rsc-bundle.js.
// Thus, the __dirname of this code is where we can find the manifest file.
const manifestPath = path.resolve(__dirname, reactClientManifestFileName);
if (!loadedReactClientManifests.has(manifestPath)) {
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
loadedReactClientManifests.set(manifestPath, manifest);
}

return loadedReactClientManifests.get(manifestPath)!;
}
10 changes: 5 additions & 5 deletions node_package/src/serverRenderReactComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,14 +298,14 @@ const streamRenderReactComponent = (reactRenderingResult: ReactElement, options:
return readableStream;
}

export type StreamRenderer<T> = (
export type StreamRenderer<T, P extends RenderParams> = (
reactElement: ReactElement,
options: RenderParams
options: P
) => T;

export const streamServerRenderedComponent = <T>(
options: RenderParams,
renderStrategy: StreamRenderer<T>
export const streamServerRenderedComponent = <T, P extends RenderParams>(
options: P,
renderStrategy: StreamRenderer<T, P>
): T => {
const { name: componentName, domNodeId, trace, props, railsContext, throwJsErrors } = options;

Expand Down
8 changes: 6 additions & 2 deletions node_package/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/// <reference types="react/experimental" />

import type { ReactElement, ReactNode, Component, ComponentType } from 'react';
import type { Readable, PassThrough } from 'stream';
import type { Readable } from 'stream';

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

export interface RSCRenderParams extends RenderParams {
reactClientManifestFileName: string;
}

export interface CreateParams extends Params {
componentObj: RegisteredComponent;
shouldHydrate?: boolean;
Expand Down Expand Up @@ -181,7 +185,7 @@ export interface ReactOnRails {
getOrWaitForComponent(name: string): Promise<RegisteredComponent>;
serverRenderReactComponent(options: RenderParams): null | string | Promise<RenderResult>;
streamServerRenderedReactComponent(options: RenderParams): Readable;
serverRenderRSCReactComponent(options: RenderParams): Readable;
serverRenderRSCReactComponent(options: RSCRenderParams): Readable;
handleError(options: ErrorOptions): string | undefined;
buildConsoleReplay(): string;
registeredComponents(): Map<string, RegisteredComponent>;
Expand Down

0 comments on commit c20576d

Please sign in to comment.