# CSS处理

# 样式处理

Webpack处理css,需要借助:

  • css-loader:让webpack认识css文件;
  • style-loader:把webpack处理完的css加载到html中,相当于是<style>引入;
  • Less-loader,scss-loader等:把scss,less这些语言转化为css;

所以,这三者的使用顺序是:style-loader, css-loader, scss-loader,webpack中是顺序使用,逆序书写

# css-loader

首先添加 css-loader:

npm install --save-dev css-loader
# or
npm i -D css-loader

然后给webpack.config.js添加rule

{
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['css-loader']
      }
    ];
  }
}

这时候修改app.js 添加下面代码:

import css from './css/index.css';
console.log(css, css.toString());

效果如下: 图片描述

这时候 CSS 会被转成字符串, JS 就可以直接使用。

除了上面直接在webpack.config.js中添加rule,还可以在 JavaScript 中直接使用下面的方式引入:

import css from 'css-loader!./css/index.css';
console.log(css);

上面代码中import css from 'css-loader!./css/index.css'是 webpack loader 的内联写法。

# style-loader

有了 css-loader 可以识别 CSS 语法了,下面就需要 style-loader 出场了。简单来说,style-loader 是将 css-loader 打包好的 CSS 代码以<style>标签的形式插入到 HTML 文件中,所以style-loader是和css-loader成对出现的,并且style-loader是在css-loader之后。首先安装style-loader

npm install --save-dev style-loader
# or
npm i -D css-loader

# 预处理器loader

由于 CSS 标准自诞生以来,一直致力于在表现力层面的发展,相对基本语法和核心机制并没有实质性的变化,所以产生了好多 CSS 的预处理器。预处理器补足了 CSS 的一些语法上的缺陷,支持变量、运算、函数、作用域、继承、嵌套写法等,使用 CSS 预处理器可以大大的提升开发效率和体验,同时能够更好的做好模块化开发。

Tips:CSS 核心语法直到近些年才有大的发展,比如自定义属性(custom properties,又称为变量 variables) 、嵌套写法,但是已经远远的落后于 CSS 预处理器的发展。

常见的 CSS 预处理器有:Less (opens new window)Sass 及其语法变种 Scss (opens new window)Stylus (opens new window)

下面以 Less 预处理器为例,介绍 CSS 预处理器的用法。首先安装对应的 loader:less-loader (opens new window)

npm i -D less-loader
# or
npm install less-loader --save-dev

然后修改webpack.config.js

// webpack.config.js
module.exports = {
  //   ...
  module: {
    rules: [
      {
        test: /\.less$/,
        loader: 'less-loader' // 将 Less 编译为 CSS
      }
    ]
  }
};

less-loader只是将 Less 语法编译成 CSS,后续还需要使用css-loaderstyle-loader处理才可以,所以一般来说需要配合使用:

// webpack.config.js
module.exports = {
  //   ...
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          },
          'less-loader' // 将 Less 编译为 CSS
        ]
      }
    ]
  }
};

注意一些预处理语言需要安装对应的解析器,例如 sass-loader,需要同时安装 node-sass:npm install sass-loader node-sass --save-dev

# 扩展1:mini-css-extract-plugin

CSS 作为<style>标签放到 HTML 内还是不够的,还需要将 CSS 以<link>的方式通过 URL 的方式引入进来,这时候就需要使用mini-css-extract-plugin (opens new window)这个插件了,首先安装它:

npm install --save-dev mini-css-extract-plugin

mini-css-extract-plugin这个使用的时候需要分别配置 loader 和 plugin,loader 需要放在css-loader之后代替style-loader

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  plugins: [
    // 添加 plugin
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css'
    })
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        // 添加 loader
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  }
};

# 扩展2:CSS Modules(React风格)

CSS Modules 指的是所有的 CSS 类名及其动画名都只是局部作用域的 CSS 文件。

CSS Modules 既不是官方标准,也不是浏览器的特性,而是在构建过程中对 CSS 类名选择器限定作用域的一种方式,如的广告样式、某个 UI 通用弹层 SDK 这类样式,都需要避免自己的命名跟宿主环境的样式冲突或者避免被 AdBlock (opens new window) 这类广告拦截器拦截掉。

CSS Modules 主要解决的问题有:

  1. 解决 CSS 类都是全局的,容易造成全局污染(样式冲突);
  2. JS 和 CSS 共享类名;
  3. 可以方便的编写出更加健壮和扩展方便的 CSS。

这类 CSS 模块化的解决方案很早之前前端社区就有一些讨论和方案,比如最早的通过 CSS 命名约定的BEM (opens new window)OOCSS (opens new window)等,再到 React 中使用的用 JavaScript 来写 CSS 规则的 CSS in JS (opens new window) 方案,再到通过编译工具来帮助 JavaScript 可以使用 CSS 的 CSS Modules 方案。

下面来看下 CSS Modules 究竟是什么,来看下代码表现,首先创建一个app.css文件,内容如下:

/* app.css */
.element {
    background-color: blue;
    color: white;
    font-size: 24px;
}

知道了,在 JS 中可以直接import一个 CSS 文件:

// app.js
import styles from './app.css';

那么 CSS Modules 中,JS 可以直接使用 CSS 的类名作为对象值,例如下面代码:

// app.js
import styles from './app.css';

let element = `
  <div class="${styles.element}">
    <p>CSS Modules</p>
  </div>
`;
document.write(element);

在 css-loader 增加modules的选项,说明打开 CSS Modules 支持。

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          }
        ]
      }
    ]
  }
};

跟 CSS Modules 相关的配置还有很多,具体可以在css-loader对应的文档 (opens new window)找到。