4.核心概念-Loader—中-灵析社区

懒人学前端

五、CSS-Loader

css-loader

css-loader 会对 import 和 url() 进行处理,就像 js 解析 import/require() 一样。

使用

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title>css-loader</title>
</head>
<body>
</body>
</html>

index.js

src/index.js 文件中使用 import 导入 index.css 并输出导入的样式内容。

import indexCss from "./index.css";

console.log(indexCss.toString())

index.css

src/index.css 文件中使用 import 导入 index.css。

body {
  background-color: aqua;
  width: 500px;
  height: 500px;
  border: 1px solid red;
}

安装 css-loader

npm install css-loader -D

安装成功后,将 css-loader 配置到 webpack.config.js 中

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

执行打包命令,此时在浏览器中打开 dist/index.html 发现页面没有正确展示我们定义的样式,但是控制台中输出了我们定义的样式,到了这一步,css-loader 我们就正确引入并使用了,没有正确展示效果的原因是 css-loader 对 index.js 中的 import 进行处理,默认生成一个数组存放处理后的样式字符串,并将其导出。而 style-loader 负责将 css 插入到 html 中,style-loader 的使用我们在下一节展示。

配置项

css-loader 包含下面几个配置项

url

允许启用/禁用处理 CSS 函数 url 和 image-set。如果设置为false, css-loader 将不会解析 url 或 image-set 中指定的任何路径。还可以通过传递函数来根据资源路径动态地控制这种行为。从版本4.0.0开始,绝对路径是基于服务器根目录进行解析的。

src/index.css

body {
    background: url(./img/1.png);
}

webpack.config.js

module.exports = {
  ...
   {
      loader: 'css-loader',
      options: {
          url: false,
          // url: true
      }
    }
};

在控制台我们在 index.js 中输出了 index.css 导出的字符串,我们来看下 url 设置为 false 和 true 的 background 区别。

当 url 设置为 false 时, url 中的图片地址没做任何处理,当 url 值为 true 时,编译后地址为图片的路径,并且 dist 文件夹下会生成一张图片。

import

允许启用/禁用 @import 处理。

src/index.css

@import url('./main.css');

body {
  border: 1px solid red;
}

src/main.css

body {
  width: 200px;
  height: 200px;
}

webpack.config.js

module.exports = {
...
  {
    loader: 'css-loader',
    options: {
        import: false
        // import: true
    }
  }
};

为了方便看到样式,我这安装了 style-loader 并添加到了 loader 中,我们来看下 import 设置为 false 和 true 的区别。

当设置为 false 时 index.css 中的 @import 没有解析导致运行代码时找不到 main.css。

modules

查询参数 modules 会启用 CSS 模块规范。

默认情况下,这将启用局部作用域 CSS。(你可以使用 :global(...) 或 :global 关闭选择器 and/or 规则。详情可查看 modules

webpack.config.js

{
  loader: 'css-loader',
  options: {
      modules: true
  }
}

sourceMap

设置 sourceMap 选项查询参数来引入 source map。

例如 extract-text-webpack-plugin 能够处理它们。

默认情况下取决于compiler.devtool 值,值为 false 和 eval 时,不会生成 source map,一般情况下不启用它,因为它们会导致运行时的额外开销,并增加了 bundle 大小 (JS source map 不会)。此外,相对路径是错误的,你需要使用包含服务器 URL 的绝对公用路径。

webpack.config.js

{
  ...
  loader: 'css-loader',
  options: {
      sourceMap: true
  }
}

esModule

css-loader 中有时生成 esModule 模块化的形式是有益的,比如 module-concatenation 和 tree-shaking 时必须使用 esModule 模式才会生效。如果想启用 CommonJS 模块语法,则 esModule 设置为 false。

webpack.config.js

{
  ...
  options: {
    esModule: true
  }
}

importLoaders

在 src/index.css 中使用的 @import './main.css',importLoaders 选项可以定义在 @import 时使用哪些插件编译。

webpack.config.js

{
  ...
  use: [
    "style-loader",
    {
      loader: "css-loader",
      options: {
        // 0 => no loaders (default);
        // 1 => postcss-loader;
        // 2 => postcss-loader, sass-loader
        importLoaders: 2,
      },
    },
    "postcss-loader",
    "sass-loader",
  ],
}

exportType

允许将样式导出为带有模块的数组、字符串或可构造样式表(如CSSStyleSheet)。默认值是 'array'。

webpack.config.js

{
  ...
  use: [
    {
      loader: 'css-loader',
      options: {
          exportType: 'string'
      }
    }
    ]
  }
}

