I am trying to import a scss file from node_modules
. This to be exact:
https://github.com/material-components/material-components-web-react/tree/master/packages/button
I tried @import '@material/react-button/index.scss';
in my scss file. This yields this error:
/Users/alex/Developer/sasm2/src/app.scss: File to import not found or unreadable: ./@material/react-button/index.scss.
at options.error (/Users/alex/Developer/sasm2/node_modules/node-sass/lib/index.js:291:26)
I also tried @import '../node_modules/@material/react-button/index.scss';
which results in
/Users/alex/Developer/sasm2/src/app.scss: File to import not found or unreadable: ./@material/button/mdc-button.
at options.error (/Users/alex/Developer/sasm2/node_modules/node-sass/lib/index.js:291:26)
The second error message references mdc-button instead of react-button. This is because react-button imports mdc-button. It does of course not use the node_modules path.
Can we add the functionality to parcel to resolve pathes into node_modules just like for javascript imports?
| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.9.7
| Node | v10.7.0
| npm/Yarn | 6.2.0
| Operating System | macOS 10.13.6
You could try your luck with the tilde operator (~
) to reference node_modules.
For example:
@import '~@material/react-button/index.scss';
This does work indeed. The problem are still the transitive dependencies. It fails with the first depdency like before:
/Users/alex/Developer/sasm2/src/app.scss: File to import not found or unreadable: ./@material/button/mdc-button.
When looking at these modules it is clear that they expect the the same semantic as ES2015 imports: When the path is not prefixed with /
or .
node_modules
should be searched.
Is it possible to implement this behaviour within parcel?
@athei this is the result of everyone just creating a new syntax for importing css, basically there are no standards for these things unfortunately. This will probably not be implemented at the moment, but you can probably add a postCSS plugin that resolves/rewrites the imports.
We followed webpacks weird ~node_module/...
syntax as it seemed most common. However originally we used the basic JS import syntax, but it caused many issues.
My personal opinion is that css in node_modules should be static and not contains any imports and definitely not with an exotic syntax.
but you can probably add a postCSS plugin that resolves/rewrites the imports.
Are you sure that this will help? Does the postcss help at build time where the error occurs?
I'm not sure haven't tried. But in theory it should
I just tried with a really minimal postcss plugin that just prepends ~
to all imports and it did not work. It seems to fail so fast before the postcss even runs.
app.scss
@import '@material/react-button/index.scss';
postcss.config.js
var postcss = require('postcss');
var tilde = postcss.plugin('postcss-tilde', function (opts) {
opts = opts || {};
var regex = new RegExp('^([\'"])(.+)([\'"])$');
return function (root, result) {
root.walkAtRules(function(rule) {
if (rule.name !== 'import')
return
rule.params = rule.params.replace(regex, '$1~$2$3');
});
};
});
module.exports = {
plugins: [
tilde,
],
};
I verified with postcss-cli
:
npx postcss-cli src/app.scss -c postcss.config.js
@import '~@material/react-button/index.scss';
Still I get this:
/Users/alex/Developer/sasm2/src/app.scss: File to import not found or unreadable: ./@material/react-button/index.scss.
at options.error (/Users/alex/Developer/sasm2/node_modules/node-sass/lib/index.js:291:26)
Ow I might have given you wrong advice, I meant sass plugin.
User defined importer plugins should have priority over parcels built-in one
https://github.com/parcel-bundler/parcel/blob/master/src/assets/SASSAsset.js#L50-L62
I am not sure what you mean by sass plugin. Should I register a *.scss
access type?:
https://parceljs.org/asset_types.html
After inspecting the source you linked I understood that the opts
that contain the importers are coming from package.json
. I did not find a way to pass these as a plugin or how to pass functors (an importer) through package.json. The following code in package.json did also work:
"sass": {
"includePaths": ["./node_modules"]
}
The plugins are part of .sassrc.js
. You'd probably have to add this config to the node_module of material for this.
module.export = {
importer: () => {
// Write some resolve logic...
}
}
And how to write a plugin is documented by sass-node
, documentation is pretty limited but I guess you can figure it out by looking at the source I linked... Pretty much just copy and edit that
Or probably a better idea, pre-compile the entire material node_module and use that :) Turn it into a private package, make it part of a monorepo or make it public and name it material-compiled or something. You can even add postCSS config to enable css modules on it if you want, like mentioned earlier, I don't think css should be published as uncompiled/untranspiled source, neither does js so why would css do it
I am also using material-components-web-react and ran into this issue.
I was just trying to import a Button and use it but got:
Error: File to import not found or unreadable: ./@material/button/mdc-button.
on line 23 of stdin
@import "@material/button/mdc-button";
So if you import:
import '@material/react-button/index.scss';
from App.js directly jumping into node_modules (with .sassrc includePaths config), it won't work.
Just include this from inside an App.scss rather
@import '@material/react-button/index.scss';
remember @
Then import App.scss from App.js
import './App.scss'
no @
In my .sassrc from root dir I have
{
"includePaths": ["src", "node_modules"]
}
So the trick is: don't import from scss from .js jumping right into node_modules straight away. Rather, first import an scss locally, same dir, then jump into node_modules from there within scss with @import.
Also it's more convenient because if you want to override some styles you can do it inside App.scss.
You could try your luck with the tilde operator (
~
) to reference node_modules.For example:
@import '~@material/react-button/index.scss';
Thanks very much. It's weird how other libraries are getting imported okay on a non-tilde way, though,
Still can't get it to work:
How the hell do you tell sass to grab the style from module? Tried with:
The correct way to import and reference files from node_module
is the following:
npm install -D node-sass
npm install -D node-sass-package-importer
Then update your node-sass script to use the importer. Example, in package.json
:
Change:
"sass": "node-sass ./my-styles.scss ./dist/styles.css",
To:
"sass": "node-sass --importer node_modules/node-sass-package-importer/dist/cli.js ./my-styles.scss ./dist/styles.css",
You will be able to import using the ~
sign.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.
Most helpful comment
You could try your luck with the tilde operator (
~
) to reference node_modules.For example: