Skip to content

Commit 20d4328

Browse files
ihabadhamclaude
andcommitted
Modernize generator and project structure documentation
This commit updates documentation that was 9.5 years outdated, removing references to directory structures and patterns that haven't existed since 2016 and replacing them with accurate modern (2025) guidance. ## Changes to docs/api-reference/generator-details.md - Replace outdated structure description with accurate modern organization - Document both non-Redux and Redux generator structures separately - Add visual directory trees showing actual generated code locations - Document previously undocumented --typescript option - Remove references to non-existent app/lib folder (removed Apr 2016) - Remove incorrect path app/javascript/app/bundles (never existed - was docs typo) - Add auto-bundling explanation with cross-reference - Show real component structure: src/ComponentName/ror_components/ ## Changes to docs/building-features/react-router.md - Update path reference from legacy client/app/bundles to modern src/ structure - Clarify this example applies to --redux generator option - Make path reference generic rather than specific to outdated structure ## Changes to docs/getting-started/project-structure.md Complete rewrite to reflect modern React on Rails: ### Removed outdated content: - Old bundles/ structure presented as current (was 2015-2016 pattern) - "Moving node_modules to /client" section (tested and proven broken with Shakapacker) - References to /client/app/assets directory (generator stopped creating in Apr 2016) - Outdated CSS/assets management discussion ### Added modern content: - Modern auto-bundling structure as recommended approach - Traditional manual structure as legacy option with clear use cases - Decision guide for choosing between approaches - CSS Modules documentation (default in generator since modern versions) - Real code examples from actual generator templates - Rails Asset Pipeline as alternative approach - Advanced global styles pattern ## Historical Context Research revealed: - Oct 2015: Generator created client/app/lib/middlewares/ and client/app/bundles/ - Apr 5, 2016: Docs added describing app/lib folder - Apr 23, 2016: Generator removed these directories (18 days later!) - Apr 2016 - Oct 2025: Docs never updated - outdated for 9.5 years ## Testing Performed Created test app at /home/ihab/ihab/work/shakacode/test/default-structure-test/: - Verified default generator creates src/ structure, not bundles/ - Verified CSS modules co-located with components - Tested /client conversion: works perfectly (just move + config change) - Tested moving node_modules to /client: FAILS with Shakapacker - Confirmed SHAKAPACKER_CONFIG env var doesn't solve the issue 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 76e0836 commit 20d4328

File tree

3 files changed

+187
-49
lines changed

3 files changed

+187
-49
lines changed

docs/api-reference/generator-details.md

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,78 @@ Another good option is to create a simple test app per the [Tutorial](../getting
4141

4242
## Understanding the Organization of the Generated Client Code
4343

44-
The generated client code follows our organization scheme. Each unique set of functionality is given its own folder inside of `app/javascript/app/bundles`. This encourages modularity of _domains_.
44+
The React on Rails generator creates different directory structures depending on whether you use the `--redux` option.
4545

46-
Inside the generated "HelloWorld" domain you will find the following folders:
46+
### Default Structure (Without Redux)
4747

48-
- `startup`: contains the entry point files for webpack. It defaults to a single file that is used for both server and client compilation. But if these need to be different, then you can create two Webpack configurations with separate endpoints. Since RoR v14.2 this is strongly recommended because the client can import `react-on-rails/client` instead of `react-on-rails` for decreased bundle size.
49-
- `containers`: contains "smart components" (components that have functionality and logic that is passed to child "dumb components").
50-
- `components`: contains "dumb components", or components that simply render their properties and call functions given to them as properties by a parent component. Ultimately, at least one of these dumb components will have a parent container component.
48+
The basic generator creates a simple, flat structure optimized for auto-bundling:
5149

52-
You may also notice the `app/lib` folder. This is for any code that is common between bundles and therefore needs to be shared (for example, middleware).
50+
```
51+
app/javascript/
52+
└── src/
53+
└── HelloWorld/
54+
└── ror_components/ # Components auto-registered by React on Rails
55+
├── HelloWorld.jsx # Your React component
56+
├── HelloWorld.module.css
57+
└── HelloWorld.server.js # Optional: separate server rendering logic
58+
```
59+
60+
- **`src/`**: Source directory for all React components
61+
- **`ror_components/`**: Directory name is configurable via `config.components_subdirectory` in `config/initializers/react_on_rails.rb`
62+
- **Auto-registration**: Components in `ror_components/` directories are automatically discovered and registered when using `auto_load_bundle: true`
63+
64+
For components that need different client vs. server implementations, use `.client.jsx` and `.server.jsx` suffixes (e.g., `HelloWorld.client.jsx` and `HelloWorld.server.jsx`).
65+
66+
### Redux Structure (With `--redux` Option)
67+
68+
The Redux generator creates a more structured organization with familiar Redux patterns:
69+
70+
```
71+
app/javascript/
72+
└── src/
73+
└── HelloWorldApp/
74+
├── actions/ # Redux action creators
75+
│ └── helloWorldActionCreators.js
76+
├── components/ # Presentational components
77+
│ ├── HelloWorld.jsx
78+
│ └── HelloWorld.module.css
79+
├── constants/ # Action type constants
80+
│ └── helloWorldConstants.js
81+
├── containers/ # Connected components (smart components)
82+
│ └── HelloWorldContainer.js
83+
├── reducers/ # Redux reducers
84+
│ └── helloWorldReducer.js
85+
├── ror_components/ # Auto-registered entry points
86+
│ ├── HelloWorldApp.client.jsx
87+
│ └── HelloWorldApp.server.jsx
88+
└── store/ # Redux store configuration
89+
└── helloWorldStore.js
90+
```
91+
92+
This structure follows Redux best practices:
93+
94+
- **`components/`**: Presentational "dumb" components that receive data via props
95+
- **`containers/`**: Container "smart" components connected to Redux store
96+
- **`actions/`** and **`reducers/`**: Standard Redux patterns
97+
- **`ror_components/`**: Entry point files that initialize Redux and render the app
98+
99+
### TypeScript Support
100+
101+
The generator also supports a `--typescript` option for generating TypeScript files:
102+
103+
```bash
104+
rails generate react_on_rails:install --typescript
105+
```
106+
107+
This creates `.tsx` files instead of `.jsx` and adds TypeScript configuration.
108+
109+
### Auto-Bundling and Component Registration
53110

54-
### Redux
111+
Modern React on Rails uses auto-bundling to eliminate manual webpack configuration. Components placed in the configured `components_subdirectory` (default: `ror_components`) are automatically:
55112

56-
If you have used the `--redux` generator option, you will notice the familiar additional redux folders in addition to the aforementioned folders. The Hello World example has also been modified to use Redux.
113+
1. Discovered by the generator
114+
2. Bundled into separate webpack entry points
115+
3. Registered for use with `react_component` helper
116+
4. Loaded on-demand when used in views
57117

58-
Note the organizational paradigm of "bundles". These are like application domains and are used for grouping your code into webpack bundles, in case you decide to create different bundles for deployment. This is also useful for separating out logical parts of your application. The concept is that each bundle will have it's own Redux store. If you have code that you want to reuse across bundles, including components and reducers, place them under `/client/app/lib`.
118+
For detailed information on auto-bundling, see the [Auto-Bundling Guide](../core-concepts/auto-bundling-file-system-based-automated-bundle-generation.md).

docs/building-features/react-router.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ _This article needs updating for the latest version of React Router_
44

55
React on Rails supports the use of React Router. Client-side code doesn't need any special configuration for the React on Rails gem. Implement React Router how you normally would. Note, you might want to avoid using Turbolinks as both Turbolinks and React Router will be trying to handle the back and forward buttons. If you get this figured out, please do share with the community! Otherwise, you might have to tweak the basic settings for Turbolinks, and this may or may not be worth the effort.
66

7-
If you are working with the HelloWorldApp created by the react_on_rails generator, then the code below corresponds to the module in `client/app/bundles/HelloWorld/startup/HelloWorldApp.jsx`.
7+
If you are working with the HelloWorldApp created by the react_on_rails generator (with `--redux` option), the code below corresponds to your Redux entry point component (typically in `src/HelloWorldApp/ror_components/`).
88

99
```js
1010
import { BrowserRouter, Switch } from 'react-router-dom';
Lines changed: 117 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,73 @@
1-
# Recommended Project structure
1+
# Recommended Project Structure
22

3-
The React on Rails generator uses the standard Shakapacker convention of this structure:
3+
React on Rails supports two main organizational approaches for your React components.
4+
5+
## Modern Auto-Bundling Structure (Recommended)
6+
7+
The current React on Rails generator creates a component-based structure optimized for automatic bundle generation:
48

59
```text
6-
app/javascript:
7-
├── bundles:
8-
│ # Logical groups of files that can be used for code splitting
9-
│ └── hello-world-bundle.js
10-
├── packs:
11-
│ # only Webpack entry files here
12-
│ └── hello-world-bundle.js
10+
app/javascript/
11+
├── src/
12+
│ ├── HelloWorld/
13+
│ │ ├── HelloWorld.module.css
14+
│ │ └── ror_components/ # Auto-discovered by React on Rails
15+
│ │ ├── HelloWorld.jsx # Client & server rendering
16+
│ │ └── HelloWorld.server.js # Optional: server-only code
17+
│ └── AnotherComponent/
18+
│ └── ror_components/
19+
│ ├── AnotherComponent.client.jsx # Client-only rendering
20+
│ └── AnotherComponent.server.jsx # Server-only rendering
21+
└── packs/
22+
├── generated/ # Auto-generated entry points (gitignored)
23+
│ ├── HelloWorld.js
24+
│ └── AnotherComponent.js
25+
└── server-bundle.js # Server rendering entry point
1326
```
1427

15-
Per the example repo [shakacode/react_on_rails_demo_ssr_hmr](https://github.com/shakacode/react_on_rails_demo_ssr_hmr),
16-
you should consider keeping your codebase mostly consistent with the defaults for [Shakapacker](https://github.com/shakacode/shakapacker).
28+
**Key features:**
29+
30+
- Components in `ror_components/` directories are automatically discovered and registered
31+
- Each component gets its own webpack bundle for optimal code splitting
32+
- No manual `ReactOnRails.register()` calls needed
33+
- Supports separate `.client.jsx` and `.server.jsx` files for different rendering logic
34+
35+
For details, see [Auto-Bundling Guide](../core-concepts/auto-bundling-file-system-based-automated-bundle-generation.md) and [Generator Details](../api-reference/generator-details.md).
36+
37+
## Traditional Manual Structure (Legacy)
38+
39+
For projects requiring explicit control over webpack entry points:
40+
41+
```text
42+
app/javascript/
43+
├── bundles/
44+
│ └── HelloWorld/
45+
│ ├── components/
46+
│ │ └── HelloWorld.jsx
47+
│ └── startup/
48+
│ └── registration.js # Manual ReactOnRails.register()
49+
└── packs/
50+
└── hello-world-bundle.js # Webpack entry point
51+
```
52+
53+
This approach requires manual component registration and webpack configuration but offers complete control over bundling strategy.
54+
55+
## Choosing Your Structure
56+
57+
**Use modern auto-bundling if:**
58+
59+
- Starting a new project
60+
- Want automatic code splitting per component
61+
- Prefer convention over configuration
62+
- Want to minimize boilerplate
63+
64+
**Use traditional manual structure if:**
65+
66+
- Have complex custom webpack requirements
67+
- Need fine-grained control over bundle composition
68+
- Migrating from older React on Rails versions
69+
70+
For most projects, we recommend the modern auto-bundling approach.
1771

1872
## Steps to convert from the generator defaults to use a `/client` directory for source code
1973

@@ -29,47 +83,71 @@ mv app/javascript client
2983
source_path: client
3084
```
3185
32-
## Moving node_modules from `/` to `/client` with a custom Webpack setup
86+
## Styling Your Components
3387
34-
Shakapacker probably doesn't support having your main `node_modules` directory under `/client`, so only follow these steps if you want to use your own Webpack configuration.
88+
React on Rails supports multiple approaches for styling your components. The modern recommended approach uses **CSS Modules** with co-located stylesheets.
3589
36-
1. Move the `/package.json` to `/client/package.json`
37-
2. Create a `/package.json` that delegates to `/client/package.json`.
38-
```json
39-
"scripts": {
40-
"heroku-postbuild": "cd ./client && yarn"
41-
},
42-
```
43-
3. If your `node_modules` directory is not at the top level of the Rails project, then you will need to set the
44-
ENV value of `SHAKAPACKER_CONFIG` to the location of the `config/shakapacker.yml` file per [rails/webpacker PR 2561](https://github.com/rails/webpacker/pull/2561). (Notice the change of spelling from Webpacker to Shakapacker)
90+
### Modern Approach: CSS Modules (Recommended)
4591
46-
## CSS, Sass, Fonts, and Images
92+
The generator creates components with CSS Module support out of the box:
4793
48-
Should you move your styling assets to Webpack, or stick with the plain Rails asset pipeline? It depends!
94+
```text
95+
app/javascript/src/HelloWorld/
96+
├── ror_components/
97+
│ ├── HelloWorld.client.jsx
98+
│ └── HelloWorld.module.css # Co-located with component
99+
```
49100

50-
Here's a good discussion of this option: [Why does Rails 6 include both Webpacker and Sprockets?](https://rossta.net/blog/why-does-rails-install-both-webpacker-and-sprockets.html).
101+
**Example usage:**
51102

52-
You have 2 basic choices:
103+
```jsx
104+
import React from 'react';
105+
import * as style from './HelloWorld.module.css';
53106

54-
### Simple Rails Way
107+
const HelloWorld = () => <label className={style.bright}>Hello World</label>;
108+
```
55109

56-
This isn't really a technique, as you keep handling all your styling assets using Rails standard tools, such as using the [sass-rails gem](https://rubygems.org/gems/sass-rails/versions/5.0.4). Basically, Webpack doesn't get involved with styling. Your Rails layouts just continue doing the styling the standard Rails way.
110+
**Benefits:**
57111

58-
#### Advantages to the Simple Rails Way
112+
- **Scoped styles**: Class names are automatically scoped to prevent conflicts
113+
- **Co-location**: Styles live next to their components for better organization
114+
- **Type safety**: Works seamlessly with TypeScript
115+
- **Hot reloading**: Style changes reload instantly without page refresh
116+
- **Zero configuration**: Works out of the box with the generator
59117

60-
1. Much simpler! There's no change from your current processes.
118+
### Alternative: Rails Asset Pipeline
61119

62-
### Using Webpack to Manage Styling Assets
120+
You can continue using Rails' traditional asset pipeline with [sass-rails](https://rubygems.org/gems/sass-rails) or similar gems:
63121

64-
This technique involves customization of the Webpack config files to generate CSS, image, and font assets.
122+
```erb
123+
<%# app/views/layouts/application.html.erb %>
124+
<%= stylesheet_link_tag 'application', media: 'all' %>
125+
```
65126

66-
#### Directory structure
127+
**Use this approach when:**
67128

68-
1. `/client/app/assets`: Assets for CSS for client app.
69-
1. `/client/app/assets/fonts` and `/client/app/assets/styles`: Globally shared assets for styling. Note, most Sass and image assets will be stored next to the JavaScript files.
129+
- You have existing Rails stylesheets you want to keep
130+
- You prefer keeping styles completely separate from JavaScript
131+
- You don't need component-scoped styling
70132

71-
#### Advantages to having Webpack Manage Styles
133+
### Advanced: Global Styles with Webpack
72134

73-
1. You can use [CSS modules](https://github.com/css-modules/css-modules), which is super compelling once you see the benefits.
74-
1. You can use CSS in JS.
75-
1. You can do hot reloading of your assets. Thus, you do not have to refresh your web page to see asset change, including changing styles.
135+
For global styles (fonts, resets, variables), you can create additional webpack entry points:
136+
137+
```text
138+
app/javascript/
139+
├── packs/
140+
│ ├── application.css # Global styles
141+
│ └── server-bundle.js
142+
└── src/
143+
└── HelloWorld/
144+
└── ror_components/
145+
├── HelloWorld.jsx
146+
└── HelloWorld.module.css
147+
```
148+
149+
Import global styles in your layout:
150+
151+
```erb
152+
<%= stylesheet_pack_tag 'application' %>
153+
```

0 commit comments

Comments
 (0)