Webpacker: CSS Modules without stylesheet_pack_tag

Created on 1 Oct 2018  Â·  12Comments  Â·  Source: rails/webpacker

According to this https://github.com/rails/webpacker/blob/master/docs/webpack.md#overriding-loader-options-in-webpack-3-for-css-modules-etc

If you want to import any css module, you should manually include it in your view using the <%= stylesheet_pack_tag 'my_styles' %> tag.

I couldn't manage to make it work without it, I'm importing the styles as modules import styles from './my_styles.scss' from a jsx component, and then importing that component into a view with <%= javascript_pack_tag 'my_component' %>. The component itself is imported and rendered, including the classNames generated by the css module. However, the stylesheet is NOT rendered into de DOM, and according to styles-loader and css-loader they should be rendered out of the box.

I'm not sure which config is wrong on webpacker that is preventing this from happening.

this is my .babelrc

{
  "presets": [
    [
      "env",
      {
        "modules": "commonjs",
        "targets": {
          "browsers": "> 1%",
          "uglify": true,
          "node": "current",
          "modules": "commonjs"
        },
        "useBuiltIns": true,
        "development": {
          "plugins": ["transform-es2015-modules-commonjs"]
        }
      }
    ],
    "react",
    "env"
  ],
  "plugins": [
    "syntax-dynamic-import",
    "transform-object-rest-spread",
    [
      "transform-class-properties",
      {
        "spec": true
      }
    ]
  ]
}

this is my webpack/environment.js (I haven't touched the others)

const { environment } = require('@rails/webpacker');
const merge = require('webpack-merge');

const myCssLoaderOptions = {
    modules: true,
    sourceMap: true,
    localIdentName: '[name]__[local]___[hash:base64:5]'
};

const CSSLoader = environment.loaders.get('sass').use.find(el => el.loader === 'css-loader');

CSSLoader.options = merge(CSSLoader.options, myCssLoaderOptions);

module.exports = environment;

And my package.json

{
  "private": true,
  "scripts": {
    "test": "jest --env=jsdom '--coverage'",
    "build": "./bin/webpack",
    "start": "./bin/webpack-dev-server"
  },
  "devDependencies": {
    "autoprefixer": "9.1.1",
    "babel-core": "~6.26.3",
    "babel-jest": "^23.6.0",
    "babel-loader": "^7.0.2",
    "enzyme": "^3.6.0",
    "enzyme-adapter-react-16": "^1.5.0",
    "identity-obj-proxy": "^3.0.0",
    "jest": "23.4.1",
    "webpack": "^3.5.5",
    "webpack-cli": "3.1.0",
    "webpack-dev-server": "2.11.2"
  },
  "dependencies": {
    "@rails/webpacker": "3.5",
    "babel-preset-env": "^1.7.0",
    "babel-preset-react": "^6.24.1",
    "postcss-loader": "~3.0.0",
    "prop-types": "^15.6.2",
    "react": "^16.5.2",
    "react-dom": "^16.5.2",
    "react-select": "^2.0.0",
    "sass-loader": "~7.1.0",
    "webpack-merge": "^4.1.4"
  }
}

What can I do to be able to import the styles using only the import style from './my_style.scss statement from any js?
Why it isn't the default behavior?

Thank you

Most helpful comment

I'm working on this too and cannot get it working. I'd like to use react-rails, webpacker, and css modules (without stylesheet_pack_tag).

Edit: actually this is working for me. I didn't see this in the docs at first: Stylesheets that end with .module.* are treated as css modules

All 12 comments

From the documentation, you stated, stylesheet_pack_tag is required to import all the styles in your component.

You cannot do without it.

I also want to use css modules with react in rails. I don't want to have to use the stylesheet_pack_tag to do this and these docs imply that webpacker will import the styles directly. However, when I use that code it also doesn't load the css, only the classNames.

I'd like to understand what you would like to happen instead of using stylesheet_pack_tag.

Are you hoping to have the styles injected by JS?

@DanielHeath the problem is that I'm already importing the styles as modules from the javascripts using the import statement. It's not intuitive and it's overwhelming to have to manually add _again_ a stylesheet_pack_tag in the html for each css module that is already imported from javascript. Basically you are maintaining the injection of these dependencies in two places. Ideally, if the css module is already imported from the javascript, it should be just bundled as any other javascript.

it's overwhelming to have to manually add again a stylesheet_pack_tag in the html for each css module that is already imported from javascript

Have you considered placing<%= stylesheet_pack_tag 'application' %> at your application.html.erb?

From the readme

You can then link the JavaScript pack in Rails views using the javascript_pack_tag helper. If you have styles imported in your pack file, you can link them by using stylesheet_pack_tag:

<%= javascript_pack_tag 'application' %>
<%= stylesheet_pack_tag 'application' %>

Hope this helps

More broadly - how do you envisage using mangled classnames (from modules) in your views?

I've proposed https://github.com/rails/webpacker/issues/1849 which I think would be a clean way to allow it.

Hasn't this issue been solved with webpacker 4? According to these docs https://github.com/rails/webpacker/blob/master/docs/css.md I only need to import the style within javascript. I do so, and on development works fine, but on production it doesn't work. It works on production only if I set extract_css: false in webpacker.yml. Not sure if that has performance implications?

How does that let you use mangled class names in your erb files?

Thanks,
Daniel Heath

On 1 Apr 2019, at 12:21 pm, Paulo notifications@github.com wrote:

Hasn't this issue been solved with webpacker 4? According to these docs https://github.com/rails/webpacker/blob/master/docs/css.md I only need to import the style within javascript. I do so, and on development works fine, but on production it doesn't work. It works on production only if I set extract_css: false in webpacker.yml. Not sure if that has performance implications?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

I'm working on this too and cannot get it working. I'd like to use react-rails, webpacker, and css modules (without stylesheet_pack_tag).

Edit: actually this is working for me. I didn't see this in the docs at first: Stylesheets that end with .module.* are treated as css modules

How about this: I have all my functions and constants declared in the Rails side of the app (under app/assets/stylesheet) but I'd like to use them in my React components styles (that are imported using css-modules). However, none of those functions or variables work from there, is there a workaround for this?

@josemigallas hm it works for me (at least in development mode, haven't tried on prod, but I think it will work)
In your styles file used by your React App try to

//my_react_styles.scss
@import "../../my_assets_directory/stylesheets/my_styles.scss"

And you'll have access to whathever variable is declared in my_styles.scss

I just added the right loader to my webpacker webpack configuration

//webpacker webpack config
environment.loaders.get('sass').use.splice(-1, 0, {
    loader: 'resolve-url-loader'
});

@madroneropaulo of course, how I did not think about that! Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

FrankFang picture FrankFang  Â·  3Comments

ankitrg picture ankitrg  Â·  3Comments

christianrojas picture christianrojas  Â·  3Comments

ijdickinson picture ijdickinson  Â·  3Comments

inopinatus picture inopinatus  Â·  3Comments