什么是PostCSS

PostCSS是一款拥有非常灵活的插件机制的CSS预处理工具。 可以通过编写插件来实现具体的预编译功能,如变量声明、mixin等。

默认使用插件

Reduce通过使用reduce-css-postcss来支持PostCSS。 默认使用如下PostCSS插件来支持SASS风格的样式源码编写:

@import v.s. @external

@importpostcss-simple-import处理,在预处理中起作用,影响编译结果。

譬如下面的情况中,在预处理时,必须将vars.css中的内容插入到a.css中相应位置,后者才能处理成预期的结果。

/* vars.css */

$red: #ff0000;
$green: #00ff00;
$blue: #0000ff;
/* a.css */

@import "./vars.css";
a {
  color: $red;
}

预处理结果:

a {
  color: #ff0000;
}

@external只是依赖声明。 在预处理后,进行依赖解析时可确定模块之间的依赖关系,影响打包结果。

如果将上面例子中的@import换成@external,则将a.css打成包后结果为:

a {
  color: $red;
}

这是因为在预处理a.css时,并未引入变量的定义。 同时在打包时,虽然a.css依赖了vars.css,但vars.css的预处理结果为空字符串,没有任何内容。

下面是一个正确使用@external的例子。

/* a.css */

@external "reset";
a {
  color: red;
}
/* b.css */

@external "reset";
b {
  color: green;
}
/* reset.css */

a, b {
  color: black;
}

打成一个包的配置:

{
  css: {
    bundleOptions: 'bundle.css',
  },
}

结果:

/* bundle.css */

a, b {
  color: black;
}

a {
  color: red;
}

b {
  color: green;
}

打成多个包的配置:

{
  css: {
    bundleOptions: {
      // 分别以a.css和b.css为入口生成两个包
      groups: ['a.css', 'b.css'],
      // 提取a.css和b.css的公共依赖,生成第三个包
      common: 'c.css',
    },
  },
}

结果:

/* 必须在a.css和b.css加载前先加载c.css */

/* a.css */
a {
  color: red;
}

/* b.css */
b {
  color: green;
}

/* c.css */
a, b {
  color: black;
}

区别小结

  • @external的目标文件是预处理后的内容,所以一定是要有具体CSS的才有意义。
  • @import的目标文件是预处理中的辅助内容,一般是变量定义、mixin等。

url变换

由于@import@external的影响,文件内容最终出现打包结果中时,url()中的相对路径需要做一些调整。 这主要由postcss-custom-url完成。

在Reduce中,默认情况下小于10k的资源将以base-64的形式内嵌,其它则根据配置进行相应的拷贝。

可以在配置中修改这个上限。

{
  css: {
    // 小于5k的资源被inline
    // 其余的拷贝到/path/to/assets
    dest: ['/path/to/dest', null, { maxSize: 5, assetOutFolder: '/path/to/assets' }],
  }
}

修改插件列表

添加插件

直接指定需要添加的插件列表:

{
  css: {
    reduce: {
      postcss: creators,
    },
  },
}

creators

Type: Array

每个元素可以有以下三种形式(以postcss-modules为例)

  • require('postcss-modules')
  • require('postcss-modules')(opts)
  • [require('postcss-modules'),opts]

更复杂的操作

指定函数操作pipeline对象。

{
  css: {
    reduce: {
      postcss: pipeline => {
        // 使用postcss-simple-vars代替postcss-advanced-variables
        pipeline.splice('postcss-advanced-variables', 1, require('postcss-simple-vars'))

        var creator = pipeline.get('autoprefixer')
        // 给autoprefixer指定配置
        creator[1] = { add: false, browsers: [] }
      },
    },
  },
}