parcel: Not working when using "postcss-import" with "postcss-next".

🐛 bug report

🎛 Configuration (.babelrc, package.json, cli command)

.postcssrc

{
    "plugins": {
        "postcss-import": {},
        "postcss-cssnext": {}
    }
}

CLI

$ parcel build app.js

app.js

import './app.css';

app.css

@import "./css/root.css";
@import "./css/body.css";

root.css

:root {
    --font: 'Helvetica';
}

body.css

body {
    font-family: var(--font);
}

You can make this problem with this attachment. You can do $ yarn run start worked.zip

🤔 Expected Behavior

Postcss

:root {
 --font: 'Helvetica';
}

body {
 font-family: var(--font);
}

Exported CSS

body {
 font-family: 'Helvetica';
}

😯 Current Behavior

Exported CSS

/* no root pseudo-class */
body {
 font-family: var(--font);
}

💁 Possible Solution

This setting is working great when using webpack + postcss-loader.

🔦 Context

I tried changing the syntax of postcss setting file though there is no hope.

🌍 Your Environment

Software Version(s)
Parcel 1.2.0
Node 9.3.0
npm/Yarn Yarn 1.3.2
Operating System Arch Linux (macOS High Sierra 10.13.2)

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 15
  • Comments: 15 (4 by maintainers)

Most upvoted comments

Any update on the above issues and getting postcss support working with parcel? @davidnagli @devongovett … it’s the only thing preventing us from going all-in on parcel for a new project.

I’m just using postcss-cli together with parcel, gets the job done 😉 I understand that this doesn’t help to solve the actual problem described in this issue and definitely isn’t a zero-config solution, but can be a workaround for others who may come here e.g. from google. I’ve tried patching parcel-bundler as @irritant suggested, but this didn’t work for my case (I’m using a couple of plugins and tailwindcss).

Here is basically what I do now:

package.json:

"postcss:watch": "postcss styles/app.css -o css/app.css --watch",
"parcel:serve": "parcel index.html -p 3100",
"start": "run-p postcss:watch parcel:serve",

styles/app.css:

@import "tailwindcss/preflight";
@import "./main.css";
@import "tailwindcss/utilities";

postcss.config.js:

module.exports = {
  plugins: [
    require("postcss-easy-import"),
    require("tailwindcss")("./tailwind.js"),
    require("postcss-nested"),
    require("autoprefixer"),
  ]
}

index.html:

<link href="css/app.css" rel="stylesheet" />

I created a fork to use for testing: https://github.com/irritant/parcel

Use the postcss-import-fix branch:

yarn add https://github.com/irritant/parcel.git#postcss-import-fix --dev
cd ./node_modules/parcel-bundler
yarn install

I have some additional information about this issue. I don’t know very much about Parcel’s implementation but I read through src/assets/CSSAsset.js and I think I know what’s causing this:

  1. The collectDependencies method on CSSAsset walks the import rules in each CSS file and sets up a dependency tree.
  2. The files listed in the dependency tree are passed to postcss, which processes them individually before concatenating them.
  3. Any variables declared in other files are ignored because they are not in scope until after concatenation.

Step 1 seems to be the problem. If CSSAsset doesn’t walk the imports, postcss-import (or whatever import plugin you prefer) should handle the imports properly and the rest of your postcss plugins should work.

I tested this locally by commenting out lines 31-58 of src/assets/CSSAsset.js (lib/assets/CSSAsset.js if you’re using Node < 8), so collectDependencies looks like this:

collectDependencies() {
    /*
    this.ast.root.walkAtRules('import', rule => {
      let params = valueParser(rule.params).nodes;
      let [name, ...media] = params;
      let dep;
      if (name.type === 'string') {
        dep = name.value;
      } else if (
        name.type === 'function' &&
        name.value === 'url' &&
        name.nodes.length
      ) {
        dep = name.nodes[0].value;
      }

      if (!dep) {
        throw new Error('Could not find import name for ' + rule);
      }

      if (PROTOCOL_RE.test(dep)) {
        return;
      }

      media = valueParser.stringify(media).trim();
      this.addDependency(dep, {media, loc: rule.source.start});

      rule.remove();
      this.ast.dirty = true;
    });
    */
    this.ast.root.walkDecls(decl => {
      if (URL_RE.test(decl.value)) {
        let parsed = valueParser(decl.value);
        let dirty = false;

        parsed.walk(node => {
          if (
            node.type === 'function' &&
            node.value === 'url' &&
            node.nodes.length
          ) {
            let url = this.addURLDependency(node.nodes[0].value, {
              loc: decl.source.start
            });
            dirty = node.nodes[0].value !== url;
            node.nodes[0].value = url;
          }
        });

        if (dirty) {
          decl.value = parsed.toString();
          this.ast.dirty = true;
        }
      }
    });
  }

Here is my extremely basic test case:

colors.css:

:root {
  --black-color: #000000;
}

main.css:

body {
  font-family: Helvetica, sans-serif;
  color: var(--black-color);
}

index.css:

@import './colors.css';
@import './main.css';

The CSS generated by Parcel 1.5.1 is:

body {
  font-family:Helvetica, sans-serif;
  color:var(--black-color);
}

This is similar to @nakoo’s results in the original post and is clearly not what we would expect.

The CSS generated with the modified collectDependencies is:

body {
  font-family:Helvetica, sans-serif;
  color:#000000;
}

As I said at the top of this comment, I don’t know enough about Parcel to know whether or not this is a good solution. In my extremely limited testing it solved the problem raised by this issue but it may break other things. I can’t say, but hopefully the community can and will weigh in on this.

Wow this is a legitamite problem, we definitely need to get this fixed. Thanks for reporting this!

Hi guys, same question as above, any news on this?

@garygreen

The css import problem (https://github.com/parcel-bundler/parcel/issues/1165) is already fixed in Parcel 2, because now the PostCSS transform is ran before imports are handled by Parcel. (Apart from a caching problem reported in https://github.com/parcel-bundler/parcel/pull/3980)

I’ve just tested the example in the original issue description and it works correctly with Parcel 2.

Feel free to report any problems or suggestions you have.

I have the same problem while using tailwindcss. I think the developers now want to focus on the development of parcel 2, that’s why this may not be their top priority