src/index.js

import indexCss from "./index.css";

console.log(indexCss)

打包后,执行 dist/index.html 可以看到控制台输出了 index.css 中定义的样式字符串。

总结

本节我们介绍了 css-loader 的使用方法和 css-loader 包含的几个常用参数配置。css-loader 可以将 js 中的 import 导入样式文件进行编译并且拿到导出内容供其他插件使用。

六、Style-Loader

style-loader

style-loader 一般和 css-loader 配合使用,css-loader 识别模块,通过特定的语法规则进行内容转换最后导出,style-loader 将 css-loader 导出的内容插入到 DOM。

使用

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title>style-loader</title>
</head>
<body>
</body>
</html>

index.js

src/index.js 文件中使用 import 导入 index.css。

import indexCss from './index.css';

index.css

设置一个长宽均为 200 像素的带红色边框的正方形

body {
    border: 1px solid red;
    width: 200px;
    height: 200px;
}

安装 style-loader

npm install style-loader -D

安装成功后,将 style-loader 配置到 webpack.config.js 中,配置中我们使用 css-loader 和 style-loader 两个加载器,webpack 中 loader 的解析一般由右向左,由下向上解析,所以 webpack 会先执行 css-loader,css-loader 导出内容传给 style-loader,最后在执行 style-loader。

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

执行打包命令,此时在浏览器中打开 dist/index.html 发现页面可以正常展示我们设置的样式,我们在控制台可以看到样式被插入到 head 标签中。

配置项

style-loader 包含下面几个配置项

injectType

设置样式如何注入 DOM,默认为 styleTag,即使用多个<style></style> 模式。

styleTag

src/index.css

@import url('style.css');
.bar {
    color: blue;
}

src/style.css

.foo {
    color: red;
}

webpack.config.js

module.exports = {
  ...
  {
    test: /\.(css)$/,
    use: [
      {
        loader: 'style-loader',
        options: { injectType: "styleTag" }
      }, 'css-loader'
    ]
  }
};

index.js

import index from "./index.css";

const divElement = document.createElement("div");
divElement.className = "foo";
divElement.innerHTML = 'style-loader'
document.body.appendChild(divElement)

执行打包命令,在浏览器中打开 dist/index.html 文件,我们可以看到 head 中插入了两个 style 标签,div 中的文字颜色可以正常显示。

singletonStyleTag

将多个样式文件内容在一个 style 标签中插入 DOM。

webpack.config.js

module.exports = {
  ...
  {
    test: /\.(css)$/,
    use: [
      {
        loader: 'style-loader',
        options: { injectType: "singletonStyleTag" }
      }, 'css-loader'
    ]
  }
};

lazyStyleTag

<style></style> 按需注入到 DOM 。建议遵循 .lazy.css 惰性样式的命名约定和 .css 基本style-loader用法。当使用 lazyStyleTag 时,可以通过 style-loader 的 style.use()、style.unuse() 按需使用。

src/style.lazy.css

.foo {
    color: red;
}

src/index.js

import styles from "./style.lazy.css";
styles.use();
const divElement = document.createElement("div");
divElement.className = "foo";
divElement.innerHTML = 'style-loader'
document.body.appendChild(divElement)

webpack.config.js

module.exports = {
...
 {
    test: /\.(css)$/,
    use: [
      {
        loader: 'style-loader',
        options: { injectType: "lazyStyleTag" }
      }, 'css-loader'
    ]
  }
};

打包后,可以看到样式被插入到 DOM,并且颜色已生效,如果 index.js 中没有调用 styles.use(),则样式不会被插入到 DOM。

