I'm trying to use Material Components Web (MDC-Web) but with no success.
The given example in webpacker README works for single file with non-relative imports within like:
@import '~@material/animation/mdc-animation.scss' // works fine
However it fails when I try to import whole MDC as suggested in https://yarnpkg.com/en/package/material-components-web
```(bash)
// app-styles.sass
@import "~material-components-web/material-components-web"
// console
Module build failed:
@import "@material/animation/mdc-animation";
^
File to import not found or unreadable: @material/animation/mdc-animation.
Parent style sheet: /project_root/node_modules/material-components-web/material-components-web.scss
in /project_root/node_modules/material-components-web/material-components-web.scss (line 17, column 1)
In /project_root/node_modules/material-components-web/material-components-web.scss (line 17, column 1)
`@import "@material/animation/mdc-animation";`
This doesn't seem to work whenever there is a non-relative import within the sass file being imported.
```[bash]
// app-styles.sass
@import "~@material/button/mdc-button"
// console
Module build failed:
@import "@material/animation/variables";
^
File to import not found or unreadable: @material/animation/variables.
Parent style sheet: /project_root/node_modules/@material/button/mdc-button.scss
in /project_root/node_modules/@material/button/mdc-button.scss (line 17, column 1)
In /project_root/node_modules/@material/button/mdc-button.scss (line 17, column 1)
@import "@material/animation/variables";
I tried tweaking things using below reources but couldn't figure it out.
https://webpack.js.org/configuration/resolve/
https://yarnpkg.com/en/package/module-alias
Related: https://stackoverflow.com/q/43187195
Please use dist - @import "~material-components-web/dist/material-components-web"
I think there is a bug with library, those files are not there:

@gauravtiwari Those files are there within node_modules/@material along with node_modules/material-components-web directory.
(bash)
โฏ ls node_modules | grep material
@material
material-components-web
material-components-web creates a separate folder named @material and stores various components within it as subfolders.

@zoras Ahh that's why. You see, sass-loader needs a ~ in the beginning to understand that a particular file is using a node_modules import. Since material-components-web doesn't respect that unfortunately it's not possible - https://github.com/webpack-contrib/sass-loader#imports
The main file is referenced correctly but not the children modules. Another solution would be to import this inside .js file and see if that works?
import 'material-components-web/material-components-web'
@gauravtiwari nop, it didn't work and throws same error.
```(bash)
// in app/javascript/packs/application.js
import 'material-components-web/material-components-web'
// console
Module build failed:
@import "@material/animation/mdc-animation";
^
File to import not found or unreadable: @material/animation/mdc-animation.
Parent style sheet: stdin
in /project_root/node_modules/material-components-web/material-components-web.scss (line 17, column 1)
@ ./~/material-components-web/material-components-web.scss 4:14-201
@ ./app/javascript/packs/application.js
```
Is there any way to rewrite or tell sass-loader to check in ~ or node_modules directory by default?
@zoras Don't think that's easily possible. Have you figured it out yet? Perhaps you may want to open an issue on material-components-web repo.
Spent some time debugging and figuring out what going on in the webpacker code.
Here how I did it:
config/webpack/loaders/sass.js with content:const cssLoader = require('@rails/webpacker/package/rules/css')
const cloneDeep = require('lodash/fp/cloneDeep')
const deepMerge = require('@rails/webpacker/package/utils/deep_merge')
let sassLoader = cloneDeep(cssLoader)
module.exports = deepMerge(sassLoader, {
test: /\.(scss|sass)$/i,
use: [{
loader: 'sass-loader',
options: {
includePaths: ['node_modules'],
sourceMap: true,
},
}]
})
The content is mostly copied from node_modules/@rails/webpacker/package/rules/sass.js
the important part is: includePaths: ['node_modules'],
config/webpack/environment.jsconst { environment } = require('@rails/webpacker')
const typescript = require('./loaders/typescript')
const sass = require('./loaders/sass')
environment.loaders.append('typescript', typescript)
environment.loaders.append('sass', sass)
module.exports = environment
And it just works the hard part was inspecting webpacker code and figuring out what to do.
Finally figured this out and it's actually pretty simple. You need to update the existing default sass-loader!
simply add the following in config/webpack/enviroment.js just before module.exports
environment.loaders.get('sass').use.find(item => item.loader === 'sass-loader').options.includePaths = ['node_modules']
Which is actually shown pretty well in the documentation:
Probably a cleaner way to do it instead of chaining but it works.
Most helpful comment
Spent some time debugging and figuring out what going on in the webpacker code.
Here how I did it:
config/webpack/loaders/sass.jswith content:The content is mostly copied from
node_modules/@rails/webpacker/package/rules/sass.jsthe important part is:
includePaths: ['node_modules'],config/webpack/environment.jsThis is mine (working on a typescript project)
And it just works the hard part was inspecting webpacker code and figuring out what to do.