Skip to content

Document CSS Modules export mode configuration#588

Merged
justin808 merged 1 commit into
mainfrom
justin808-css-modules-export-mode
Sep 18, 2025
Merged

Document CSS Modules export mode configuration#588
justin808 merged 1 commit into
mainfrom
justin808-css-modules-export-mode

Conversation

@justin808

@justin808 justin808 commented Sep 16, 2025

Copy link
Copy Markdown
Member

Relates to #587

Summary by CodeRabbit

  • Documentation
    • Added comprehensive guide on CSS Modules export modes in Shakapacker, recommending default-export usage.
    • Details multiple configuration approaches to enforce default exports (including Sass), with verification steps and debug workflow.
    • Provides migration guidance (updating imports/class references) and codemod suggestions.
    • Includes troubleshooting, TypeScript compatibility notes, and performance considerations.
    • Outlines future configuration direction and summarizes best-practice patterns for consistent styling imports.

@justin808 justin808 requested a review from tomdracz September 16, 2025 06:29
@coderabbitai

coderabbitai Bot commented Sep 16, 2025

Copy link
Copy Markdown

Walkthrough

Adds a new documentation page explaining CSS Modules export modes in Shakapacker, default vs named exports, and multiple configuration approaches to enforce default exports. Includes verification steps, migration guidance, future config notes, troubleshooting, TypeScript notes, and performance considerations. No code changes; documentation only.

Changes

Cohort / File(s) Summary
Docs
docs/css-modules-export-mode.md
New doc detailing CSS Modules export modes, three configuration options to force default exports, verification/migration steps, future YAML config placeholder, troubleshooting, TypeScript notes, and performance considerations.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Possibly related issues

Poem

A rabbit taps keys with a whisker’s delight,
“From named to default, our styles now alight!”
Docs hop ahead, clear paths to explore,
CSS burrows labeled, confusion no more.
With gentle thumps and tidy byte trails,
We ship the guide—no code, just tales.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Document CSS Modules export mode configuration" is concise and directly describes the primary change in the PR (the addition of documentation about CSS Modules export mode, as reflected by docs/css-modules-export-mode.md), so it accurately summarizes the main intent and is clear for reviewers scanning history.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch justin808-css-modules-export-mode

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
docs/css-modules-export-mode.md (4)

36-55: Add error handling and defensive checks for production robustness.

The configuration override function should handle edge cases where the expected webpack rule structure might not exist or differ from expectations.

 const overrideCssModulesConfig = (config) => {
+  if (!config?.module?.rules) {
+    console.warn('Webpack config structure unexpected - skipping CSS Modules override');
+    return config;
+  }
+
   // Find the CSS rule in the module rules
   const cssRule = config.module.rules.find(rule =>
     rule.test && rule.test.toString().includes('css')
   );

   if (cssRule && cssRule.use) {
     const cssLoaderUse = cssRule.use.find(use =>
-      use.loader && use.loader.includes('css-loader')
+      use?.loader && use.loader.includes('css-loader')
     );

-    if (cssLoaderUse && cssLoaderUse.options && cssLoaderUse.options.modules) {
+    if (cssLoaderUse?.options?.modules) {
       // Set namedExport to false for default export behavior
       cssLoaderUse.options.modules.namedExport = false;
       cssLoaderUse.options.modules.exportLocalsConvention = 'asIs';
+    } else if (cssLoaderUse) {
+      console.warn('CSS loader found but modules configuration missing - ensure CSS Modules are enabled');
     }
+  } else {
+    console.warn('CSS rule not found in webpack configuration - CSS Modules override skipped');
   }

   return config;
 };

175-175: Correct the webpack stats command flag.

The --profile flag should be --analyze for webpack stats generation in most webpack configurations.

-NODE_ENV=development bin/shakapacker --profile --json > /tmp/webpack-stats.json
+NODE_ENV=development bin/shakapacker --json > /tmp/webpack-stats.json

Alternatively, if profiling data is desired:

-NODE_ENV=development bin/shakapacker --profile --json > /tmp/webpack-stats.json
+NODE_ENV=development bin/shakapacker --json --profile > /tmp/webpack-stats.json

225-228: Provide concrete codemod implementation guidance.

The codemod example is helpful but could be more actionable by referencing existing tools or providing a basic implementation outline.

Consider expanding this section with more specific guidance:

 ### 3. Consider Using a Codemod

 For large codebases, consider writing a codemod to automate the migration:

 ```bash
-# Example using jscodeshift (pseudocode)
-npx jscodeshift -t css-modules-migration.js src/
+# Install jscodeshift
+npm install -g jscodeshift

+# Run the transformation
+npx jscodeshift -t css-modules-migration.js src/

+A basic codemod template might transform:
+js +// Transform: import { class1, class2 } from './styles.module.css' +// To: import styles from './styles.module.css' +// And update className={class1} to className={styles.class1} +
+
+Consider using existing codemods like css-modules-codemod if available.


---

`276-276`: **Clarify the webpack profiling command.**

The command should be consistent with the earlier example and include proper flags.



```diff
-1. Check webpack stats: `bin/shakapacker --profile`
+1. Check webpack stats: `bin/shakapacker --json > webpack-stats.json`
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8162562 and 0f43cfb.

📒 Files selected for processing (1)
  • docs/css-modules-export-mode.md (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.7.2.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.8.0.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.2.x)
  • GitHub Check: Testing (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.8.0.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.2.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.8.0.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.7.1.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.1.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.0.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.6.1.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.1.x)
  • GitHub Check: Testing (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.0.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.0.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.6.1.x)
  • GitHub Check: Testing (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.0.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.1.x)
  • GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.6.1.x)
  • GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.6.0.x)
  • GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.0.x)
  • GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.7.0.x)
