Skip to content

Improve CSS Modules backward compatibility documentation in v9 upgrade guide #809

@justin808

Description

@justin808

Improve CSS Modules backward compatibility documentation in v9 upgrade guide

Problem

When upgrading from Shakapacker 8.x to 9.x, the CSS Modules breaking change causes existing code to fail at runtime, but the upgrade guide doesn't provide a complete working example of how to restore backward compatibility.

What happens

Shakapacker 9.0+ changed CSS Modules from default exports to named exports (namedExport: true). Code using the old syntax:

import styles from './component.module.css';

Will fail at runtime with errors like components not rendering or undefined class names.

Current documentation gap

The v9 upgrade guide mentions:

"Override the css-loader configuration as shown in CSS Modules Export Mode documentation"

However, it doesn't provide a complete working example of how to configure webpack to restore the v8 behavior. Users need to figure out:

  1. Where to add the override (in which webpack config file)
  2. How to iterate through rules and modify loader options
  3. What exact options to set for full backward compatibility

Suggested improvement

Add a complete working example to the upgrade guide showing how to override CSS Modules configuration:

Add to "CSS Modules Configuration Changed to Named Exports" section:

#### Restoring v8 Behavior (Backward Compatibility)

If you have a large codebase and want to keep using default imports temporarily, override the CSS Modules configuration in your webpack config:

```javascript
// config/webpack/commonWebpackConfig.js (or similar)
const { generateWebpackConfig, merge } = require('shakapacker');

const baseConfig = generateWebpackConfig();

const customConfig = () => {
  const config = merge({}, baseConfig, /* your other options */);

  // Override CSS Modules to use default exports (v8 behavior)
  config.module.rules.forEach((rule) => {
    if (rule.test && rule.test.test('example.module.css')) {
      if (Array.isArray(rule.use)) {
        rule.use.forEach((loader) => {
          if (
            loader.loader &&
            loader.loader.includes('css-loader') &&
            loader.options &&
            loader.options.modules
          ) {
            loader.options.modules.namedExport = false;
            loader.options.modules.exportLocalsConvention = 'camelCase';
          }
        });
      }
    }
  });

  return config;
};

module.exports = customConfig;
```

**Note:** This is a temporary solution. The recommended approach is to migrate your imports to use named exports as shown in the main documentation.

Real-world impact

This issue affected our React on Rails upgrade to Shakapacker 9.1.0. Without a clear example:

  1. ✅ Tests failed with React components not rendering
  2. ✅ CI showed no webpack build errors (bundles compiled successfully)
  3. ✅ Runtime errors were silent - components just didn't appear
  4. ✅ Required debugging webpack config to identify the root cause

A complete example would have saved hours of debugging and made the upgrade path clearer.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions