webpack css_module配置与使用

本文主要是基于webpack+es6+react关于css module脚手架的搭建。可以从css_module_demo下载相关案例,本文拟从4种可能的情形配置启动css_module。

css_module

css module最简单的情形,只需要在css-loader启动css module配置即可。

webpack css-loader

module: {
     rules: [{
         test:  [/\.js$/, /\.jsx$/, /\.es6$/],
         include: [
           path.resolve(__dirname, 'src'),
         ],
         use: {
           loader: "babel-loader"
         },
       }, {
         test: [/\.css/],
         exclude: path.resolve(__dirname, 'src/styles/global'),
         use: [
           'style-loader',
           {
             loader: 'css-loader',
             options: {
                 modules: true,
                 localIdentName: '[name]__[local]-[hash:base64:5]'
             }
           }
         ]
      }, {
        test: [/\.css/],
        include: path.resolve(__dirname, 'src/styles/global'),
        use: [
          'style-loader',
          'css-loader'
        ]
      }]
   },

一般项目中,会有normalize.css或者global.css全局css样式,此时若不需要处理,可以配置两种css的管理方式。具体的使用方法,可参照css_module_demo demo1的配置。

css_module + less\scss

若需要配合less、scss编辑器,配置与css-loader类似,在css、less相关配置中设置如下即可.

  ...
    {
         test: [/\.css$/, /\.less$/],
         exclude: path.resolve(__dirname, 'src/styles/global'),
         use: [
           'style-loader',
           {
             loader: 'css-loader',
             options: {
                 modules: true,
                 localIdentName: '[name]__[local]-[hash:base64:5]'
             }
           },
           {
             loader: 'postcss-loader',
             options: {
               ident: 'postcss',
               plugins: (loader) => [
                 require('postcss-import')({ root: loader.resourcePath }),
                 require('postcss-cssnext')(),
                 require('autoprefixer')(),
                 require('cssnano')()
               ]
             }
           },
           'less-loader'
         ]
      }, {
        test: [/\.css$/, /\.less$/],
        include: path.resolve(__dirname, 'src/styles/global'),
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: (loader) => [
                require('postcss-import')({ root: loader.resourcePath }),
                require('postcss-cssnext')(),
                require('autoprefixer')(),
                require('cssnano')()
              ]
            }
          },
          'less-loader'
        ]
      }
...

这样我就可以使用less的功能了,如我们在app.less中

.global {
  text-align: left;
  font-size: 20px;
  composes: box from "../styles/views/layout.less";
  .title {
    font-size: 22px;
    color: red;
  }
  .title:before {
    content: 'before i come'
  }
  .title:hover {
    font-size: 40px;
  }
}

但是css module中,不能在子选择器中使用compose,如我们在title中定义composes

.global {
  text-align: left;
  font-size: 20px;
  composes: box from "../styles/views/layout.less";
  .title {
    font-size: 22px;
    composes: heading from "../styles/views/typography.less";
    color: red;
  }
  .title:before {
    content: 'before i come'
  }
  .title:hover {
    font-size: 40px;
  }
}

会提示类似如下的错误

ERROR in ./node_modules/.0.28.7@css-loader?{"modules":true,"localIdentName":"[name]__[local]-[hash:base64:5]"}!./node_modules/.2.0.8@postcss-loader/lib?{"ident":"postcss"}!./node_modules/.4.0.5@less-loader/dist/cjs.js!./src/components/app.less
Module build failed: Error: composition is only allowed when selector is single :local class name not in ":local(.global) :local(.title)"

css module作者在issues/261中提到“Composition works differently to mixins. It does not mutates rules, just concatenates names.”

css_module + react-css-modules

在每个样式中都是style.*中的形式比较麻烦,可以使用react-css-modules解决这种问题。例如在app.js中

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import CSSModules from 'react-css-modules';
import { Link } from 'react-router-dom';
import styles from './app.less'
class App extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div styleName='global'>
                <h1 styleName='title'>css module test case</h1>
                <ul role="nav" styleName='nav'>
                    <li><Link to="/CompositionOverrides">CompositionOverrides</Link></li>
                    <li><Link to="/GlobalSelectors">GlobalSelectors</Link></li>
                    <li><Link to="/ScopedAnimations">ScopedAnimations</Link></li>
                    <li><Link to="/ScopedSelectors">ScopedSelectors</Link></li>
                    <li><Link to="/StyleVariantA">StyleVariantA</Link></li>
                </ul>
                {this.props.children}
            </div>
        );
    }
}
export default CSSModules(App, styles)

react-css-modules缺点是是需要运行时的依赖,而且需要在运行时才获取className,性能损耗大。在比较大的项目中,会导致较大的延迟。那么这个问题怎么解决那,可以使用bable-plugins-react-css-modules 把className获取前置到编译阶段。

css_module + bable-plugins-react-css-modules

bable-plugins-react-css-modules与react-css-modules是同一个作者开发的工具,bable-plugins-react-css-modules相对于react-css-modules,在性能方面有了较大的提高。
bable-plugins-react-css-modules有两种配置方式,一是配置在webpack.config.js,二是配置在.babelrc中,本文采取的方式是配置在webpack.config.js中。

       ...
       {
       test:  [/\.js$/, /\.jsx$/, /\.es6$/],
         include: [
           path.resolve(__dirname, 'src'),
         ],
         use: {
           loader: "babel-loader",
           options: {
             cacheDirectory: true,
             plugins: [
               [ "react-css-modules", {
                 context: path.resolve(__dirname, "src"),
                 "generateScopedName": "[path][name]__[local]--[hash:base64:5]"
               }]
             ]
           }
         },
       }
      ...

总结

css module具有灵活性、易移植的优点,可以配合less、scss等多种css编译器使用。本文依赖于webpack css-loader,配置了css module、css module + less\scss、css module+react-css-modules、css module + babel-plugin-react-css-modules等四种css_module使用方式。

参考文献

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容

  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,133评论 7 35
  • GitChat技术杂谈 前言 本文较长,为了节省你的阅读时间,在文前列写作思路如下: 什么是 webpack,它要...
    萧玄辞阅读 12,663评论 7 110
  • 学习流程 参考文档:入门Webpack,看这篇就够了Webpack for React 一. 简单使用webpac...
    Jason_Zeng阅读 3,104评论 2 16
  • 衣服风格能反映一个人的生活态度,也能决定一个人的第一印象。毫无疑问,简单淡雅的人一定不会穿有太多颜色的衣服,对...
    渔舟舟爱看花阅读 489评论 2 5
  • 睁开明亮的双眼,除去睡意的干扰,舒展美丽的笑容,拥抱快乐的一天,大家好,我是你们的老朋友“手抓饼”愿新的一天你们工...
    junlingyurui阅读 296评论 2 2