css-modules / postcss-icss-values

Pass arbitrary constants between your module files
MIT License
203 stars 18 forks source link

Work with other PostCSS plugins #5

Open pauldijou opened 8 years ago

pauldijou commented 8 years ago

Hoping I didn't do anything wrong, but I tried to use this plugin with some other PostCSS plugins and it failed when importing values.

For example, with postcss-calc, the expression is not evaluated...

/* size is 20px */
@value size from "./variables.css";
@value localSize: 20px;

.group {
  margin-top: calc(20px * 0.5);
  margin-bottom: calc(size * 0.5);
  margin-left: calc(localSize * 0.5);
  margin-right: calc(20px - localSize);
  padding-top: size;
  padding-bottom: localSize;
}

/* Render */
.group {
  margin-top: 10px;
  margin-bottom: calc(i__const_size_1 * 0.5);
  margin-left: 10px;
  margin-right: 0;
  padding-top: 20px;
  padding-bottom: 20px;
}

So, when used alone in padding-top, sizeis fine, but with the calc plugin, it fails with it's unique name or stuff. Same problem with colors:

.button:hover {
  background-color: color(#2c3e50 lightness(+10%));
}
/* render */
.button:hover {
  background-color: rgb(62, 87, 112);
}

/* and */
@value primary: #2c3e50;
.button:hover {
  background-color: color(primary lightness(+10%));
}
/* render */
.button:hover {
  background-color: rgb(62, 87, 112);
}

/* but */
@value primary from "./variables.css";
.button:hover {
  background-color: color(primary lightness(+10%));
}

Crashes the build with

ERROR in ./components/Button/style.css
Module build failed: ModuleBuildError: Module build failed: Error: .../css-modules/components/Button/style.css:15:3: Unable to parse color from string "i__const_primary_8"
    at .../css-modules/components/Button/style.css:15:3
    at Object.Color (.../css-modules/node_modules/postcss-color-function/node_modules/css-color-function/node_modules/color/color.js:31:15)
    at toRGB (.../css-modules/node_modules/postcss-color-function/node_modules/css-color-function/lib/convert.js:39:15)
    at Object.convert (.../css-modules/node_modules/postcss-color-function/node_modules/css-color-function/lib/convert.js:28:10)
    at transformColor (.../css-modules/node_modules/postcss-color-function/index.js:49:43)
    at transformColorValue (.../css-modules/node_modules/postcss-color-function/index.js:20:16)
    at Object.tryCatch [as try] (.../css-modules/node_modules/postcss-color-function/node_modules/postcss-message-helpers/index.js:53:12)
    at transformDecl (.../css-modules/node_modules/postcss-color-function/index.js:19:31)
    at .../css-modules/node_modules/postcss-loader/node_modules/postcss/lib/container.js:88:34
    at .../css-modules/node_modules/postcss-loader/node_modules/postcss/lib/container.js:73:26
    at Rule.each (.../css-modules/node_modules/postcss-loader/node_modules/postcss/lib/container.js:59:22)
    at DependenciesBlock.onModuleBuildFailed (.../css-modules/node_modules/webpack/node_modules/webpack-core/lib/NormalModuleMixin.js:315:19)
    at nextLoader (.../css-modules/node_modules/webpack/node_modules/webpack-core/lib/NormalModuleMixin.js:270:31)
    at .../css-modules/node_modules/webpack/node_modules/webpack-core/lib/NormalModuleMixin.js:292:15
    at context.callback (.../css-modules/node_modules/webpack/node_modules/webpack-core/lib/NormalModuleMixin.js:148:14)
    at .../css-modules/node_modules/postcss-loader/index.js:54:17
    at runMicrotasksCallback (node.js:314:7)
    at doNTCallback0 (node.js:407:9)
    at process._tickCallback (node.js:336:13)
 @ ./components/Button/index.js 25:16-38

Not sure what went wrong with the plugin chain, but it would be awesome to seamlessly integrate with any another PostCSS plugin.

geelen commented 8 years ago

Good catch! What's happening is those plugins are running before the ICSS imports are resolved, and they need to be run afterwards. I actually built this in a PR for media query support then bailed on it: https://github.com/css-modules/css-modules-loader-core/pull/18/files#diff-1fdf421c05c1140f6d71444ea2b27638R10

But you're right, this needs to find its way back into the loader. How have you been you running this, btw?

pauldijou commented 8 years ago

Here is my playground: https://github.com/pauldijou/css-modules

The failing cases are no longer in it, but that's the build I'm using. I did put the calc and color plugins after the modules-values ones here, but looks like it wasn't enough for all use cases.

geelen commented 8 years ago

Right, ok, so it looks like at the moment css-loader doesn't have any way to run PostCSS plugins after the load (before, say, the ExtractTextPlugin or the style-loader gets the content). Maybe @markdalgleish would be a good person to ping on this one, I think @sokra is still away on holidays.

ferdinandsalis commented 8 years ago

Hi @geelen, what is the status on this. Would love to use values, however I cant because of this issue. I really like css modules, great work!

geelen commented 8 years ago

Sorry, wrong issue number in my commit message

dfala commented 8 years ago

Any updates? This postcss modules sounds awesome but can't use it until this gets resolved. Thanks in advance!

timmolendijk commented 8 years ago

Same here.

As @geelen rightfully mentions, it is a problem that css-loader doesn't trivially allow you to run your PostCSS plugins after the compile step to ICSS.

But even if it would, things would still not work as expected.

Another example. Let's just assume we post-process the color function, in which case the CSS Modules parses as follows:

Works:

/* colors.css */

@value transparent-gray: color(#aaaaaa a(50%));

.iAmGray {
  /* Will work as expected */
  color: transparent-gray;
}

Breaks:

@value transparent-gray from './colors.css';

.iAmBroken {
  /* Will compile to: `color: color(#aaaaaa a(50%);` */
  color: transparent-gray;
}
timmolendijk commented 8 years ago

Btw, not all plugins should run after CSS Modules. A prime example being variables. In @geelen's CSS Module Values pull request he gives a compelling example of variables needing to be local (and therefore pre-processed).

Btw2, this problem with postcss-custom-properties makes it basically unusable with CSS Modules Values.

timmolendijk commented 8 years ago

I just found out that postcss-color-function does solely do a walkDecls and does not look at at-rules. This means that something like @value my-red: color(#ff0000 a(50%)); will simply be overlooked and never parsed into a plain color value.

Effectively the same situation applies to postcss-custom-properties, and I guess it's fair to expect others to exhibit similar behavior.

This is clearly a major reason why PostCSS and CSS Modules Values do not get along very well (yet).

epilande commented 8 years ago

Hi any updates to this issue?

MrOrz commented 8 years ago

I'm also having this issue.

There is a pull request by @Strate on css-loader that provides an option named afterModules, which allows us to chain postcss modules after css-loader completes CSS-module stuff. I have gave the PR a try and it worked beautifully.

In order to use the PR, edit package.json to load the PR branch:

"css-loader": "git+https://git@github.com/megaplan/css-loader#postcss_later_plugins",

And update your webpack config accordingly:

module.exports = {
  module: {
    loaders: [
      {
        test: /\.css$/,
        loader: 'style!css?modules&afterModules=executeAfterCSSModule',
      },
    ]
  },
  cssLoader: {
    executeAfterCSSModule(pipeline) {
      pipeline.use(require('postcss-calc'));
    },
  },
  // ...
}

Then postcss-calc can correctly turns this:

@value gap: 14px;
.wrapper {
  margin-bottom: calc(gap * -1);
}

into this:

@value gap: 14px;
.wrapper {
  margin-bottom: -14px;
}

@sokra Would you share with us any thoughts on Strate's PR?

sanpoChew commented 8 years ago

@MrOrz Thanks a lot for that, works like a charm. Hopefully the PR gets accepted at some point.

gregberge commented 8 years ago

Any updates? The PR has been rejected, so what to do?

princed commented 7 years ago

I wrote a workaround to overcome this flaw in ~CSS Modules~ css-loader?moduleshttps://github.com/princed/postcss-modules-values-replace. I'd love to have some feedback on it.

chrisvasz commented 7 years ago

@princed You just solved a major problem in our build process! Thank you -- that plugin is awesome!

joshwnj commented 7 years ago

related: #64

It works, as long as the postcss-calc plugin runs after the other CSS Modules plugins. There's an after option for this in https://github.com/css-modules/css-modulesify/, I haven't tried it with the other implementations (but https://github.com/princed/postcss-modules-values-replace looks like a great way to go)