🔇 Additional comments (1)
docs/css-modules-export-mode.md (1)

1-289: Excellent comprehensive documentation for CSS Modules export configuration!

This documentation provides clear, actionable guidance for configuring CSS Modules export modes in Shakapacker. The structure is logical, examples are practical, and the migration guidance is thorough. The content effectively bridges the gap between current behavior and recommended practices.

}

// Plain CSS rule for non-modules
const plainCssRule = getStyleRule(/(?<!\.module)\.css$/i, [], {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

Verify the negative lookahead regex pattern for cross-platform compatibility.

The negative lookbehind (?<!\.module) may not be supported in all JavaScript engines or webpack versions. Consider using a more compatible approach.

If compatibility issues arise, consider this alternative approach:

-// Plain CSS rule for non-modules
-const plainCssRule = getStyleRule(/(?<!\.module)\.css$/i, [], {
+// Plain CSS rule for non-modules (more compatible pattern)
+const plainCssRule = getStyleRule(/\.css$/i, [], {
   sourceMap: true,
   importLoaders: 2,
-  modules: false
+  modules: {
+    auto: (resourcePath) => !resourcePath.includes('.module.css')
+  }
 });

🏁 Script executed:

#!/bin/bash
# Description: Check if the negative lookbehind regex pattern is widely supported
# in the versions of Node.js and webpack typically used with Shakapacker

echo "Checking Node.js version support for negative lookbehind patterns..."
node -e "
try {
  const regex = /(?<!\.module)\.css$/i;
  console.log('✓ Negative lookbehind supported in Node.js', process.version);
  console.log('Test: \"style.css\" matches:', regex.test('style.css'));
  console.log('Test: \"style.module.css\" matches:', regex.test('style.module.css'));
} catch (e) {
  console.error('✗ Negative lookbehind NOT supported:', e.message);
}
"

echo -e "\nChecking webpack documentation for css-loader regex patterns..."

Length of output: 556


Replace unsupported negative lookbehind with a compatible pattern and use css-loader modules.auto

Sandbox Node v24.3.0 throws a SyntaxError for /(?<!.module).css$/i — negative lookbehind is not safe; update the docs/example at docs/css-modules-export-mode.md:97.

-// Plain CSS rule for non-modules
-const plainCssRule = getStyleRule(/(?<!\.module)\.css$/i, [], {
+// Plain CSS rule for non-modules (more compatible pattern)
+const plainCssRule = getStyleRule(/\.css$/i, [], {
   sourceMap: true,
   importLoaders: 2,
-  modules: false
+  modules: {
+    auto: (resourcePath) => !resourcePath.includes('.module.css')
+  }
 });

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In docs/css-modules-export-mode.md around line 97, replace the unsupported
negative lookbehind regex /(?<!\.module)\.css$/i with a compatible approach: use
a plain /\.css$/i matcher (or keep /\.css$/i and explicitly exclude
/\.module\.css$/i) and configure css-loader to use modules.auto (e.g. modules: {
auto: resourcePath => /\.module\.css$/i.test(resourcePath) }) so module CSS is
detected without relying on lookbehind; update the example and any comments to
show the new regex and the modules.auto usage.


## Future Shakapacker Configuration

In future versions of Shakapacker, this configuration may be exposed via `config/shakapacker.yml`:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL that this is actually defaulted based on esModule option https://webpack.js.org/loaders/css-loader/#namedexport

Agree that using false makes sense down the line though that is a breaking change warranting major release 👍

@justin808 justin808 merged commit b25aa1b into main Sep 18, 2025
49 of 55 checks passed
@justin808 justin808 deleted the justin808-css-modules-export-mode branch September 18, 2025 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants