Skip to content

Commit 52a1855

Browse files
authored
Fix CSS module handling in pack generator (#1769)
Enhance pack generation workflow with CSS module filtering and automated dev tooling Major improvements to the React on Rails development experience: **CSS Module Fix (Fixes #1768)** - Add COMPONENT_EXTENSIONS regex to filter valid React component files - Prevent CSS modules from being processed as components, fixing build failures - Add comprehensive tests for file filtering logic **Automated Development Workflow** - Integrate automatic pack generation into bin/dev scripts - Add detailed cleaning feedback with file listing and timing - Unify bin/dev script to support both server and static modes - Replace bin/dev-static with unified approach **Developer Experience Improvements** - Enhanced rake task output with Rainbow colors and progress feedback - Targeted cleaning to preserve generated files while removing obsolete ones - Clear error messages and fail-fast behavior for pack generation - Add CODING_AGENTS.md guide for AI contributors **Technical Enhancements** - Refactor complex methods to meet RuboCop compliance - Improve error handling and edge case management - Update all documentation to reflect unified bin/dev approach - Add comprehensive test coverage for new functionality This change eliminates manual pack generation steps, prevents CSS module build failures, and significantly improves the developer onboarding experience while maintaining backward compatibility. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent f4adcd9 commit 52a1855

File tree

19 files changed

+721
-188
lines changed

19 files changed

+721
-188
lines changed

CHANGELOG.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,6 @@ for details.
442442
- Removal of config.symlink_non_digested_assets_regex as it's no longer needed with rails/webpacker.
443443
If any business needs this, we can move the code to a separate gem.
444444
- Added configuration option `same_bundle_for_client_and_server` with default `false` because
445-
446445
1. Production applications would typically have a server bundle that differs from the client bundle
447446
2. This change only affects trying to use HMR with react_on_rails with rails/webpacker.
448447

@@ -1160,13 +1159,11 @@ No changes.
11601159
- Added automatic compilation of assets at precompile is now done by ReactOnRails. Thus, you don't need to provide your own `assets.rake` file that does the precompilation.
11611160
[#398](https://github.com/shakacode/react_on_rails/pull/398) by [robwise](https://github.com/robwise), [jbhatab](https://github.com/jbhatab), and [justin808](https://github.com/justin808).
11621161
- **Migration to v6**
1163-
11641162
- Do not run the generator again if you've already run it.
11651163

11661164
- See [shakacode/react-webpack-rails-tutorial/pull/287](https://github.com/shakacode/react-webpack-rails-tutorial/pull/287) for an example of upgrading from v5.
11671165

11681166
- To configure the asset compilation you can either
1169-
11701167
1. Specify a `config/react_on_rails` setting for `build_production_command` to be nil to turn this feature off.
11711168
2. Specify the script command you want to run to build your production assets, and remove your `assets.rake` file.
11721169

CODING_AGENTS.md

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
# 🤖 Coding Agents & AI Contributors Guide
2+
3+
This guide provides specific guidelines for AI coding agents (like Claude Code) contributing to React on Rails. It supplements the main [CONTRIBUTING.md](./CONTRIBUTING.md) with AI-specific workflows and patterns.
4+
5+
## Quick Reference Commands
6+
7+
### Essential Commands
8+
9+
```bash
10+
# Install dependencies
11+
bundle && yarn
12+
13+
# Run tests
14+
bundle exec rspec # All tests (from project root)
15+
cd spec/dummy && bundle exec rspec # Dummy app tests only
16+
17+
# Linting & Formatting
18+
bundle exec rubocop # Ruby linting
19+
bundle exec rubocop [file_path] # Lint specific file
20+
# Note: yarn format requires local setup, format manually
21+
22+
# Development
23+
cd spec/dummy && foreman start # Start dummy app with webpack
24+
```
25+
26+
### CI Compliance Checklist
27+
28+
- [ ] `bundle exec rubocop` passes with no offenses
29+
- [ ] All RSpec tests pass
30+
- [ ] No trailing whitespace
31+
- [ ] Line length ≤120 characters
32+
- [ ] Security violations properly scoped with disable comments
33+
34+
## Development Patterns for AI Contributors
35+
36+
### 1. Task Management
37+
38+
Always use TodoWrite tool for multi-step tasks to:
39+
40+
- Track progress transparently
41+
- Show the user what's being worked on
42+
- Ensure no steps are forgotten
43+
- Mark tasks complete as you finish them
44+
45+
```markdown
46+
Example workflow:
47+
48+
1. Analyze the problem
49+
2. Create test cases
50+
3. Implement the fix
51+
4. Run tests
52+
5. Fix linting issues
53+
6. Update documentation
54+
```
55+
56+
### 2. Test-Driven Development
57+
58+
When fixing bugs or adding features:
59+
60+
1. **Create failing tests first** that reproduce the issue
61+
2. **Implement the minimal fix** to make tests pass
62+
3. **Add comprehensive test coverage** for edge cases
63+
4. **Verify all existing tests still pass**
64+
65+
### 3. File Processing Guidelines
66+
67+
When working with file generation or processing:
68+
69+
- **Filter by extension**: Only process relevant files (e.g., `.js/.jsx/.ts/.tsx` for React components)
70+
- **Validate assumptions**: Don't assume all files in a directory are components
71+
- **Handle edge cases**: CSS modules, config files, etc. should be excluded appropriately
72+
73+
Example from CSS module fix:
74+
75+
```ruby
76+
COMPONENT_EXTENSIONS = /\.(jsx?|tsx?)$/
77+
78+
def filter_component_files(paths)
79+
paths.grep(COMPONENT_EXTENSIONS)
80+
end
81+
```
82+
83+
## RuboCop Compliance Patterns
84+
85+
### Common Fixes
86+
87+
1. **Trailing Whitespace**
88+
89+
```ruby
90+
# Bad
91+
let(:value) { "test" }
92+
93+
# Good
94+
let(:value) { "test" }
95+
```
96+
97+
2. **Line Length (120 chars max)**
98+
99+
```ruby
100+
# Bad
101+
expect { eval(pack_content.gsub(/import.*from.*['"];/, "").gsub(/ReactOnRails\.register.*/, "")) }.not_to raise_error
102+
103+
# Good
104+
sanitized_content = pack_content.gsub(/import.*from.*['"];/, "")
105+
.gsub(/ReactOnRails\.register.*/, "")
106+
expect { eval(sanitized_content) }.not_to raise_error
107+
```
108+
109+
3. **Named Subjects (RSpec)**
110+
111+
```ruby
112+
# Bad
113+
describe "#method_name" do
114+
subject { instance.method_name(arg) }
115+
116+
it "does something" do
117+
expect(subject).to eq "result"
118+
end
119+
end
120+
121+
# Good
122+
describe "#method_name" do
123+
subject(:method_result) { instance.method_name(arg) }
124+
125+
it "does something" do
126+
expect(method_result).to eq "result"
127+
end
128+
end
129+
```
130+
131+
4. **Security/Eval Violations**
132+
133+
```ruby
134+
# Bad
135+
expect { eval(dangerous_code) }.not_to raise_error
136+
137+
# Good
138+
# rubocop:disable Security/Eval
139+
sanitized_content = dangerous_code.gsub(/harmful_pattern/, "")
140+
expect { eval(sanitized_content) }.not_to raise_error
141+
# rubocop:enable Security/Eval
142+
```
143+
144+
### RuboCop Workflow
145+
146+
1. Run `bundle exec rubocop [file]` to see violations
147+
2. Fix violations manually or with auto-correct where safe
148+
3. Re-run to verify fixes
149+
4. Use disable comments sparingly and with good reason
150+
151+
## Testing Best Practices
152+
153+
### Test Structure
154+
155+
```ruby
156+
describe "FeatureName" do
157+
context "when condition A" do
158+
let(:setup) { create_test_condition }
159+
160+
before do
161+
# Setup code
162+
end
163+
164+
it "does expected behavior" do
165+
# Arrange, Act, Assert
166+
end
167+
end
168+
end
169+
```
170+
171+
### Test Fixtures
172+
173+
- Create realistic test data that represents edge cases
174+
- Use descriptive names for fixtures and variables
175+
- Clean up after tests (handled by RSpec automatically in most cases)
176+
177+
### CSS Module Testing Example
178+
179+
```ruby
180+
# Create test fixtures
181+
Write.create("ComponentWithCSSModule.module.css", css_content)
182+
Write.create("ComponentWithCSSModule.jsx", jsx_content)
183+
184+
# Test the behavior
185+
it "ignores CSS module files during pack generation" do
186+
generated_packs = PacksGenerator.instance.generate_packs_if_stale
187+
expect(generated_packs).not_to include("ComponentWithCSSModule.module.js")
188+
end
189+
```
190+
191+
## Git & PR Workflow
192+
193+
### Branch Management
194+
195+
```bash
196+
git checkout -b fix/descriptive-name
197+
# Make changes
198+
git add .
199+
git commit -m "Descriptive commit message
200+
201+
- Bullet points for major changes
202+
- Reference issue numbers
203+
- Include 🤖 Generated with Claude Code signature"
204+
205+
git push -u origin fix/descriptive-name
206+
```
207+
208+
### Commit Message Format
209+
210+
```
211+
Brief description of the change
212+
213+
- Detailed bullet points of what changed
214+
- Why the change was needed
215+
- Any breaking changes or considerations
216+
217+
Fixes #issue_number
218+
219+
🤖 Generated with [Claude Code](https://claude.ai/code)
220+
221+
Co-Authored-By: Claude <noreply@anthropic.com>
222+
```
223+
224+
### PR Creation
225+
226+
Use `gh pr create` with:
227+
228+
- Clear title referencing the issue
229+
- Comprehensive description with summary and test plan
230+
- Link to the issue being fixed
231+
- Include the Claude Code signature
232+
233+
## Common Pitfalls & Solutions
234+
235+
### 1. File Path Issues
236+
237+
- Always use absolute paths in tools
238+
- Check current working directory with `pwd`
239+
- Use proper path joining methods
240+
241+
### 2. Test Environment
242+
243+
- Run tests from correct directory (often project root)
244+
- Understand the difference between gem tests vs dummy app tests
245+
- Clean up test artifacts appropriately
246+
247+
### 3. Dependency Management
248+
249+
- Don't assume packages are installed globally
250+
- Use `bundle exec` for Ruby commands
251+
- Verify setup with `bundle && yarn` when needed
252+
253+
### 4. RuboCop Configuration
254+
255+
- Different rules may apply to different directories
256+
- Use `bundle exec rubocop` (not global rubocop)
257+
- Check `.rubocop.yml` files for project-specific rules
258+
259+
## Debugging Workflow
260+
261+
1. **Understand the Problem**
262+
- Read the issue carefully
263+
- Reproduce the bug if possible
264+
- Identify root cause
265+
266+
2. **Create Minimal Test Case**
267+
- Write failing test that demonstrates issue
268+
- Keep it focused and minimal
269+
270+
3. **Implement Fix**
271+
- Make smallest change possible
272+
- Ensure fix doesn't break existing functionality
273+
- Follow existing code patterns
274+
275+
4. **Verify Solution**
276+
- All new tests pass
277+
- All existing tests still pass
278+
- RuboCop compliance maintained
279+
- Manual testing if applicable
280+
281+
## IDE Configuration for AI Context
282+
283+
When analyzing codebases, ignore these directories to avoid confusion:
284+
285+
- `/coverage`, `/tmp`, `/gen-examples`
286+
- `/node_package/lib`, `/node_modules`
287+
- `/spec/dummy/app/assets/webpack`
288+
- `/spec/dummy/log`, `/spec/dummy/node_modules`, `/spec/dummy/tmp`
289+
- `/spec/react_on_rails/dummy-for-generators`
290+
291+
## Communication with Human Maintainers
292+
293+
- Be transparent about AI-generated changes
294+
- Explain reasoning behind implementation choices
295+
- Ask for clarification when requirements are ambiguous
296+
- Provide comprehensive commit messages and PR descriptions
297+
- Include test plans and verification steps
298+
299+
## Resources
300+
301+
- [Main Contributing Guide](./CONTRIBUTING.md)
302+
- [Pull Request Guidelines](./docs/contributor-info/pull-requests.md)
303+
- [Generator Testing](./docs/contributor-info/generator-testing.md)
304+
- [RuboCop Documentation](https://docs.rubocop.org/)
305+
- [RSpec Best Practices](https://rspec.info/)
306+
307+
---
308+
309+
This guide evolves based on AI contributor experiences. Suggest improvements via issues or PRs!

docs/additional-details/migrating-from-react-rails.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,16 @@
33
In this guide, it is assumed that you have upgraded the `react-rails` project to use `shakapacker` version 7. To this end, check out [Shakapacker v7 upgrade guide](https://github.com/shakacode/shakapacker/tree/master/docs/v7_upgrade.md). Upgrading `react-rails` to version 3 can make the migration smoother but it is not required.
44

55
1. Update Deps
6-
76
1. Replace `react-rails` in `Gemfile` with the latest version of `react_on_rails` and run `bundle install`.
87
2. Remove `react_ujs` from `package.json` and run `yarn install`.
98
3. Commit changes!
109

1110
2. Run `rails g react_on_rails:install` but do not commit the change. `react_on_rails` installs node dependencies and also creates sample React component, Rails view/controller, and updates `config/routes.rb`.
1211

1312
3. Adapt the project: Check the changes and carefully accept, reject, or modify them as per your project's needs. Besides changes in `config/shakapacker` or `babel.config` which are project-specific, here are the most noticeable changes to address:
14-
1513
1. Check Webpack config files at `config/webpack/*`. If coming from `react-rails` v3, the changes are minor since you have already made separate configurations for client and server bundles. The most important change here is to notice the different names for the server bundle entry file. You may choose to stick with `server_rendering.js` or use `server-bundle.js` which is the default name in `react_on_rails`. The decision made here affects the other steps.
1614

1715
2. In `app/javascript` directory you may notice some changes.
18-
1916
1. `react_on_rails` by default uses `bundles` directory for the React components. You may choose to rename `components` into `bundles` to follow the convention.
2017

2118
2. `react_on_rails` uses `client-bundle.js` and `server-bundle.js` instead of `application.js` and `server_rendering.js`. There is nothing special about these names. It can be set to use any other name (as mentioned above). If you too choose to follow the new names, consider updating the relevant `javascript_pack_tag` in your Rails views.

docs/getting-started.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,8 @@ You may need to check [the instructions for installing into an existing Rails ap
3838
```
3939

4040
3. Start the app:
41-
4241
- Run `./bin/dev` for HMR
43-
- Run `./bin/dev-static` for statically created bundles (no HMR)
42+
- Run `./bin/dev static` for statically created bundles (no HMR)
4443

4544
4. Visit http://localhost:3000/hello_world.
4645

docs/guides/streaming-server-rendering.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ You can test your application by running `rails server` and navigating to the ap
119119
When a user visits the page, they'll experience the following sequence:
120120

121121
1. The initial HTML shell is sent immediately, including:
122-
123122
- The page layout
124123
- Any static content (like the `<h1>` and footer)
125124
- Placeholder content for the React component (typically a loading state)
@@ -165,13 +164,11 @@ Streaming SSR is particularly valuable in specific scenarios. Here's when to con
165164
### Ideal Use Cases
166165

167166
1. **Data-Heavy Pages**
168-
169167
- Pages that fetch data from multiple sources
170168
- Dashboard-style layouts where different sections can load independently
171169
- Content that requires heavy processing or computation
172170

173171
2. **Progressive Enhancement**
174-
175172
- When you want users to see and interact with parts of the page while others load
176173
- For improving perceived performance on slower connections
177174
- When different parts of your page have different priority levels

docs/guides/tutorial.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ Then run the server with one of the following options:
134134
```bash
135135
./bin/dev # For HMR
136136
# or
137-
./bin/dev-static # Without HMR, statically creating the bundles
137+
./bin/dev static # Without HMR, statically creating the bundles
138138
```
139139

140140
Visit [http://localhost:3000/hello_world](http://localhost:3000/hello_world) and see your **React On Rails** app running!

0 commit comments

Comments
 (0)