Skip to content

Commit 28014b2

Browse files
justin808claude
andcommitted
Move CSS modules fix into function to ensure it applies on each call
The previous fix modified baseClientRspackConfig at module load time, but generateWebpackConfig() returns a fresh config each time. Moving the CSS modules configuration inside the commonRspackConfig() function ensures the fix is applied every time the config is requested. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 1685fb4 commit 28014b2

File tree

1 file changed

+48
-45
lines changed

1 file changed

+48
-45
lines changed
Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Common configuration applying to client and server configuration
22
const { generateWebpackConfig, merge } = require('shakapacker');
33

4-
const baseClientRspackConfig = generateWebpackConfig();
54
const commonOptions = {
65
resolve: {
76
extensions: ['.css', '.ts', '.tsx', '.bs.js'],
@@ -20,57 +19,61 @@ const ignoreWarningsConfig = {
2019
ignoreWarnings: [/Module not found: Error: Can't resolve 'react-dom\/client'/],
2120
};
2221

23-
// Fix all CSS-related loaders to use default exports instead of named exports
24-
// Shakapacker 9 defaults to namedExport: true, but existing code expects default exports
25-
baseClientRspackConfig.module.rules.forEach((rule) => {
26-
if (rule.use && Array.isArray(rule.use)) {
27-
const cssLoader = rule.use.find((loader) => {
28-
const loaderName = typeof loader === 'string' ? loader : loader?.loader;
29-
return loaderName?.includes('css-loader');
30-
});
31-
32-
if (cssLoader?.options?.modules) {
33-
cssLoader.options.modules.namedExport = false;
34-
cssLoader.options.modules.exportLocalsConvention = 'camelCase';
35-
}
36-
}
37-
});
22+
// Copy the object using merge b/c the baseClientRspackConfig and commonOptions are mutable globals
23+
const commonRspackConfig = () => {
24+
const baseClientRspackConfig = generateWebpackConfig();
3825

39-
const scssConfigIndex = baseClientRspackConfig.module.rules.findIndex((config) =>
40-
'.scss'.match(config.test) && config.use,
41-
);
26+
// Fix all CSS-related loaders to use default exports instead of named exports
27+
// Shakapacker 9 defaults to namedExport: true, but existing code expects default exports
28+
baseClientRspackConfig.module.rules.forEach((rule) => {
29+
if (rule.use && Array.isArray(rule.use)) {
30+
const cssLoader = rule.use.find((loader) => {
31+
const loaderName = typeof loader === 'string' ? loader : loader?.loader;
32+
return loaderName?.includes('css-loader');
33+
});
4234

43-
if (scssConfigIndex === -1) {
44-
console.warn('No SCSS rule with use array found in rspack config');
45-
} else {
46-
// Configure sass-loader to use the modern API
47-
const scssRule = baseClientRspackConfig.module.rules[scssConfigIndex];
48-
const sassLoaderIndex = scssRule.use.findIndex((loader) => {
49-
if (typeof loader === 'string') {
50-
return loader.includes('sass-loader');
35+
if (cssLoader?.options?.modules) {
36+
cssLoader.options.modules.namedExport = false;
37+
cssLoader.options.modules.exportLocalsConvention = 'camelCase';
38+
}
5139
}
52-
return loader.loader && loader.loader.includes('sass-loader');
5340
});
5441

55-
if (sassLoaderIndex !== -1) {
56-
const sassLoader = scssRule.use[sassLoaderIndex];
57-
if (typeof sassLoader === 'string') {
58-
scssRule.use[sassLoaderIndex] = {
59-
loader: sassLoader,
60-
options: {
61-
api: 'modern'
62-
}
63-
};
64-
} else {
65-
sassLoader.options = sassLoader.options || {};
66-
sassLoader.options.api = 'modern';
42+
const scssConfigIndex = baseClientRspackConfig.module.rules.findIndex((config) =>
43+
'.scss'.match(config.test) && config.use,
44+
);
45+
46+
if (scssConfigIndex === -1) {
47+
console.warn('No SCSS rule with use array found in rspack config');
48+
} else {
49+
// Configure sass-loader to use the modern API
50+
const scssRule = baseClientRspackConfig.module.rules[scssConfigIndex];
51+
const sassLoaderIndex = scssRule.use.findIndex((loader) => {
52+
if (typeof loader === 'string') {
53+
return loader.includes('sass-loader');
54+
}
55+
return loader.loader && loader.loader.includes('sass-loader');
56+
});
57+
58+
if (sassLoaderIndex !== -1) {
59+
const sassLoader = scssRule.use[sassLoaderIndex];
60+
if (typeof sassLoader === 'string') {
61+
scssRule.use[sassLoaderIndex] = {
62+
loader: sassLoader,
63+
options: {
64+
api: 'modern'
65+
}
66+
};
67+
} else {
68+
sassLoader.options = sassLoader.options || {};
69+
sassLoader.options.api = 'modern';
70+
}
6771
}
68-
}
6972

70-
baseClientRspackConfig.module.rules[scssConfigIndex].use.push(sassLoaderConfig);
71-
}
73+
baseClientRspackConfig.module.rules[scssConfigIndex].use.push(sassLoaderConfig);
74+
}
7275

73-
// Copy the object using merge b/c the baseClientRspackConfig and commonOptions are mutable globals
74-
const commonRspackConfig = () => merge({}, baseClientRspackConfig, commonOptions, ignoreWarningsConfig);
76+
return merge({}, baseClientRspackConfig, commonOptions, ignoreWarningsConfig);
77+
};
7578

7679
module.exports = commonRspackConfig;

0 commit comments

Comments
 (0)