csswebpackpostcsscss-variables

Could anyone please explain how to use postcss-preset-env's importFrom?


I'm trying to use Webpack+PostCSS. Here's the CSS config:

const cssRule = {
    test: /\.css$/,
    use: [
        'style-loader',
        {loader: 'css-loader'},
        {
            loader: 'postcss-loader',
            options: {
                plugins: [
                    postcssImport({
                        paths: ['./assets']
                    }),
                    postcssPresetEnv({
                        stage: 0,
                        browsers: 'Firefox ESR',
                        importFrom: ['./assets/shared/colors.css']
                    }),
                    postcssEasingGradients()
                ]
            }
        }
    ]
}

The assets/shared/colors.css file looks like this:

:root {
    --color-primary-0: #051845;
    --color-primary-1: #05112B;
    --color-primary-2: #041335;
    --color-primary-3: #092568;
    --color-primary-4: #0A328D;

    --color-primary-3-a20: #09256820;

    --color-secondary-1-0: #200446;
    --color-secondary-1-1: #16052C;
    --color-secondary-1-2: #190336;
    --color-secondary-1-3: #310769;
    --color-secondary-1-4: #42098F;

    --color-secondary-2-0: #004628;
    --color-secondary-2-1: #012C1A;
    --color-secondary-2-2: #00361F;
    --color-secondary-2-3: #006A3D;
    --color-secondary-2-4: #009153;

    --light-gray: #EEE;
    --dark-gray: #333;
}

But when I try using this colors, Firefox devtools complain that the variables are unset, and the actual colors are nowhere to be seen.

What am I doing wrong?


P. S. I also tried similar setup with Webpack css-loader's import, with exact same results...


Solution

  • Notice 2024

    As @le-markov noted, importFrom is deprecated. The thread noted has new PostCSS solution and alternative software to support importFrom. That software may have different instruction.

    Update 2021

    Consider my later, simpler, more up-to-date answer: https://stackoverflow.com/a/67610503/11817077

    Answers

    What am I doing wrong?

    There may not be a single answer. Try these.

    A. You are not exporting the variables. I suggest trying to import the variables you want to use, then export the variables. "Why export what you already have to import?!" I still ask myself this, but I have made progress by believing the following assumption:

    Based on my understanding, importing is for postcss-preset-env to apply static replacements and track where it cannot make a static replacement, while exporting is for postcss-preset-env to output variables that are necessary in the CSS for dynamic CSS behavior.

    B. Set the postcss-preset-env option preserve to true. Doing so should tell plugins to include "pre-polyfilled" CSS (like your missing variables). I have an opinion against this:

    Based on my understanding, the exportTo option allows postcss-preset-env to "pre-polyfill" the CSS, in order to improve performance of bundled CSS, while the preserve-set-to-false option provides all variables in the bundled CSS.

    C. Evaluate whether Webpack has unexpected behavior. Parcel 1.0 parses each CSS file independently, when bundling. Without a bundler (no Webpack, Parcel, Rollup, etc), I compiled functional code by both setting preserve to false and not using exportTo. See "Warning" section.

    Could anyone please explain how to use postcss-preset-env's importFrom?

    Maybe. You seem to be using importFrom correctly. But, you can try these steps for any of the above answers.

    Answer A

    1. Provide, via importFrom, the variables that you want available to postcss-preset-env (while it parses your CSS).
    2. Define, via exportTo, where to create a CSS file that you want to be included in your final CSS.
    3. Include the exported CSS in the final CSS.

    Answer B

    1. Test whether setting postcss-preset-env option preserve to false or true resolves the issue.

    Answer C

    1. Test PostCSS independently of Webpack. I recommend postcss-cli.

    Warning

    The success rate of postcss-preset-env, using the imported variables and deciding the variables necessary to export, is dependent on:

    The plugin test cases do not test order from files; the import test tests only a single order from simple objects with basic usage.

    The details of the order elude me. More complex test cases may be required.

    My Experience Using Parcel (Not Webpack)

    Different loader, but same plugin.

    1. If the format of these variable sources are file paths in an array, then order matters:
      • custom selectors
      • environmental variables
    2. Placing either of those two variable source first will make the other ineffectual.
    3. If those two variable source formats are one JavaScript object and one file path, then order matters.
    4. If those two variable source formats are both JavaScript objects, then order does not matter.
    5. The order of other variable sources, if from files, seems irrelevant.

    Reference

    1. postcss-preset-env Issue #141: "Confused about importFrom and the expected output"
    2. Personal trial and error, and some systematic testing.
    3. The postcss-preset-env test cases do not cover the examples shown in the documentation.
    4. Reading my pulled-out clumps of hair as if they are oracle bones. 🤪