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 (
            

css module test case

  • CompositionOverrides
  • GlobalSelectors
  • ScopedAnimations
  • ScopedSelectors
  • StyleVariantA
{this.props.children}
); } } 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使用方式。

参考文献

  • CSS Modules 入门及 React 中实践
  • CSS Modules 详解及 React 中实践
  • CSS Modules in React

你可能感兴趣的:(webpack css_module配置与使用)