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

Created on 18 Dec 2017  路  15Comments  路  Source: parcel-bundler/parcel

馃悰 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)

Bug Help Wanted CSS Preprocessing

Most helpful comment

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" />

All 15 comments

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

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.

Same for the postcss-partial-import plugin

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.

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'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" />

hey there,

any update on this issue?

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

Still not working properly ;(

I'm also having this issue with these plugins:

require('postcss-custom-properties'),
require('postcss-easy-import')

Can someone give an update on what the plan is to solve this issue, if any...?

I'm experiencing an issue that is almost certainly related to this.

@davidnagli @DeMoorJasper Are there any plans to fix this? It's a major bug that's affecting a lot of people.

Edit: As indicated below, this (along with a couple other bugs) are blocking me from moving over to Parcel. If this one _specifically_ is fixed, I could likely make the switch and lose an acceptable amount of functionality (temporarily).

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

We're considering switching from Webpack to Parcel but this is the one thing that is blocking us from doing so. Suprised to see this is still an issue since December 2017... how are folks managing to use Parcel + PostCSS when working with global variables across different css imports?

It's a pretty common thing to use postcss-import to process the import rules so all the css files are together, that way your global variables are all in the same scope/accessible, as are mixins etc. At the moment this workflow is completely broken with Parcel.

@devongovett @garthenweb do you have any plans on fixing this for current Parcel users? Is this fixed in v2? Would be great if this could be pushed up in priority.

@garygreen We had the same issue when migrating. Using a .sassrc.js with a data property solved the issue. Not sure if this will work nicely with css variables as it will most probably result in duplicate declarations in the final css bundle (we are only using scss variables and mixins in our project).

We just merged support for the data property in the v2 branch today. Not sure if there is/ will be a better way in the future.

The reason why this is not working is due to the architecture of parcel, there is no easy way to implement this as far as I am aware. Maybe the core team has more information.

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

edo-codes picture edo-codes  路  42Comments

jssee picture jssee  路  46Comments

garrydzeng picture garrydzeng  路  95Comments

mjrjoh picture mjrjoh  路  40Comments

Clickys picture Clickys  路  61Comments