PostCSS plugins are not applied correctly during `vite build`
Describe the bug
When running vite build with a postcss.config.cjs file in the project, I would expect postcss plugins to run before the final style.css file is created in dist/.
Example:
- final
dist/style.css
.btn {
align-items: center;
color: #ff0;
display: flex;
justify-content: center
}
.modal {
align-items: center;
color: red;
display: flex;
justify-content: center
}
.box {
align-items: center;
color: blue;
display: flex;
justify-content: center
}
- after manually running
postcss dist/styles.css -o dist/styles.css
.btn {
color: #ff0
}
.btn,
.modal {
align-items: center;
display: flex;
justify-content: center
}
.modal {
color: red
}
.box {
align-items: center;
color: blue;
display: flex;
justify-content: center
}
Reproduction
https://github.com/floroz/vite-css-module-treeshakable
Steps to reproduce
-
pnpm install -
pnpm build - inspect
dist/style.cssoutput - run
pnpm postcss(will invokepostcssCLI on the samedist/style.css) - inspect
dist/style.cssoutput (optimisations are applied)
System Info
- node 18.12
- sass 1.61
- postcss 8.4
- vite 4.2.1
Used Package Manager
pnpm
Logs
No response
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to vuejs/core instead.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [X] The provided reproduction is a minimal reproducible example of the bug.
I wanted to extend a bit my initial description as I noticed also an issue coming from the sass compilation, where %placeholders are expanded into individual style declaration, rather than collapsing class selectors together.
So there seems to be two issues with this pipeline:
-
sasscompilation of%placeholderswithin*.vue(or*.scssfile consumed via*.vue) create duplicate style declaration; -
postcssplugins are not fully applied untilpostcss-cliis run manually on final putput
This is because style in every vue files is transformed individually and so does cssnano. So not possible for merging styles from different files by cssnano. This seems to be a bug for me as we may perform postcss on renderChunk in build mode.
Thanks for the reply @fi3ework.
This is because style in every vue files is transformed individually and so does cssnano.
Is this by design? If I create .scss files, shouldn't they be combined before being transformed so that pre-processors can apply their optimizations? (i.e. placeholder collapsing?).
So not possible for merging styles from different files by cssnano. This seems to be a bug for me as we may perform postcss on
renderChunkin build mode.
Not clear on this point, is this a genuine bug that requires fixing, and therefore the expected behaviour is to have postprocessor optimization run after all stylesheets have been merged together?
Do you know if there is any workaround to apply transformations after styles are combined together?
@floroz Similar to https://github.com/vitejs/vite/issues/7504 https://github.com/vitejs/vite/issues/12400, and the workaround is quite similar to https://github.com/vitejs/vite/issues/12400#issuecomment-1468740126.
#7504
Thank you @fi3ework for the resources. Will check and verify those workarounds but it seems they still target the ability to apply postprocessing transformation, which would still invalidate the initial transformation done by sass?
Also, using a enforce: "post" isn't that different from manually executing postcss CLI after the vite build, as presented in my reproduction. (unless there are benefits I am not seeing?).
Could I tap into your knowledge (and slightly outside the boundary of this issue) to ask whether using rollup directly without vite could potentially resolve this issue (I suppose at that point the question is with the rollup-vue-plugin)?
Any update on this? Will this be fixed in v4?
@pcoterecollective
Any update on this? Will this be fixed in v4?
I've experienced such problem too. I've decided for the time being just to create vite plugin which runs postcss after bundle was generated. If you want to mitigate this for now, put this into your vite config plugins section:
Note: This only works with manually imported assets. If you have something like tailwind, this wouldnt work!
{
"name": "vite-bundle-postcss",
async generateBundle (_, bundle) {
for (const output of Object.values(bundle)) {
if (output.type !== "asset" || !output.fileName.endsWith(".css")) {
continue;
}
output.source = (await postcss([
// your plugins here:
cssnano()
]).process(output.source)).css;
}
}
}