Search code examples
csswebpackpostcss

How are `postcss-import` configured plugins applied


I've just started using PostCSS exclusively with Webpack. When using postcss-import to inline external stylesheets, I see it's options allow us to configure plugins and transformers to be applied on imported sources, but I'm a bit confused on how this fits in together with other options configured for the main PostCSS runner.

For instance, if I want to inline URLs, should I be adding the postcss-url plugin to postcss-import, the PostCSS runner or both (if my main stylesheet also has URL references)?


Solution

  • It's recommended to make postcss-import the first plugin in your list when you're defining the plugins for postcss in webpack. Since postcss-import just inlines the @import to the start of the file, any postcss plugin defined afterwards will be applied to it.

    Example:

    (For the example i'm gonna assume you use a postcss.config.js file, the same logic applies if you use an array for the plugins in the webpack 1 format)

    // Header.css
    @import 'button.css';
    
    .foo {
        font-size: 3rem;
        transform:translateY(-10px);
    }
    
    // Button.css
    
    .bar {
       transform:translateX(20px);
    }
    

    If the import plugin is behind autoprefixer, it will first apply the autoprefixer plugin on the file and then afterwards import the @import file. So by the time the file is imported the prefixing will have already happened, the output will be:

    // postcss.config.js
    module.exports = {
      plugins: {
        'autoprefixer': {},
        'postcss-import': {}
      },
    };
    
    // output.css
    .bar {
        transform: translateX(20px); // Prefixing hasn't happened on the imported file
    }
    .foo {
        font-size: 3rem;
        transform:translateY(-10px);
        -webkit-transform:translateY(-10px); // original file has been prefixed though
    }
    

    If you put the import first though, it will inline the imported file and then do the autoprefixing, this means both the imported and the original file will be autoprefixed:

    // postcss.config.js
        module.exports = {
          plugins: {
            'postcss-import': {},
            'autoprefixer': {}
          },
        };
    
    // output.css
    .bar {
        transform: translateX(20px);
        -webkit-transform:translateX(20px); // Also prefixed now
    
    }
    .foo {
        font-size: 3rem;
        transform:translateY(-10px);
        -webkit-transform:translateY(-10px); 
    }
    

    So this means you don't actually have to add plugins again in the option of the postcss-import plugin.