question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Generated CSS modules class names are deleted from the HTML on production builds with optimize

See original GitHub issue

Bug Report Quick Checklist

  • I am on the latest version of Snowpack & all plugins.
  • yarn 1.22.5
  • Ubuntu 20
  • I run Snowpack on Node.js v14+

Describe the bug

When using either @snowpack/plugin-webpack or the optimize config, all class names from CSS modules get removed from the markup.

Example markup from the project where this happens: image

To Reproduce

  1. npm init snowpack-app --template @snowpack/app-template-react
  2. Setup the webpack plugin or optimize
  3. snowpack build
  4. Inspect the HTML output or serve the output folder
  5. Check that the class names are not there.

Expected behavior

For the class names to appear. https://github.com/finiam/phoenix_starter I have a starter repo (elixir + react) that is stuck on 3.3.2 and it works there. But from 3.3.3 onwards it doesn’t.

On that project, with the 3.3.2 version, class names are generated correctly: image

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:5
  • Comments:11 (1 by maintainers)

github_iconTop GitHub Comments

4reactions
ChristiaanScheermeijercommented, May 6, 2021

We are running into the same problem with the optimization strategy (expected) and @snowpack/plugin-webpack plugin using the latest snowpack version (3.3.7). I’ve tried multiple versions from 3.3.2 without success.

Looking at the build output, it seems that the JSON keys are being renamed. While the JSX output still uses the original properties.

The CSS does contain the correct classNames, but it also includes the @use keywords in the output.

Source:

import styles from './Auth.module.scss';

const Auth = () => {
  return (
    <Layout>
      <div className={styles.Auth} />
    </Layout>
  );
};

Build output:

@use "../../styles/variables";
@use "../../styles/theme";
._22ImGiStC_zj9-aVAVSHUL{display:flex;justify-content:center;align-items:center;height:100vh}
se={_Auth_13g8k_1:"_22ImGiStC_zj9-aVAVSHUL"}
u.b.createElement(B,null,u.b.createElement("div",{className:se.Auth}))
2reactions
ChristiaanScheermeijercommented, Jun 4, 2021

I’ve debugged the problem even further and I found the cause of the issue.

The problem is that after the Snowpack build, CSS modules are being generated with unique localIdentNames. However, the original properties are being preserved and mapped by the proxy json object.

When running Webpack optimize, the *.module.css.proxy.js imports are being rewritten to *.module.css. But this will not work since the css-loader now uses an already generated CSS file with local scope selectors.

The following suggestions might fix this problem.

  1. Disable the postCssModules processor when running a build with optimize

https://github.com/snowpackjs/snowpack/blob/cd6ec781af93f8ed34a7b93b94318eeb3f3054ce/snowpack/src/build/import-css.ts#L17-L22

  1. Set the postCssModules scopeBehavior to global when running build with optimize.

  2. Somehow use the original CSS Modules file in the Webpack build instead of the already processed file.

However, I don’t know the impact of these changes.

I did found a temporary solution. The following Webpack loader strips the postCssModules uniqueness from the selectors in all *.modules.css files.

scripts/webpack/css-modules-fix.js

module.exports = function cssModulesFix(source) {
  return source.replace(/_(\w+)_[\w\d]{5}_\d+/g, function(fullMatch, originalSelector) {
    return originalSelector;
  });
};

snowpack.config.js

['@snowpack/plugin-webpack', {
      extendConfig: (config) => {
        const cssModulesRule = config.module.rules.find((rule) =>
          rule && rule.use && rule.use.find((use) => use && use.loader && use.loader.includes('css-loader') && use.options && use.options.modules));

        if (cssModulesRule) {
          cssModulesRule.use.unshift({
            loader:  require.resolve('./scripts/webpack/css-modules-fix.js'),
          });
        }

        return config;
      },
    }],

@monken this fix does create a single CSS file. You must re-enable the Snowpack loaders as well.

Read more comments on GitHub >

github_iconTop Results From Across the Web

[BUG] Generated CSS modules class names are deleted from ...
[BUG] Generated CSS modules class names are deleted from the HTML on production builds with optimize #3243. Open. 4 tasks done.
Read more >
How to configure CSS Modules for webpack - LogRocket Blog
Running npm run dev will show our styles applied to the page. We can see the generated class names in the DOM tree....
Read more >
Imported scss class names converted to hashes - Stack Overflow
The class names are converted to hashes because you're using css modules. In order to disable that you must set modules: false, ...
Read more >
css-loader | webpack - JS.ORG
'minimal-subset' Auto detect if identifier names can be omitted from hashing. Use this value to optimize the output for better GZIP or Brotli...
Read more >
What are CSS Modules and why do we need them?
CSS files in which all class names and animation names are scoped locally by default. ... Our generated HTML might look like this:...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found