1. 一个引入 CSS 资源的案例

// index.js
import './style.css'
/* style.css */
#root {
  height: 100px;
  width: 100px;
  border: 1px solid #ccc;
}

就这样打包的话,是会报错的,那么想要成功打包 CSS 资源,需要使用下面介绍的几个 loader。

2. style-loader

将 CSS 样式注入到 DOM 中。

2.1 结合 css-loader 使用

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

打包后,dist 目录下生成一个 main.js,文件内容中包含了我们所写的 CSS 代码,打开浏览器查看,在 <head> 标签内插入了一个 <style> 标签,并且页面样式也是生效的:

styleTag

2.2 结合 file-loader 使用

配置 injectType 选项(用来确定以何种形式将标签插入到 DOM 中)为 linkTag。

rules: [
  {
    test: /\.css$/,
    use: [
      { loader: 'style-loader', options: { injectType: 'linkTag' } },
      { loader: 'file-loader' }
    ]
  }
]

打包后,dist 目录下生成一个 main.js 和一个 css 文件,css 文件正是我们所写的 CSS 代码,打开浏览器查看,在 <head> 标签内插入了一个 <link> 标签,并且页面样式也是生效的:

linkTag

除了可以设置 injectType 选项,该 loader 还可以设置包括 attributes(在插入的标签中设置自定义属性)、insert(将标签插入到指定的 DOM 位置)和 base 选项。

更多详情查阅 style-loader

3. css-loader

// index.js
import style from './index.css'

console.log(style)
console.log(style.toString())
/* index.css */
@import url('./m1.css');
@import url('./m2.css');

#root {
  width: 100px;
  height: 100px;
  border: 1px solid #ccc;
}
/* m1.css */
.foo {
  color: red;
}
/* m2.css */
.bar {
  color: blue;
}

打包后,打开浏览器控制台,可以看到输出的内容是这样的:

css-loader
css-loader 的 toString 方法

CSS 文件之间通过了 @import 语法建立了引入的关系,而 css-loader 则可以解析这种关系,然后把多个的 css 文件关联在一起,并将 css 转换为 CommonJS 模块。

3.1 modules 选项

配置该选项可以启用 CSS 模块化

下面介绍在 vue 项目中使用 CSS 模块化。先使用 vue-cli3 新建一个项目,然后改造如下:

<!-- App.vue -->
<template>
  <div id="app">
    <div class="foo">foo</div>
    <div class="bar">bar</div>

    <HelloWorld />
    <HelloCSSModules />
  </div>
</template>

<!-- 中间部分代码忽略 -->

<style>
#app {
  height: 200px;
  width: 200px;
  border: 1px solid #ccc;
}
</style>

HelloScoped 组件使用 scoped 作用域书写样式:

<!-- HelloScoped.vue -->
<template>
  <div>
    <div class="foo">hello foo</div>
    <div class="bar">hello bar</div>
  </div>
</template>

<!-- 中间部分代码忽略 -->

<style scoped>
.foo {
  color: red;
}

.bar {
  color: blue;
}
</style>

HelloCssModules 组件通过 :class="$style.foo" 语法绑定类名,并且在 <style> 标签设置 module 属性:

<!-- HelloCssModules.vue -->
<template>
  <div>
    <div :class="$style.foo">css modules foo</div>
    <div :class="$style.bar">css modules bar</div>
  </div>
</template>

<!-- 中间部分代码忽略 -->

<style module>
.foo {
  color: green;
}

.bar {
  color: orange;
}
</style>

运行项目,打开浏览器进行对比,使用 scoped 语法会在 DOM 元素上设置唯一的自定义属性,然后通过 .foo[data-v-469af010] 语法来绑定样式;而使用 module 语法则直接将 class 类名替换成动态生成的唯一类名。

modules

3.2 importLoaders 选项

// webpack.config.js
rules: [
  {
    test: '/\.css$/',
    use: [
      'style-loader',
      {
        loader: 'css-loader',
        options: {
          importLoader: 0
        }
      },
      'postcss-loader'
    ]
  }
]
// index.js
import style from 'index.css';
/* index.css */
@import 'm1.css';

#root {
  width: 100px;
  height: 100px;
  border: 1px solid #ccc;
  transform: translate(100px, 100px);
}
/* m1.css */
.foo {
  transform: translate(10px, 10px);
}

在上述的文件中,我们在 index.js 引入了 index.css,index.css 中又通过 @import 语法引入了 m1.css,并且在 webpack.config.js 的配置中使用了 style-loader、css-loader 和 postcss-loader 来处理 css 文件,注意 css-loader 的 importLoader 设置为默认值 0。

运行项目,打开浏览器可以看到,#root 元素的 transform 样式属性加上了不同浏览器厂商的前缀,但是 .foo 元素的样式并没有加上前缀:

importLoaders.jpg

此时,就可以通过将 css-loader 的 importLoader 设置为 1 来解决这个问题:

// webpack.config.js
{
  loader: 'css-loader',
  options: {
    importLoader: 1
  }
}

重新打包,打开浏览器查看,发现 .foo 元素的 transform 样式属性也加上了各个浏览器厂商的前缀:

importLoaders2.jpg

总的来说,importLoader 作用于通过 @import 语法引入的 css 文件(比如 m1.css),假设 webpack.config.js 的内容是这样的:

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

importLoader 的值为 2 时,那么 m1.css 在被 css-loader 处理之前会经过 xxx-loader 和 postcss-loader,当值为 1 时,则被 css-loader 处理之前只会经过 postcss-loader,当值为 0 时,则被 css-loader 处理之前不会经过其他 loader。

更多详情查阅 css-loader

4 sass-loader

sass-loader 可以加载 sass/scss 文件并将其编译成 css 文件。

要使用 sass-loader,需要连同 node-sass 一起安装:

npm install sass-loader node-sass --save-dev

基本的使用方式:

// src/index.js
import './index.scss'
/* index.css */
$borderColor: red;

#root {
  width: 100px;
  height: 100px;
  border: 1px solid $borderColor;
}
// webpack.config.js
rules: [
  {
    test: /\.s[ac]ss$/i,
    use: [
      'style-loader',
      'css-loader',
      'sass-loader'
    ]
  }
]

执行打包指令,打开页面,可以看到,sass 语法 $borderColor: red; 生效了:

sass-loader.jpg

4.1 导入

使用 ~,可以导入 node_modules 目录里面的 sass 模块。

安装 bootstrap npm install bootstrap --save

将文件更新至下面这样:

<!-- index.html -->
<div id="root" class="btn btn-default">root</div>
/* index.css */
@import '~bootstrap/scss/bootstrap';

打包后打开浏览器,可以看到在 btn 类名下多了 bootstrap 的样式:

sass-loader_import.jpg


3santiago3
113 声望2 粉丝

引用和评论

0 条评论