Can I exclude certain css files from being bundled as css modules?
I'm building a SPA and have split the project into several npm modules. I'm using React, Typescript and PostCSS to CSS Modules for my components. This works fine. However, sometimes I want to use third party react components, that I need to style with custom CSS. In particular I'm currently trying to style the datepicker "react-datetime". To include the default css that comes with the component I simply add
import "react-datetime/css/react-datetime.css"
and the css is bundled correctly.
But, I do not want to use the default styling, so I've added my own css file. To import this one I use:
import "./custom.css";
But this time the css file is imported as a module and all css names are converted and no longer match the css names found in the html produced by the datetime component.
So the question is: Can I exclude certain files from this "css module" processing?
To enable Css Modules in parcel I added a postcss.config.js to the root of my project. It has the following content:
module.exports = {
"modules": true
};
| Software | Version(s) |
| ---------------- | ---------- |
| Parcel |1.9.7
| Node |8.11.3
| npm/Yarn | 5.6.0
| Operating System | Win10
After some investigation I found a solution by adding the following to postcss.config.js:
stringHash= require("string-hash");
module.exports = {
"modules": true,
"plugins": {
"postcss-modules": {
"generateScopedName":
function(name, filename, css) {
if(filename.endsWith("custom.css")) return name;
const i = css.indexOf(`.${name}`);
const lineNumber = css.substr(0, i).split(/[\r\n]/).length;
const hash = stringHash(css)
.toString(36)
.substr(0, 5);
return `_${name}_${hash}_${lineNumber}`;
}
,
"root": "."
}
}
};
This can also be achieved by importing the necessary css in another css with :global{}
rule:
:global {
@import '~bootstrap/index.css'
}
just to add to @SpadarShut's comment:
switching a _whole block_ of rules to :global
only works if you're importing from a less/sass file (see https://github.com/css-modules/css-modules#usage-with-preprocessors)
with vanilla CSS you're stuck with prefixing each and every rule with :global
in your custom.css
For me, set postcss.config.js
configuration as following works :)
https://github.com/css-modules/postcss-modules#generating-scoped-names
module.exports = {
modules: true,
plugins: {
'postcss-modules': {
globalModulePaths: [
// Put your global css file paths.
'index.css'
]
}
}
}
Turns out my postcss.config.js
was malformed to begin with. Based on @subuta's post I got it working. Thanks!
ideally css modules are only used if suffix .module.css|scss
whereas index.css
would be treated as vanilla css and index.module.css
would be a css module
@subuta Thank you so much for this solution. I've spent a lot of time trying to separate global css files from css modules and avoid weird behavior. My classes inside src/global.css
emitted twice in a bundle: normal (as expected) and prefixed right above normal ones. I was surprised when noticed, that plugins declaration in form of array significantly differed from object style. Your config worked well!
Thank you @subuta for this solution, that helped me get css modules working and allowed me to configure it. My challenge, now, is how do I use a custom postcss plugin with that same configuration?
To illustrate:
module.exports = {
modules: true,
plugins: {
'postcss-modules': {
globalModulePaths: [
/global.css/
]
},
autoprefixer: true
}
}
That works, because plugins
is an Object. But plugins
as an Object does not let me use a custom plugin, since it is a function. So for example:
const myPostcssPlugin = require('./path/to/my/custom/plugin')
module.exports = {
modules: true,
plugins: [
require('postcss-modules')({
globalModulePaths: [
/global.css/
]
}),
myPostcssPlugin(),
require('autoprefixer')
]
}
Even though this is a valid Postcss configuration (and is the same config as above, with the exception of the custom plugin), this seems to break the CSS modules behavior.
How can I configure Postcss with Parcel to both have a configurable css modules and a custom postcss plugin?
Even though this is a valid Postcss configuration (and is the same config as above, with the exception of the custom plugin), this seems to break the CSS modules behavior.
@thezimmee From reading postcss transform codes, and loadPlugins function and localRequire, try these syntax. (have not tested ๐)
module.exports = {
modules: true,
plugins: {
'postcss-modules': {
globalModulePaths: [
/global.css/
]
},
'./path/to/my/custom/plugin': true,
autoprefixer: true
}
}
If ./path/to/my/custom/plugin
not found at runtime, then you may try NODE_PATH
or adding Module resolution configutation(might not related)
SEE: https://parceljs.org/module_resolution.html
Thanks @subuta for the suggestions. I still can't seem to get it to work. Here's what I've tried:
Relative path (./config/postcss-custom-units.js
). This throws an error as if Parcel's looking for the plugin relative to _the source CSS file_ (error: Cannot find module './config/postcss-custom-units.js' from '/.../Projects/.../network-summary'
).
Relative path with tilde (~/config/postcss-custom-units.js
). This causes Parcel's plugin installer to throw an error saying: Failed to install ~. at PromiseQueue.install [as process] (/.../node_modules/parcel/src/utils/installPackage.js:46:11)
.
Absolute path (/config/postcss-custom-units.js
). Throws same error as in #1.
Use the alias
feature in package.json
, where postcss config refers to it as postcss-custom-units
and package.json.alias
is "postcss-custom-units": "./config/postcss-custom-units.js"
. Throws same error as in # 1.
Same as # 4 with alias configured as "postcss-custom-units": "~/config/postcss-custom-units.js"
. Throws same error as in # 1.
Same as # 4 with alias configured as "postcss-custom-units": "/config/postcss-custom-units.js"
. Throws same error as in # 1.
If anybody has any ideas, I'm all ears.
UPDATE:
For the record I finally figured it out. I installed the local custom plugin as a local/file dependency:
In package.json:
"devDependencies": {
"postcss-custom-units": "file:config/postcss-custom-units"
}
(or add with npm i -D <plugin folder>
).
Then in postcss config, just refer to the dependency name:
module.exports = {
modules: true,
plugins: {
'postcss-modules': {
globalModulePaths: [
/global.css/
]
},
'postcss-custom-units': {...},
autoprefixer: true
}
}
And it works!!
I'm not able to use Ant Design using the :global
approach:
// src/index.less
:global {
@import '~antd/dist/antd.less';
}
// src/index.js
import './index.less'
I'm not able to use Ant Design using the
:global
approach:// src/index.less :global { @import '~antd/dist/antd.less'; }
// src/index.js import './index.less'
same problem. Any solution now?
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
This can also be achieved by importing the necessary css in another css with
:global{}
rule: