In Webpacker 3.0.2 I had these settings in config/webpack/environment.js as outlined in the docs:
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
But having those settings after upgrading Webpacker is causing this error:
/Users/me/Documents/my-app/node_modules/@rails/webpacker/package/config_types/config_list.js:55
if (shouldThrow && index < 0) throw new Error(`Item ${key} not found`)
^
So I tried the example outlined in the Changelog:
const sassLoader = environment.loaders.get('sass')
const cssLoader = sassLoader.use.find(loader => loader.loader === 'css-loader')
cssLoader.options = Object.assign(cssLoader.options, {
modules: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]'
})
The error goes away, but I'm not sure those settings are being applied, because now I'm getting an error about CSS comments:
ERROR in ./app/javascript/packs/Footer.css
Module build failed: ModuleBuildError: Module build failed: Syntax Error
(26:1) Unknown word
24 | // @include bp-small {
25 | // padding: 40px 20px 20px;
> 26 | // }
| ^
And error message about local/global scope for css modules:
ERROR in ./node_modules/css-loader?{"minimize":false,"sourceMap":true,"importLoaders":2}!./node_modules/postcss-loader/lib?{"sourceMap":true,"config":{"path":"/Users/me/Documents/my-app/.postcssrc.yml"}}!./app/javascript/packs/link-editor/Durations.css
Module build failed: Error: composition is only allowed when selector is single :local class name not in ".descrText", ".descrText" is weird
at /Users/me/Documents/my-app/node_modules/postcss-modules-scope/lib/index.js:26:13
at Array.map (<anonymous>)
at getSingleLocalNamesForComposes (/Users/me/Documents/my-app/node_modules/postcss-modules-scope/lib/index.js:20:26)
at /Users/me/Documents/my-app/node_modules/postcss-modules-scope/lib/index.js:106:26
at /Users/me/Documents/my-app/node_modules/postcss/lib/container.js:198:28
at /Users/me/Documents/my-app/node_modules/postcss/lib/container.js:148:26
at Rule.each (/Users/me/Documents/my-app/node_modules/postcss/lib/container.js:114:22)
at Rule.walk (/Users/me/Documents/my-app/node_modules/postcss/lib/container.js:147:21)
at Rule.walkDecls (/Users/me/Documents/my-app/node_modules/postcss/lib/container.js:196:25)
at /Users/me/Documents/my-app/node_modules/postcss-modules-scope/lib/index.js:105:12
Footer.css isn't a sass file right? ERROR in ./app/javascript/packs/Footer.css Looks like you are including a mixin there.
Ahh my bad, didn't notice that it's a comment
Yes, so if you are using composes with css modules, you can't use composes with pseudoselectors or media queries or subclasses.
Error: composition is only allowed when selector is single :local class name not in ".descrText", ".descrText" is weird
Thanks for report. I can reproduce this locally, will push a fix 馃憤
Yes, removing parts where composes are used removes the error. And it's really not a big deal personally, but it's a bit weird as it worked fine before upgrading.
But the bigger issue is that I still can't getcss-loader to work. Deleting the options in config/webpack/environment.js (mentioned in the Changelog) removes the errors but CSS modules don't seem to be working no more. I guess this is what you had in mind when you said that you're pushing a fix. But anyway I'll post my complete code in config/webpack/environment.js (+ a new error message) to put all cards on the table:
const { environment } = require('@rails/webpacker')
const sassLoader = environment.loaders.get('sass')
const cssLoader = sassLoader.use.find(loader => loader.loader === 'css-loader')
cssLoader.options = Object.assign(cssLoader.options, {
modules: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]'
})
module.exports = environment
Error:
/Users/me/Documents/my-app/config/webpack/environment.js:4
const cssLoader = sassLoader.use.find(loader => loader.loader === 'css-loader')
^
TypeError: Cannot read property 'use' of undefined
at Object.<anonymous> (/Users/me/Documents/my-app/config/webpack/environment.js:4:34)
at Module._compile (module.js:635:30)
at Object.Module._extensions..js (module.js:646:10)
at Module.load (module.js:554:32)
at tryModuleLoad (module.js:497:12)
at Function.Module._load (module.js:489:3)
at Module.require (module.js:579:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/Users/me/Documents/my-app/config/webpack/development.js:1:83)
at Module._compile (module.js:635:30)
Thanks @hundsim Sorry for the trouble. Will fix and make a new release.
Anyway,
/Users/me/Documents/my-app/config/webpack/environment.js:4
const cssLoader = sassLoader.use.find(loader => loader.loader === 'css-loader')
^
TypeError: Cannot read property 'use' of undefined
Seems like you are still using an old version of @rails/webpacker
Hm, no I think I'm on the latest, yarn.lock has this:
"@rails/webpacker@^3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@rails/webpacker/-/webpacker-3.1.1.tgz#040766f1c130a0e71d9d84cf95b0eea32c76bfd3"
...
And btw, as always, it's me that have to thank you for your incredible work 馃檹
@hundsim Thank you 馃檹
So, can you update me what issues are you having currently?
The CSS issue you pointed out, it seems like a bug with css loader:
Fails:
// hello.css
.container {
max-width: 100%;
}
// good one issue
.world {
max-width: 100%;
}
// see more
Works:
// hello.css
.container {
max-width: 100%;
}
// good one issue
.world {
max-width: 100%;
}
Still works:
// hello.css
.container {
max-width: 100%;
}
//good one issue
.world {
max-width: 100%;
}
/* see more */
which probably seems correct because for comments in CSS we use /* */ not //
Made an example here with css modules support: https://github.com/gauravtiwari/webpacker-3.1.1
OK, so this error finally vanished when I ran yarn without the postinstall below in package.json (that I inserted half a year ago thanks to this thread). I tried putting postinstall back and it still without errors 馃檹
"scripts": {
"postinstall": "npm rebuild node-sass"
}
So with the above applied and removing compose and changing type of comments at end of file there are no more errors. But there are no styles applied. I've concluded that it has to do with the file extensions. Up until Webpacker 3.0.2 I've been using .css on all styling files and still fully been able to use css-loader. How can I continue to use the extension.css? I actually suspect this is the root cause to the CSS errors I've reported in this thread.
In the changelog this is mentioned:
"Separate css and sass loader for easier configuration. style loader is now css loader, which resolves .css files and sass loader resolves .scss and .sass files."
I assume this touches on my problem, but I cannot wrap my head around how to configure so that I can work with .css files again (despite the adhering code example) 馃槗
@hundsim Yep, that's true. If you want to use css modules in .css files, please enable css modules there:
const cssRule = environment.loaders.get('css')
const cssLoader = cssRule.use.find(loader => loader.loader === 'css-loader')
cssLoader.options = Object.assign(cssLoader.options, {
modules: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]'
})
The idea behind separation is that:
import global.css)import styles from './app.scss')So, it's up to you which one you use for global styles and app styles.
That separation makes so much sense. And your code clarification was of course obvious..
The "only" thing that I'm still battling with is @import in css-files. Is there any way to get it to work as it did before 3.1?
I'm using relative @import at the top of a .css-file like this, mainly to import variables:
@import "../../variables";
@import should work, since it should use postcss-import under the hood. Are you getting any errors?
No errors. At a second thought/check, SASS functionality doesn't seem to be applied at all. No nesting, no "Undefined variable:", not possible to apply SASS features in the same file etc.
So perhaps I misunderstood the css-loader settings in config/webpack/environment.js. If we set css in this line
const cssRule = environment.loaders.get('css')
then we can import styles into the js-file like so import styles from './MyComponent.css';
but there is no SASS functionality anymore as it was on Webpacker 3.0?
And if this assumption above is correct, then I assume that if we want the SASS functionality as before we have to do 2 things:
const cssRule = environment.loaders.get('sass')Right?
did you resolve this? we use sass functionality like nesting and mixins, but have all files in .css. and use :global to get global scope.
we want to upgrade, so if we convert all .css to .scss everything should work as before?
Yes, I can confirm that it works if you convert all .css files and references 馃憤
If you have hundreds of css-files like me, then this speeds things up:
brew install rename
cd app/javascript/packs
find . -name "*.css" -exec rename 's/\.css$/.scss/' '{}' \;
And then I did a "find and replace" in my editor for all .css references to those files.
Most helpful comment
The idea behind separation is that:
import global.css)import styles from './app.scss')So, it's up to you which one you use for global styles and app styles.