Skip to content

Commit 0ab9eac

Browse files
justin808claude
andcommitted
Refactor bundler detection and improve documentation
Code quality improvements: 1. **Extract bundler detection to shared utility** - Created config/webpack/bundlerUtils.js with getBundler(), isRspack(), getCssExtractPlugin() - Eliminates duplication across clientWebpackConfig.js and serverWebpackConfig.js - Provides single source of truth for bundler selection 2. **Improve error messages** - serverWebpackConfig.js now provides actionable error message with specific file paths and configuration to check when server-bundle entry is missing 3. **Enhance documentation** - Added "Verifying Patches" section to patches/README.md with concrete steps - Improved Sass modern API comments explaining why it's needed - Added common troubleshooting scenarios for patch application All changes tested with both Webpack and Rspack bundlers. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 5f92988 commit 0ab9eac

File tree

5 files changed

+73
-13
lines changed

5 files changed

+73
-13
lines changed

config/webpack/bundlerUtils.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Bundler utilities for automatic Webpack/Rspack detection.
3+
*
4+
* Shakapacker 9.1+ supports both Webpack and Rspack as bundlers.
5+
* The bundler is selected via config/shakapacker.yml:
6+
* assets_bundler: webpack # or 'rspack'
7+
*/
8+
9+
const { config } = require('shakapacker');
10+
11+
/**
12+
* Gets the appropriate bundler module based on shakapacker.yml configuration.
13+
*
14+
* @returns {Object} Either webpack or @rspack/core module
15+
*/
16+
const getBundler = () => {
17+
return config.assets_bundler === 'rspack'
18+
? require('@rspack/core')
19+
: require('webpack');
20+
};
21+
22+
/**
23+
* Checks if the current bundler is Rspack.
24+
*
25+
* @returns {boolean} True if using Rspack, false if using Webpack
26+
*/
27+
const isRspack = () => config.assets_bundler === 'rspack';
28+
29+
/**
30+
* Gets the appropriate CSS extraction plugin for the current bundler.
31+
*
32+
* @returns {Object} Either mini-css-extract-plugin (Webpack) or CssExtractRspackPlugin (Rspack)
33+
*/
34+
const getCssExtractPlugin = () => {
35+
return isRspack()
36+
? getBundler().CssExtractRspackPlugin
37+
: require('mini-css-extract-plugin');
38+
};
39+
40+
module.exports = {
41+
getBundler,
42+
isRspack,
43+
getCssExtractPlugin,
44+
};

config/webpack/clientWebpackConfig.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
// The source code including full typescript support is available at:
22
// https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/blob/master/config/webpack/clientWebpackConfig.js
33

4-
const { config } = require('shakapacker');
54
const commonWebpackConfig = require('./commonWebpackConfig');
6-
7-
// Auto-detect bundler from shakapacker config and load the appropriate library
8-
const bundler = config.assets_bundler === 'rspack'
9-
? require('@rspack/core')
10-
: require('webpack');
5+
const { getBundler } = require('./bundlerUtils');
116

127
const configureClient = () => {
8+
const bundler = getBundler();
139
const clientConfig = commonWebpackConfig();
1410

1511
clientConfig.plugins.push(

config/webpack/commonWebpackConfig.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,15 @@ const commonWebpackConfig = () => {
8383
scssRule.use[sassLoaderIndex] = {
8484
loader: sassLoader,
8585
options: {
86+
// Use modern API for better performance and to support sass-resources-loader
87+
// The modern API uses the Sass JavaScript API instead of the legacy Node API
8688
api: 'modern'
8789
}
8890
};
8991
} else {
9092
sassLoader.options = sassLoader.options || {};
93+
// Use modern API for better performance and to support sass-resources-loader
94+
// The modern API uses the Sass JavaScript API instead of the legacy Node API
9195
sassLoader.options.api = 'modern';
9296
}
9397
}

config/webpack/serverWebpackConfig.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@
44
const path = require('path');
55
const { config } = require('shakapacker');
66
const commonWebpackConfig = require('./commonWebpackConfig');
7-
8-
// Auto-detect bundler from shakapacker config and load the appropriate library
9-
// This allows the same config to work with both Webpack and Rspack
10-
const bundler = config.assets_bundler === 'rspack'
11-
? require('@rspack/core')
12-
: require('webpack');
7+
const { getBundler } = require('./bundlerUtils');
138

149
/**
1510
* Generates the server-side rendering (SSR) bundle configuration.
@@ -28,6 +23,8 @@ const bundler = config.assets_bundler === 'rspack'
2823
* @returns {Object} Webpack/Rspack configuration object for server bundle
2924
*/
3025
const configureServer = () => {
26+
const bundler = getBundler();
27+
3128
// We need to use "merge" because the clientConfigObject, EVEN after running
3229
// toWebpackConfig() is a mutable GLOBAL. Thus any changes, like modifying the
3330
// entry value will result in changing the client config!
@@ -41,7 +38,9 @@ const configureServer = () => {
4138

4239
if (!serverEntry['server-bundle']) {
4340
throw new Error(
44-
"Create a pack with the file name 'server-bundle.js' containing all the server rendering files",
41+
"Server bundle entry 'server-bundle' not found. " +
42+
"Check that client/app/packs/server-bundle.js exists and is configured in shakapacker.yml. " +
43+
"Verify nested_entries is set correctly and the file is in the source_entry_path.",
4544
);
4645
}
4746

patches/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,23 @@ import * as Json from "@glennsl/rescript-json-combinators/src/Json.bs.js";
3131

3232
**TODO**: Check if patch is still needed when upgrading `@glennsl/rescript-json-combinators`
3333

34+
## Verifying Patches
35+
36+
After running `yarn install`, verify the patch was applied correctly:
37+
38+
```bash
39+
# Run ReScript build - should succeed without errors
40+
yarn res:build
41+
42+
# Expected output: Compiled successfully
43+
# If you see errors about missing .bs.js files, the patch wasn't applied
44+
```
45+
46+
**Common issues**:
47+
- **Patch not applied**: Check that `postinstall` script ran (look for patch-package output during install)
48+
- **Build fails**: Run `yarn install --force` to reapply patches
49+
- **Wrong ReScript version**: Ensure ReScript version matches the patched package expectations
50+
3451
## How Patches Work
3552

3653
1. **Creation**: When you modify a package in `node_modules/`, run:

0 commit comments

Comments
 (0)