CSS预编译与PostCSS以及Webpack构建CSS综合方案

原文连接javascript

CSS全称Cascading Style Sheets(层叠样式表),用来为HTML添加样式,本质上是一种标记类语言。CSS前期发展很是迅速,1994年哈肯·维姆·莱首次提出CSS,1996年12月W3C推出了第一个正式版本。随后不到两年的时间,1998年5月便推出了第二个版本,一直沿用至今。可是CSS3的制订工做却迟迟没有完成。CSS3最初的草案在1999年便被提出,可是直到今日CSS3规范仍然有部分特性没有完成。若是说ES6与ES5相隔的6年时间让开发者们熬尽了心肝,那么从提案到发布相隔近20年光阴的CSS3能够说是千呼万唤始出来,并且犹抱琵琶半遮面。css

CSS的缺陷

CSS的初衷是为了弥补HTML原生样式的不足,早期对样式要求并不复杂的web网站仅仅须要少许的CSS代码便可。在现在web应用程序追求极致用户体验的潮流下,对CSS的要求也不断加强。复杂CSS开发是一件很是痛苦的事情,最主要的缘由是受限于浏览器的实现以及CSS自身的弱编程能力:html

  1. 浏览器实现不理想甚至实现方案各一。对CSS的兼容处理几乎是每一个前端工程师必备的技能,究其根本是浏览器对CSS规范的实现程度和方案不一。其中尤以IE浏览器最甚,包括以IE内核的众多国产浏览器。虽然目前绝大多数web应用已经不在兼容IE8如下浏览器,但IE8和IE9仍然让前端工程师们头疼不已;
  2. CSS的弱编程能力。CSS经过“selector-properties”的模式为HTML文档增长样式,简单的语法可让没有任何编程基础的初学者或者设计人员很快上手。但CSS不支持嵌套,甚至运算、变量、复用等这些几乎是编写复杂代码的必备特性。从CSS3引入了cal()以及处于草案阶段的var()能够隐约看出W3C有意增强CSS的编程能力;

开发者们不断探索着可以弥补这些缺陷的解决方案,CSS预编译器是第一种顺势而生的革命性方案。前端

CSS预编译

CSS预编译的工做原理是提供便捷的语法和特性供开发者编写源代码,随后通过专门的编译工具将源码转化为CSS语法。最先的CSS预编译器是2007年起源于Ruby on Rails社区的SASS,目前比较流行的其余CSS预编译器如Less、Stylus的诞生都必定程度上受到了SASS的影响和启发。java

CSS预编译器几乎成为现现在开发CSS的标配,它从如下几个方面提高了CSS开发的效率:webpack

  1. 加强编程能力;
  2. 加强可复用性;
  3. 加强可维护性;
  4. 更便于解决浏览器兼容性。

不一样的预编译器特性虽然有所差别,但核心功能均围绕这些目标打造,好比:web

  • 嵌套;
  • 变量;
  • mixin/继承;
  • 运算;
  • 模块化;

嵌套是全部预编译器都支持的语法特性,也是原生CSS最让开发者头疼的问题之一;mixin/继承是为了解决hack和代码复用;变量和运算加强了源码的可编程能力;模块化的支持不只更利于代码复用,同时也提升了源码的可维护性。编程

PostCSS

CSS预编译的理念与Babel有必定相通之处,最重要的区别是:预编译语法并不是规范的CSS,而是各成一派。由预编译语法编写的源代码不能在任何宿主浏览器中运行。从这个角度考虑,CSS预编译更像CoffeeScript、TypeScript等JavaScript子集。能够预见的是,若是将来CSS规范推出了预编译相似的特性和语法,这些预编译器都将成为历史的尘埃。PostCSS则反其道而行之,从理念上更加接近Babel,业内也有人将其称为“CSS的Babel”。浏览器

PostCSS鼓励开发者使用规范的CSS原生语法编写源代码,而后配置编译器须要兼容的浏览器版本,最后通过编译将源码转化为目标浏览器可用的CSS代码。PostCSS提供了丰富的插件用于实现不一样场景的编译需求,最经常使用的好比autoprefixer、sprites等,编译流程以下图所示:
前端工程师

PostCSS并非另外一种CSS预编译器,与SASS、Less等预编译器也并不冲突。PostCSS与Babel的不一样之处在于,它所支持的所谓“将来CSS语法”并非严格的CSS规范,其中大部分语法和特性目前只是CSS4的草案而已。不少人将PostCSS称为“CSS后编译器”,这个称谓能够必定程度上说明目前业界对PostCSS的广泛使用方案,请看下图:

即便是PostCSS支持的“将来CSS语法”也并不能彻底弥补CSS的缺陷,因此目前广泛的方案是将CSS预编译与PostCSS综合在一块儿:

  • 使用CSS预编译弥补CSS源码的弱编程能力,好比变量、运算、继承、模块化等;
  • 使用PostCSS处理针对浏览器的需求,好比autoprefix、自动css sprites等。

Webpack结合预编译与PostCSS实现CSS构建

经过Webpack配置项中的use指定的loader是按照索引反向执行,好比存在下述配置方案:

{
  test: /\.less$/,
  use: [
    'style-loader',
    'css-loader',
    'less-loader'
  ]
}

.less后缀类型的文件依次通过less-loadercss-loaderstyle-loader编译。在这种工做模式的基础上,结合图3-4所示的编译流程,使用Webpack结合CSS预编译与PostCSS的编译方案便一目了然了:

{
  test: /\.less$/,
  use: [{
    loader: 'style-loader',
    options: {} // style-loader options
  },{
    loader: 'css-loader',
    options: {
      importLoaders: 2 // css-loader options
    } 
  },{
    loader: 'postcss-loader',
    options: {} // postcss-loader options
  },{
    loader: 'less-loader',
    options: {} // less-loader options
  }]
}

上述配置中有如下须要注意的细节:

  1. css-loader中importLoaders选项的做用是用于配置css-loader做用于 @import 的资源以前须要通过其余loader的个数。@import 用于css源码中引用其余模块的关键字,若是你的项目中肯定不会涉及模块化能够忽略此配置项;
  2. 若是须要将编译后的css文件独立导出,则需将style-loader[注]替换为extract-text-webpack-plugin,以下:
{
  test: /\.less$/,
  use: ExtractTextPlugin.extract({
    filename: './dest/[name].[contenthash].css'
    use: [{
      loader: 'css-loader',
      options: {
        importLoaders: 2 // css-loader options
      } 
    },{
      loader: 'postcss-loader',
      options: {} // postcss-loader options
    },{
      loader: 'less-loader',
      options: {} // less-loader options
    }],
    publicPath: '/'
  })
}

注:不少开发者容易混淆css-loader和style-loader的做用。css-loader的做用是解析css源文件并获取其引用的资源,好比@import引用的模块、url()引用的图片等,而后根据Webpack配置编译这些资源。style-loader负责将css代码经过<style>标签插入html文档中,因此若是独立导出css文件就再也不须要style-loader。css-loader必须在style-loader以前执行。

相关文章
相关标签/搜索