attributes

将指定的属性值附加到 <style> 或 <link> 标签

webpack.config.js

{
  loader: 'style-loader',
  options: { attributes: {id: 'styleLoader'} }
}

insert

默认情况下 style-loader 会将<style>、<link> 标签插入到 <head> 标签尾部,设置 insert 后,可以将样式标签插入到其他位置。

webpack.config.js

{
  loader: 'style-loader',
  options: { insert: 'body' }
}

styleTagTransform

当插入 style 标签到 DOM 时转换标签和 css,可以设置自定义方法解析 style 标签插入方式。

webpack.config.js

{
  ...
    loader: 'style-loader',
    options: { styleTagTransform: function(css, style) {
      style.innerHTML = `${css}.modify{}\n`
      document.head.appendChild(style)
    } 
}

打包后,在浏览器中打开 dist/index.html,我们可以看到 css 样式后面添加了我们在方法中书写的内容。

esModule

style-loader 中生成 esModule 模块化的形式是有益的,比如 tree-shacking 时必须使用 esModule 模式才会生效。如果想启用 CommonJS 模块语法,则 esModule 设置为 false。

webpack.config.js

{
  ...
  options: {
    esModule: true
  }
}

base

当使用一个或多个 DllPlugin 时,此设置主要用作 css 冲突的解决方法。允许您通过指定大于 DllPlugin1 使用的范围的 css 模块 ID 基数来防止 app 的 css(或DllPlugin2 的 css)覆盖 DllPlugin1 的 css

webpack.dll1.config.js

{
  ...
  use: ["style-loader", "css-loader"],
}

webpack.dll2.config.js

{
  ...
  use: [
    { loader: "style-loader", options: { base: 1000 } },
    "css-loader",
  ],
}

webpack.app.config.js

{
  ...
  use: [
    { loader: "style-loader", options: { base: 2000 } },
    "css-loader",
  ],
}

总结

本节我们介绍了 style-loader 的使用方法和 style-loader 包含的几个常用参数配置。style-loader 一般和 css-loader 配合使用。

七、Postcss-Loader

postcss-loader

在使用 postcss-loader 之前,我们先来了解下 PostCSS。以下摘自 PostCSS 简介。

PostCSS 是一个允许使用 JS 插件转换样式的工具。 这些插件可以检查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 编译尚未被浏览器广泛支持的先进的 CSS 语法,内联图片,以及其它很多优秀的功能。PostCSS 的 Autoprefixer 插件是最流行的 CSS 处理工具之一。

由此我们可以知道通过使用 PostCSS 和 相应的插件,我们可以完成样式格式化、自动根据浏览器的支持情况增加样式前缀、使用先进的 CSS 特性等很多优秀的功能,截止到目前,PostCSS 有 200 多个插件。你可以在 插件列表 找到他们。如果我们想在 webpack 中使用 PostCSS 及 相应插件完成我们想要的功能,这时就需要通过 postcss-loader 来处理。

使用

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title>postcss-loader</title>
</head>
<body>
</body>
</html>

index.js

src/index.js 文件中使用 import 导入 index.css 并输出导入的样式内容。

import indexCss from "./index.css";

index.css

body {
 display: flex;
}

安装 postcss-loader 和 postcss

npm install postcss-loader postcss -D

安装成功后,将 postcss-loader 配置到 webpack.config.js 中,postcss-loader 通过加载插件转换 css 内容,转换后的内容虽然是 .css 文件,但是仍需传递给 css-loader 做后续处理。

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

以上只是将 postcss-loader 配置到了 webpack 中,执行打包命令可以正常打包,但 css 内容不会发生变化,postcss-loader 需要通过插件来达到我们想要的效果,下面我们以自动添加前缀为例看下效果。

安装 autoprefixer

npm install autoprefixer -D

postcss.config.js

项目根目录下新建 postcss.config.js 文件,配置 autoprefixer 插件,和要对应的浏览器版本。其中 browsers 的配置可以配置到 package.json 或者 .browserslistrc 文件下,如果配置到 postcss.config.js 中打包时会有警告,不过我们为了演示 autoprefixer 效果,不对此做处理。

module.exports = {
    plugins: [
      require('autoprefixer')({
        'browsers': ['> 1%', 'last 2 versions']
      })
    ]
};

配置完成后,执行打包命令,打包成功后在浏览器中打开 dist/index.html 文件,在控制台中我们可以看到,样式代码已经自动增加前缀。

配置项

postcss-loader 包含下面几个配置项

  • execute
  • postcssOptions
  • sourceMap
  • implementation

execute

默认:undefined

值类型:Boolean

作用:在 CSS-in-JS 中,如果您想要处理在 JavaScript 中书写的样式,需要使用 postcss-js 解析器,添加 execute 选项并设置为 true。

webpack.config.js

module.exports = {
  ...
   {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          parser: "postcss-js",
        },
        execute: true,
      },
    }
};

postcssOptions

默认:undefined

值类型:Object | Function

作用:允许设置 PostCSS options 和插件。支持所有PostCSS选项。

webpack.config.js

module.exports = {
  ...
   {
      loader: "postcss-loader",
      options: {
        // object
        postcssOptions: {
          ...
        }
        // function
        postcssOptions: (loaderContext) => {
          return {
            ...
          }
        }
      },
    }
};

sourceMap

默认:取决于 devtool 选项

值类型:Boolean

作用:是否开启 sourceMap

webpack.config.js

module.exports = {
  ...
   {
      loader: "postcss-loader",
      options: {
        sourceMap: true
      },
    }
};

implementation

默认:postcss

值类型:Function | String

作用:implementation 选项决定使用哪个 PostCSS 实现。覆盖本地安装的 postcss 的 peerDependency 版本

webpack.config.js


module.exports = {
  ...
   {
      loader: "postcss-loader",
      options : {  implementation : require ( "postcss" )  }
    }
};

总结

本节我们介绍了 postcss-loader 的使用方法,postcss-loader 主要是 PostCSS 在 webpack 环境下的使用方法,通过加载不同的插件来达到处理样式文件的效果,PostCSS 支持的插件非常丰富,本文只是通过自动添加前缀的例子做一个展示,想看其他插件的使用方法可以去 PostCSS 官网查看。

八、Sass-Loader

sass-loader

Sass
sass 是一种 css 的预编译语言。它提供了 变量(variables)、嵌套(nested rules)、 混合(mixins)、 函数(functions)等功能,并且完全兼容 css,sass 能够帮助复杂的样式表更有条理,并且易于在项目内部或跨项目共享设计。

当 css 变得越来越臃肿、 越来越复杂、越来越难以维护时 sass 为我们提供了 css 中不存在的特性辅助我们编写健壮、 可维护的 css 代码。

在使用 sass 之前,需要在项目中安装它,而 sass-loader 的作用是加载 sass/scss 文件并将其编译为 css,通过将 style-loader 和 css-loader 与 sass-loader 链式调用,可以立刻将样式作用在 DOM 元素。

使用

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title>sass-loader</title>
</head>
<body>
  <p>hello sass</p>
</body>
</html>

index.js

src/index.js 文件中使用 import 导入 index.scss。

import indexCss from "./index.scss";

index.scss

sass 和 scss 其实是同一种东西,我们平时都称之为 sass,不过两者之间写法也存在些区别,感兴趣的小伙伴儿可自行查阅,我们本案例都以 scss 为例。

$primary-color: #f00;

body {
  color: $primary-color;
}

安装 sass-loader 和 sass

npm install sass-loader sass --save-dev

安装成功后,将 sass-loader 配置到 webpack.config.js 中。

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

执行打包命令后,在浏览器打开 dist/index.html 文件,我们可以看到我们在 index.scss 文件中定义的颜色常量被正确的显示到了标签上面,在控制台可以看到,color 的颜色属性已由定义的变量转换成了定义的颜色值。

配置项

sass-loader 可以通过指定 options 参数,向 sass 传递选项参数。

  • implementation
  • sassOptions
  • sourceMap
  • additionalData
  • webpackImporter
  • warnRuleAsWarning

implementation

默认值:sass

