全局css的终结——css module

@youngwind 2016-01-09 08:03:50发表于 youngwind/blog 其他

前言

长久以来,css的全局入侵性一直没得到有效的解决,反观js,早有Browserify和webpack等使代码变得模块化。问题的核心在于全局类的命名冲突上,幸好,webpack的css-loader提供了这样的一个解决方案,名字叫做 CSS Module

假设我们有大概下面这样的代码

// webpack.config.js
module: {
    loaders: [
      {test: /\.scss$/, loader: 'style!css!postcss-loader!sass?sourceMap'},
    ]
  },
// 组件 picker.js
var React = require("react");
require("./picker.scss");

var Picker = React.createClass({
  render: function () {
    var value = this.props.value;

    return (
        <h1 className="demo">{value}</h1>
    );
  }
});

module.exports = Picker;
//picker.scss 组件的样式
.demo {
  color: pink;
}

那么,最终渲染出来的DOM元素应该长这个样。
2016-01-09 4 02 59

如何应用css module?

// webpack.config.js
// 看到区别了吗?在于css-loader后面多了一些参数!
module: {
    loaders: [
      {test: /\.scss$/, loader: 'style!css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader!sass?sourceMap'},

    ]
  },
// 组件picker.js
var React = require("react");

// 区别在与这行!!
var styles = require("./picker.scss");

var Picker = React.createClass({
  render: function () {
    var value = this.props.value;
    return (
        // 还有这行!!如果有了解过react-native的肯定会发现这写法简直跟react-native如出一辙。
        <h1 className={styles.demo}>{value}</h1>
    );
  }
});

module.exports = Picker;
//picker.scss 组件的样式
// 没错,scss文件不需要任何修改
.demo {
  color: pink;
}

最后渲染的DOM元素是这样的。
2016-01-09 4 09 49
因为css最后被编译成下面的这样子了。
2016-01-09 4 11 14

结论

css module会确保每个类的全局唯一性,因此,给组件写样式的时候再也不用担心出现样式冲突了!
参考资料:

  1. https://github.com/css-modules/webpack-demo
  2. https://www.zhihu.com/question/34834178
  3. http://web.jobbole.com/83953/