parcel: šCSS Importing effectively broken
The way Parcelās CSS import is currently being implemented broken. There are several issues related to this problem. Basically, Parcel is applying postcss transforms before concatenating the CSS, this means that any CSS that gets imported is not being transformed properly. This breaks functionality and wonāt allow you to use basic features like css-variables if they are being imported anywhere.
related to this: #609 #593 #329
š¤ Expected Behavior
I should be able to declare variables in one file and use them in another via @import
without getting undefined
errors
šÆ Current Behavior
Parcel is not transforming variables that are in imported css files.
š Possible Solution
Concatenate the CSS files (i.e. perform import) before applying transforms. Or let users use the postcss-import
plugin from their own config to get things working properly.
@irritant came up with a patch that was as simply commenting out the import gathering during the collectDependencies()
process, this should perhaps be the default until something is figured out.
š» Code Sample
other.css
:root {
--varColor: #639;
}
input.css
@import './other.css';
body {
color: var(--varColor);
}
output.css
body {
color: var(--varColor); /* should be #639 */
}
some more examples can also be found in #329
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 39
- Comments: 48 (19 by maintainers)
any update on this issue with tailwindcss and @import ?
not sure if it helps anyone but I have published a small postcss plugin as a temporary work around for my project:
npm install postcss-parcel-import
then add it to your .postcssrc or config:and in the pcss files use then
@parcel-import '.../../mixins.pcss'
basically it hides it from parcel importing and will substitute the rule with the file contents before other plugins are run.
This is just a temporary solution until this bug is solved.
Source code under MIT: https://github.com/mendrik/postcss-parcel-import
my solution was to build in two steps.
and run
yarn run build
@mischnic the problem is with imports;
if you split your code example into:
config.css
and app.css
variables wonāt be substituted.
Going on what @michael-ciniawsky said, this works:
variables.css
button.css
.postcssrc
@devongovett What is the reason we dont want postcss processing on the final concatenated file? Is that not how every other tool does this type of stuff?
I think we could maybe solve this issue by moving postcss to the
pretransform
phase, which occurs prior to dependencies being parsed. Currently, it is applied in thetransform
phase, which happens after@import
s are already parsed.https://github.com/parcel-bundler/parcel/blob/bdc044acfad84ba25bdb6631fbd3dd955424a227/packages/core/parcel-bundler/src/assets/CSSAsset.js#L96-L98
If that method is simply renamed to
pretransform
rather thantransform
postcss will be applied first, meaning that if a user specifiespostcss-import
in their.postcssrc
, then imports will be compiled away by postcss instead of being handled by parcel. If not, or there is no.postcssrc
, then parcel will handle the imports as it does today.Would someone like to prototype this and create a PR?
I recently discovered Parcel and used it from last couple days (itās great!) and Iām also banging my head around CSS issues. Hereās my 2 cents, specially after reading @devongovett comment:
Although clever, and desirable, this is not how CSS is generally processed. CSS is not JS and although PostCSS could come close (I donāt know enough about PostCSS), certainly LESS is not.
AFAIK CSS
@import
does not work like ES6import
. At least, not semantically. This is illustrated by the following LESS snippet:What would the processed
body { background: ??? }
be in this snippet? Well, the color isblue
processed with LESS andred
processed with SASS. (OK, SASS uses$
for variables, bear with me).In other words, although the snippet does not have any
@import
I think you get the point: variables in LESS are ālazyā processed, so they get the LAST assigned value even if it is assigned at the very end of the last.less
file. SASS on the other hand replaces variables with the value they had at that moment while processing.Both LESS and SASS require processing the whole thing anyway. LESS for obvious reasons: it requires a 2-pass compilation. But as a general rule of thumb CSS processors never had the notion of āscopesā so importing a CSS file does not open a new āscopeā or whatever. It is expected for a
.less
/.sass
file to get access to the āglobalā namespace, so to speak, so you donāt have to@import "variables"
in every single file.Found a counterintuitive fix for working with Tailwind (CC @aguilera51284)
.postcssrc.js
Going to close since this is working in Parcel 2.
@mischnic ideally, but I feel like if users are specifying to use postcss-import instead of the default parcel behavior then that is their problem not ours, so if we donāt support using parcelās resolver with postcss-import then thatās probably ok.
I was referring to a css file importing sass/less (though that could be done with some configuration).
I think we should only do this if there is some postcss configuration, to retain performance for āvanillaā CSS.
@devongovett
The CSS spec requires
@import
statements to be hoisted to the top of the file or they wonāt work. Iāve confirmed this in Chrome.By processing files independently, the
@import
statements get hoisted to the top of each individual chunk, but then they get concatenated and they are not hoisted in the resulting final CSS.The workaround for now is something like this:
This answer from @andreidcm worked super well for me! The difference was explicitly passing
preserve: false
to my postcss config, where originally CSS custom properties were not being replaced, I did ensure I passed theimportFrom
option too which was a path to myvars.css
file where all my custom properties were šOne issue is that, with this change, Parcel doesnāt know anything about the dependencies of a CSS file, and so HMR (and caching) for these doesnāt work anymore. We would first need to recursively search for imports and add these as a dependency before postcss runs (so parsing every CSS file twice).
hmm, does anyone manage to make it work, using @sj26 's
parcel-plugin-css-pretransform
?this is my .postcssrc file. the result is as without the plugin
Imports should be handled by postcss directly and not by Parcel!!
@mischnic The problem is that the postcss-import module is not executed in the way it should be, as imports are handled by Parcel, but only after the postcss transformation has been made!
See: https://github.com/parcel-bundler/parcel/issues/609#issuecomment-359428778
My current workaround is also @cmnstmntmn https://github.com/parcel-bundler/parcel/issues/1165#issuecomment-416218024
This is the same issue as CSS files being compiled with PostCSS before theyāre imported https://github.com/parcel-bundler/parcel/issues/609
The example code in the issue description works correctly with the current Parcel:
iām also facing a similar issue. iād like to use
postcss-mixins
, where a@define-mixin
happens infoo.css
, and the@mixin
happens inbar.css
(where@import './foo.css';
appears earlier). i cannot get this to work with parcel - i get anUndefined mixin
error.If parcel isnāt responsible for collecting and parsing the dependencies it doesnāt know about it resulting in the manual force recompiling. Not sure what even makes this work, are you using sass?
@irritant I admire your commitment to Parcel but I think at that point it might be easier to just use Gulp as the build tool or even plain Webpack. I have to make that decision myself since unfortunately I cant stop work waiting for this issue gets fixed, Parcel was really great for everything else though.