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 in Webpacker 3.0? #775

Closed
ezuk opened this issue Sep 8, 2017 · 14 comments
Closed

CSS Modules in Webpacker 3.0? #775

ezuk opened this issue Sep 8, 2017 · 14 comments

Comments

@ezuk
Copy link
Contributor

ezuk commented Sep 8, 2017

Hi there,

I had CSS modules working with Webpacker 2.x, but when upgrading to 3 they just stop working. No errors or anything, I just get empty objects when importing a CSS file.

Here's my loaders/style.js:

const ExtractTextPlugin = require('extract-text-webpack-plugin')
const path = require('path')
const config = require('../config')

const postcssConfigPath = path.resolve(process.cwd(), '.postcssrc.yml')
const isProduction = process.env.NODE_ENV === 'production'
const extractCSS = !(config.dev_server && config.dev_server.hmr)

const extractOptions = {
  fallback: 'style-loader',
  use: [
    { loader: 'css-loader', options: {
        minimize: env.NODE_ENV === 'production',
        modules: true,
        localIdentName: '[path][name]__[local]--[hash:base64:5]'
      }
    },
    { loader: 'postcss-loader', options: { sourceMap: true, config: { path: postcssConfigPath } } },
    'resolve-url-loader',
    { loader: 'sass-loader', options: { sourceMap: true } }
  ]
}

// For production extract styles to a separate bundle
const extractCSSLoader = {
  test: /\.(scss|sass|css)$/i,
  use: ExtractTextPlugin.extract(extractOptions)
}

// For hot-reloading use regular loaders
const inlineCSSLoader = {
  test: /\.(scss|sass|css)$/i,
  use: ['style-loader'].concat(extractOptions.use)
}

module.exports = isProduction || extractCSS ? extractCSSLoader : inlineCSSLoader

So I set modules to true. However, when compiling, I still get this:

WARNING in ./node_modules/css-loader?{"minimize":false}!./node_modules/postcss-loader/lib?{"sourceMap":true,"config":{"path":"/home/ezuk/ccn/.postcssrc.yml"}}!./node_modules/resolve-url-loader!./node_modules/sass-loader/lib/loader.js?{"sourceMap":true}!./app/javascript/components/Training/styles.scss

So I don't see my options applied to the css-loader here.

This happened also with sass.js as the loader - I switched to styles.js based on this loader.

Any idea why I can't get modules to play nice here? Thank you!

@brentdodell
Copy link

I would like to know how to enable CSS Modules in Webpacker 3.0 as well. I was actually just about to open a new issue when I found this one that is very recent.

You said you had them working on 2.0. I am brand new to Webpack(er), and so this is probably a silly question, but...

To my understanding, on 2.0 the loaders were created by Webpacker at the time of install and lived in config/webpack/loaders/ where you could easily customize them, but in 3.0 don't they live in the Webpacker NPM package where they're inaccessible?

What happens when you create a loader file with the same name in config/webpack/loaders/? Does it get used instead of the default by the same name inside the Webpacker package?

The docs for Webpacker don't seem super helpful. They mention adding a new loader (in config/webpack/loaders), and modifying an existing loader (through config/webpack/environment.js)...the one they modify though (babel) is super simple compared to the style loader.

Also, how do you define what loaders are ran? Is it in the config somewhere, or is it that all .js files inside the loaders folder (be it inside the package, or in our config/webpack folder) get combined, and whichever happens to match first based on the value of test in the loader config?

@gauravtiwari
Copy link
Member

Please see this comment: #756 (comment)

Does this help?

@ezuk
Copy link
Contributor Author

ezuk commented Sep 8, 2017

@gauravtiwari bingo! That fixed it. Opened a PR to update the docs to put this in as a recipe (many people want CSS modules I suspect): #777

@axhamre
Copy link

axhamre commented Sep 19, 2017

I'm using the exact code linked to by guaravtiwari above. The hashed CSS-class is rendered on the element, but no styling is applied.

When logging styles.myNiceClass I get color: "Hello__color___3dGW5" - does that give any hint what is happening?

This is what I have in the file Hello.css:

.myNiceClass {color: blue;}

@kozhin
Copy link

kozhin commented Sep 21, 2017

The same with me.

@marshall-cho
Copy link

Chiming in here. CSS modules worked pretty much out of the box with Webpacker 2. I totally understand that CSS modules isn't Webpacker's responsibility, but it would be super nice if someone could provide a working code sample for CSS modules to smoothen the transition from Webpacker 2 to 3.

@gauravtiwari
Copy link
Member

@kozhin
Copy link

kozhin commented Sep 22, 2017

@gauravtiwari I guess, we both did as described at https://github.com/rails/webpacker/blob/master/docs/webpack.md#overriding-loader-options-in-webpack-3-for-css-modules-etc
The result is:

  • class names are generated as expected
  • but no corresponding stylesheets are loaded for generated class names
    Webpack compiles assets without any errors or warnings.
    CSS modules option is enabled - I see it in Webpack's output:

./node_modules/css-loader?{"minimize":false,"modules":true,"sourceMap":true,"localIdentName":"[name]__[local]___[hash:base64:5]"}!./node_modules/postcss-loader/lib?{"sourceMap":true,"config":{"path":"/app/.postcssrc.yml"}}!./node_modules/resolve-url-loader!./node_modules/sass-loader/lib/loader.js?{"sourceMap":true}!./app/javascript/components/subscribe_button/SubscribeButton.scss

screen shot 2017-09-22 at 12 13 53

@gauravtiwari
Copy link
Member

Just tested seems to work fine for me. The environment.js has this:

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('style').use.find(el => el.loader === 'css-loader')

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

module.exports = environment

screen shot 2017-09-22 at 10 20 13

Works with both watcher and dev server.

@gauravtiwari
Copy link
Member

Btw you are referencing styles within your components right?

import styles from './style.sass'

class HelloReact extends React.Component {
  componentDidMount() {
    this._node.style.fontSize = '25px'
  }

  handleOnClick = () =>
    console.log('I got clicked')

  render () {
    return (
      <div className={styles['hello-react']}>
        <p ref={node => (this._node = node)}>Hello {this.props.name}!</p>
        <img onClick={this.handleOnClick} src={logo} className={styles['react-logo']} alt="React" />
      </div>
    )
  }
}

@kozhin
Copy link

kozhin commented Sep 22, 2017

@gauravtiwari thank you very much! I've investigated your example and found that I forgot to add a line declaring pack's stylesheets.

<%= stylesheet_pack_tag 'YOUR_PACK_NAME_HERE', media: 'all', 'data-turbolinks-track': 'reload' %>

@gauravtiwari
Copy link
Member

No problem 👍 Glad it's fixed 😄

ezuk added a commit to ezuk/webpacker that referenced this issue Sep 22, 2017
Stresses that you need to use the stylesheet pack tag, based on further confusion around rails#775
@ezuk ezuk mentioned this issue Sep 22, 2017
gauravtiwari pushed a commit that referenced this issue Sep 22, 2017
Stresses that you need to use the stylesheet pack tag, based on further confusion around #775
@axhamre
Copy link

axhamre commented Sep 22, 2017

That solved it for me too, thank you so much @gauravtiwari for the patience.

I've got nobody to blame but myself, but I think it was the initial commented lines in the generated react file that made me to stop thinking (it only mentions the javascript_pack_tag):

Run this example by adding <%= javascript_pack_tag 'hello_react' %> to the head of your layout file...

@JarLowrey
Copy link

JarLowrey commented Oct 16, 2017

I am trying to style an external library through the CSS loader instead of using global styles - arqex/react-datetime#439 . I am using the given loader code (from above discussion) in my environment.js and my react component looks something like this

import styles from 'react-datetime/css/react-datetime.css'
import Datetime from 'react-datetime';
import React from 'react';

export default class EventSearchForm extends React.Component {

  render() {
    return (
      <div>
        <Datetime className={styles['rdt']} />
        <Datetime />
      </div>
    );
  }
}

The css-loader component appears to be working. The generated class name is there and it links to the included style sheet if I include the pack_tags in layout's head (as mentioned above).

    <%= javascript_pack_tag 'application' %>
    <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>

selection_023

It looks like only the top level element's style is being included though, only the rdt class. So I guess my question is, is there any way to use css-loader + style-loader to style child elements of an external component?

Supposedly the default style-loader should take care of this, but it's not working. I printed out my style loaders in environment.js (console.log(environment.loaders.get('style')) ) and received

{ test: /\.(scss|sass|css)$/i,
  use:
   [ { loader: '/home/james/Documents/comity.fit/node_modules/extract-text-webpack-plugin/dist/loader.js',
       options: [Object] },
     { loader: 'style-loader' },
     { loader: 'css-loader', options: [Object] },
     { loader: 'postcss-loader', options: [Object] },
     { loader: 'resolve-url-loader' },
     { loader: 'sass-loader', options: [Object] } ] }

So I'd think style, sass, css etc loader should be working fine, but the styles are not being included.

sensiblegame added a commit to sensiblegame/webpack that referenced this issue Oct 23, 2017
Stresses that you need to use the stylesheet pack tag, based on further confusion around rails/webpacker#775
KingTiger001 added a commit to KingTiger001/Rails-web-pack-project that referenced this issue Jan 15, 2023
Stresses that you need to use the stylesheet pack tag, based on further confusion around rails/webpacker#775
smartech7 pushed a commit to smartech7/ruby-webpacker that referenced this issue Aug 4, 2023
Stresses that you need to use the stylesheet pack tag, based on further confusion around rails/webpacker#775
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