值类型:Object | String

作用:sass-loader 要使用的 sass 实现。默认情况下,sass-loader 会根据你的依赖解析需要使用的实现。 只需将必需的实现添加到 package.json(sass 或 node-sass 包)中并安装依赖项即可。

package.json

// sass-loader 将会使用 sass 实现
{
  "devDependencies": {
    "sass-loader": "^7.2.0",
    "sass": "^1.22.10"
  }
}

package.json

// sass-loader 将会使用 node-sass 实现
{
  "devDependencies": {
    "sass-loader": "^7.2.0",
    "node-sass": "^5.0.0"
  }
}

同时安装 node-sass 和 sass 的情况下,sass-loader 默认会选择 sass。 为了避免这种情况,你可以使用 implementation 选项。

webpack.config.js


module.exports = {
  ...
   {
      loader: "sass-loader",
      options: {
        // Object
        implementation: require('sass')
        // String
        implementation: require.resolve('sass')
      },
    }
};

sassOptions

默认值:sass 实现的默认值

值类型:Object | Function

作用:设置 sass 实现的启动选项。

在使用他们之前,请查阅有关文档:Dart Sass 文档提供了所有可用的 sass 选项。

webpack.config.js

module.exports = {
  ...
  {
    {
      loader: "sass-loader",
      options: {
        // Object
        sassOptions: {
          includePaths: ['absolute/a', 'absolute/b'],
        },
        // Function
        sassOptions: (loaderContext) => {
          // 有关可用属性的更多信息 https://webpack.js.org/api/loaders/
          ...
          return {
            includePaths: ['absolute/a', 'absolute/b'],
          };
        },
      },
    }
  }
};

sourceMap

默认值:取决于 complier.devtool值,值为 false 和 eval 时,不会生成 source map。

值类型:Boolean

作用:是否开启 sourceMap

webpack.config.js

module.exports = {
  ...
   {
      loader: "sass-loader",
      options: {
        sourceMap: true
      },
    }
};

additionalData

默认值:undefined

值类型: String | Function

作用:在实际的文件之前要添加的 sass / scss 代码。下面的示例中,width、value 可以在 index.scss 中直接引用。

webpack.config.js

module.exports = {
  ...
  {
    loader: "sass-loader",
    options : {  
      // String
      additionalData: '$width:' + process.env.NODE_ENV + ';',
      // Function sync
      additionalData: (content, loaderContext) => {
        ...
        return '$value: 100px;' + content;
      }
      // Function async 
      additionalData: async (content, loaderContext) => {
        ...
        return '$value: 100px;' + content;
      }
    }
  }
};

webpackImporter

默认值:true

值类型: Boolean

作用:开启 / 关闭默认的 Webpack importer。在某些情况下,可以提高性能。但是请谨慎使用,因为 aliases 和以 〜 开头的 @import 规则将不起作用。 你可以传递自己的 importer 来解决这个问题(参阅 importer docs)。

webpack.config.js

module.exports = {
  ...
  {
    loader: "sass-loader",
    options : {  
      webpackImporter: false,
    }
  }
};

warnRuleAsWarning

默认值:false (在下一个大版本发布中它将默认设置为 true)

值类型: Boolean

作用:将 @warn 规则视为 webpack 警告而不是日志。

index.scss

$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    @if not index($known-prefixes, $prefix) {
      @warn "Unknown prefix #{$prefix}.";
    }

    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

body {
  @include prefix('display', 'flex', 'a');
}

webpack.config.js

module.exports = {
  ...
   {
      loader: "sass-loader",
      options : {  
        warnRuleAsWarning: true,
      }
    }
};

在上面的例子中,我们 $prefixes 值传入 a,执行打包命令,虽然可以打包成功,但是控制台会输出警告,如果我们将 $prefixes 值传入 $known-prefixes 中定义的 o,则控制台不会显示警告。

总结

本节我们介绍了 sass-loader 的使用方法和一些配置参数。通过使用 sass-loader 和 sass 可以让我们让我们的样式表更有条理并且易于维护。

阅读量:2015

点赞量:0

收藏量:0