Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS Modules without stylesheet_pack_tag #1720

Closed
madroneropaulo opened this issue Oct 1, 2018 · 13 comments
Closed

CSS Modules without stylesheet_pack_tag #1720

madroneropaulo opened this issue Oct 1, 2018 · 13 comments

Comments

@madroneropaulo
Copy link

madroneropaulo commented Oct 1, 2018

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

@ytbryan
Copy link
Contributor

ytbryan commented Oct 2, 2018

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

You cannot do without it.

@joshalling
Copy link

joshalling commented Nov 1, 2018

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.

@DanielHeath
Copy link

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?

@madroneropaulo
Copy link
Author

@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.

@ytbryan
Copy link
Contributor

ytbryan commented Dec 21, 2018

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

@DanielHeath
Copy link

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

I've proposed #1849 which I think would be a clean way to allow it.

@madroneropaulo
Copy link
Author

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?

@DanielHeath
Copy link

DanielHeath commented Apr 1, 2019 via email

@bradreid
Copy link

bradreid commented Apr 1, 2019

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

@josemigallas
Copy link

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?

@madroneropaulo
Copy link
Author

madroneropaulo commented Jul 22, 2019

@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'
});

@josemigallas
Copy link

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

@guillaumebriday
Copy link
Member

Is this issue still relevant? Feel free to reopen if needed

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

No branches or pull requests

7 participants