vite icon indicating copy to clipboard operation
vite copied to clipboard

PostCSS not applied to imports via `composes`

Open elisehein opened this issue 1 year ago • 4 comments

Describe the bug

I'm trying to have styles included in a CSS module via composes processed by PostCSS, but it's not happening. All other styles are processed by PostCSS correctly.

Take the following CSS modules and PostCSS config:

{
  "plugins": {
    "postcss-preset-env": {
      "browsers": "defaults, ie >= 11",
      "importFrom": [
        "./src/variables.css"
      ]
    },
    "postcss-nested": { }
  }
}
/* variables.css */
:root {
  --color-red: red;
  --color-blue: blue;
}

/* component.module.css */
.component {
  color: var(--color-red);

  .nested {
    width: 100%;
  }
}

/* main.module.css */
.main {
  composes: component from "./component.module.css";
  color: var(--color-blue);

  .nested {
    display: block;
  }
}

Expected result

I exect to see the styles I include with .main via `composes: component from "./component.module.css" to be valid (with PostCSS plugins applied). Expected result:

 ._component_xs2hm_5 {
  color: red;
  color: var(--color-red);
 }

 ._component_xs2hm_5 ._nested_xs2hm_13 {
  width: 100%;
}

._foo_1mrk0_1 {
  color: blue;
  color: var(--color-blue);
}

._foo_1mrk0_1 ._nested_1mrk0_7 {
  width: 100%;
}

Actual result

The styles included via composes are not processed by PostCSS. They are included in the <style> tag as-is, resulting in invalid CSS.

 ._component_xs2hm_5 {
  color: var(--color-red);

  ._nested_xs2hm_13 {
    width: 100%;
  }
}

._foo_1mrk0_1 {
  color: blue;
  color: var(--color-blue);
}

._foo_1mrk0_1 ._nested-bar_1mrk0_7 {
  width: 100%;
}

The same bug can be observed in the production build.

There was a similar issue logged and fixed in vue-loader: https://github.com/vuejs/vue-loader/issues/959

Reproduction

https://github.com/elisehein/vite-postcss-compose-repro

System Info

System:
    OS: macOS 12.4
    CPU: (10) arm64 Apple M1 Pro
    Memory: 721.78 MB / 32.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.16.0 - ~/.asdf/installs/nodejs/16.16.0/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 8.15.0 - ~/.asdf/plugins/nodejs/shims/npm
    Watchman: 2022.05.16.00 - /usr/local/bin/watchman
  Browsers:
    Firefox: 103.0.2
    Safari: 15.5
    Safari Technology Preview: 15.4
  npmPackages:
    @vitejs/plugin-legacy: ^1.8.2 => 1.8.2 
    @vitejs/plugin-react: ^1.0.0 => 1.3.2 
    vite: ^3.0.2 => 3.1.0

Used Package Manager

npm

Logs

No response

Validations

elisehein avatar Sep 12 '22 07:09 elisehein

Vite puts postcss plugins in the following order.

[postcssImport, postcssModules, ...userPlugins, postcssViteRewriteUrl]

In this order ([postcssModules, postcssNested]), the output is:

._component_8abi2_1 {
  color: var(--color-red);

  ._nested_8abi2_7 {
    width: 100%;
  }
}

._foo_15itx_1 {
  color: red;
}

But when the order is [postcssNested, postcssModules], the output is:

._component_8abi2_1 {
  color: var(--color-red);
}._component_8abi2_1 ._nested_8abi2_7 {
    width: 100%;
  }._foo_15itx_1 {
  color: red;
}

stackblitz

So I think we need an option to apply a plugin before default ones, or reorders the plugins.

sapphi-red avatar Sep 12 '22 12:09 sapphi-red

We had a related PR to change the order of PostCSS plugins, and have the user ones before the internal ones:

  • https://github.com/vitejs/vite/pull/7186

In that case, it was closed because the issue should have been fixed upstream. But it could count as another case where having the chance to inject plugins before Vite plugins could have been useful. Maybe we could have a { order: 'pre', ...plugin } for PostCSS plugins too?

patak-dev avatar Sep 12 '22 15:09 patak-dev

I took a look around postcss plugin specs. Maybe it's possible to solve on plugins' side?

https://github.com/postcss/postcss/releases/tag/8.0.0#:~:text=Plugins%20will%20re%2Dvisit%20changed%20nodes%20to%20reduce%20compatibility%20issues%20between%20plugins.%20Now%20the%20order%20of%20plugins%20in%20your%20PostCSS%20config%20will%20be%20less%20important. #764 #296

I feel it's better to avoid extending the plugin interface of PostCSS.

sapphi-red avatar Sep 13 '22 10:09 sapphi-red

Another point in favor of waiting here is that there is a chance we end up replacing PostCSS with LigthingCSS in the future

patak-dev avatar Sep 13 '22 12:09 patak-dev

Another point in favor of waiting here is that there is a chance we end up replacing PostCSS with LigthingCSS in the future

Any news on when this will happen? I'm deciding if it's worth waithing for a fix to this issue or just go with plain old css :)

basmilius avatar Oct 03 '22 13:10 basmilius