Skip to content

Commit

Permalink
Throw error when attempting to redefine ReactOnRails global
Browse files Browse the repository at this point in the history
Webpack configuration could attempt to import react-on-rails multiple times in
each runtime chunk, leading to the global ReactOnRails variable being
overridden and client rendering crashes. This should be avoided by relying on a
single runtime chunk.

Read more at #1558.
  • Loading branch information
rubenochiavone committed Jul 20, 2023
1 parent 7c366b6 commit 312593b
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 0 deletions.
80 changes: 80 additions & 0 deletions docs/javascript/troubleshooting-when-using-webpacker.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,83 @@
# Client rendering crashes when configuring `optimization.runtimeChunk` to `multiple`

## Context

1. Ruby version: 3.1
2. Rails version: 7.0.6
3. Shakapacker version: 6.6.0
4. React on Rails version: 13.3.5

## The failure

Configuring webpack to embed the runtime in each chunk and calling `react_component` twice in a rails view/partial causes the client render to crash with the following error:

```
Could not find component registered with name XXX. Registered component names include [ YYY ]. Maybe you forgot to register the component?
```

```
VM4859 clientStartup.js:132 Uncaught Error: ReactOnRails encountered an error while rendering component: XXX. See above error message.
at Object.get (ComponentRegistry.js:40:15)
at Object.getComponent (ReactOnRails.js:211:44)
at render (VM4859 clientStartup.js:103:53)
at forEachReactOnRailsComponentRender (VM4859 clientStartup.js:138:9)
at reactOnRailsPageLoaded (VM4859 clientStartup.js:164:5)
at renderInit (VM4859 clientStartup.js:205:9)
at onPageReady (VM4859 clientStartup.js:234:9)
at HTMLDocument.onReadyStateChange (VM4859 clientStartup.js:238:13)
```

## Configs

### Webpack configuration

```js
optimization: {
runtimeChunk: 'multiple'
},
```

### Rails view

```haml
= react_component("XXX", props: @props)
= yield
= react_component("YYY", props: @props)
```

## The problem

Configuring webpack to embed the runtime in each chunk and calling `react_component` twice in a rails view/partial causes the client render to crash.

Read more at https://github.com/shakacode/react_on_rails/issues/1558.

## Solution

To overcome this issue, we could use [shakapacker](https://github.com/shakacode/shakapacker)'s default optimization configuration (pseudo-code):

```js
const { webpackConfig: baseClientWebpackConfig } = require('shakapacker');

// ...

config.optimization = baseClientWebpackConfig.optimization;
```
As it set the `optimization.runtimeChunk` to `single`. See its source:

`package/environments/base.js:115`
```js
optimization: {
splitChunks: { chunks: 'all' },

runtimeChunk: 'single'
},
```
https://github.com/shakacode/shakapacker/blob/cdf32835d3e0949952b8b4b53063807f714f9b24/package/environments/base.js#L115-L119

Or set `optimization.runtimeChunk` to `single` directly.

# When `ReactOnRails.configuration.webpack_generated_files` is specified, it prevents usage of `manifest.json`

## Context

Rails: 5.0.2
Expand Down
10 changes: 10 additions & 0 deletions node_package/src/ReactOnRails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ if (ctx === undefined) {
throw new Error("The context (usually Window or NodeJS's Global) is undefined.");
}

if (ctx.ReactOnRails !== undefined) {
throw new Error(`
The ReactOnRails value exists in the ${ctx} scope, it may not be safe to overwrite it.
This could be caused by setting Webpack's optimization.runtimeChunk to "true" or "multiple" - please check your Webpack configuration.
Read more at https://github.com/shakacode/react_on_rails/issues/1558.
`);
}

const DEFAULT_OPTIONS = {
traceTurbolinks: false,
turbo: false,
Expand Down

0 comments on commit 312593b

Please sign in to comment.