vite icon indicating copy to clipboard operation
vite copied to clipboard

PostCSS plugins are not applied correctly during `vite build`

Open floroz opened this issue 2 years ago • 7 comments

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.css output
  • run pnpm postcss (will invoke postcss CLI on the same dist/style.css)
  • inspect dist/style.css output (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

floroz avatar Apr 09 '23 15:04 floroz

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:

  • sass compilation of %placeholders within *.vue (or *.scss file consumed via *.vue) create duplicate style declaration;
  • postcss plugins are not fully applied until postcss-cli is run manually on final putput

floroz avatar Apr 11 '23 08:04 floroz

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.

fi3ework avatar Apr 12 '23 18:04 fi3ework

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 renderChunk in 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 avatar Apr 13 '23 06:04 floroz

@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.

fi3ework avatar Apr 13 '23 15:04 fi3ework

#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)?

floroz avatar Apr 14 '23 14:04 floroz

Any update on this? Will this be fixed in v4?

pcoterecollective avatar May 30 '24 12:05 pcoterecollective

@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;
    }
  }
}

Dovias avatar Sep 14 '24 18:09 Dovias