【问题标题】:What is the purpose of css-loader in webpackwebpack中css-loader的作用是什么
【发布时间】:2017-06-12 04:41:39
【问题描述】:

我开始使用 Webpack 2,我看到很多项目都在使用 css-loader,但我没有找到它的用途。

【问题讨论】:

  • 您阅读了 readme.md 吗? github.com/webpack-contrib/css-loader
  • 是的,但我没有发现它有帮助
  • 也许将您的问题扩大到哪些部分令人困惑?
  • Webpack 可以捆绑样式以及 javascript。 css-loader 允许你在你的包中导入 *.css。 Webpack 也将遍历 css 中的 @importurl()
  • 我为什么要使用它?例如,我知道我会使用 sass-loader 它会从 scss 文件创建 css

标签: javascript npm sass webpack


【解决方案1】:

编辑:在原始答案中,我描述的是style-loader 而不是css-loader。很容易忘记这些加载程序的不同用途,因为css-loader 只能与style-loader 一起使用。


新答案

css-loader 让您可以更好地控制导入.css 文件。

1.转换url(image.png) => require('./image.png')

由于现在使用require,因此您可以使用例如file-loaderurl-loader。 现在url(image.png)可以转换为:

url(/public-path/0dcbbaa701328a3c262cfd45869e351f.png)

或者用url-loader的limit属性创建内联图片:

url(data:image/jpeg;base64,LzlqLzRBQ ... zdF3)

2。启用CSS Modules

让我们考虑componentAcomponentB 的样式:

componentA/style.css

.wrapper {
  background-color: blue;
}
.specificToComponentA {
  // rest of styles
}

componentB/style.css

.wrapper {
  background-color: red;
}
.specificToComponentB {
  // rest of styles
}

componentA 看起来:

import './style.css';

export default function () {
  document.body.innerHTML = `
    <div class="wrapper">
      <div class="specificToComponentA">componentA</div>
    </div>
  `;
}

componentB 看起来:

import './style.css';

export default function () {
  document.body.innerHTML = `
    <div class="wrapper">
      <div class="specificToComponentB">componentB</div>
    </div>
  `;
}

这些组件的背景颜色是什么颜色?这个问题与样式泄漏有关,很难判断它们是红色还是蓝色(很难预测style-loader 创建的样式顺序)。如果你使用 CSS Modules 方法,你可以处理这个问题。 现在将样式导入变量,该变量将包含具有映射类名称的对象:

componentA 带有 CSS 模块的外观:

import s from './style.css';

export default function () {
  document.body.innerHTML = `
    <div class="${s.wrapper}">
      <div class="${s.specificToComponentA}">componentA</div>
    </div>
  `;
}

s 对象将包含:

{
  wrapper: "WO0HHIhH77",
  specificToComponentA: "jPYPsVTDZu"
}

componentA/style.css 将被转换为

.WO0HHIhH77 {
  background-color: blue;
}
.jPYPsVTDZu {
  // rest of styles
}

componentB 与 CSS 模块看起来:

import s from './style.css';

export default function () {
  document.body.innerHTML = `
    <div class="${s.wrapper}">
      <div class="${s.specificToComponentB}">componentB</div>
    </div>
  `;
}

s 对象将包含:

{
  wrapper: "C8EKTwiZfd", // Look, different than in componentA!!!
  specificToComponentB: "KI5jRsC2R5"
}

componentB/style.css 将被转换为

.C8EKTwiZfd { // Look, different than in componentA!!!
  background-color: red;
}
.KI5jRsC2R5 {
  // rest of styles
}

现在,即使您不在两个组件中使用像 wrapper 这样的超级特定名称,您也可以确定它们不会重叠,componentA 保持蓝色,componentB 保持红色。它是封装样式的强大功能,描述为 CSS 模块 - 在 css-loader 的帮助下可以实现。

旧答案

css-loader style-loader 改变 js 和 css

让我们考虑一下这个项目结构

├── components 
│   │
│   ├── componentA
│   │   ├── style.css
│   │   └── index.js
│   │
│   ├── componentB
│   │   ├── style.css
│   │   └── index.js
│   │
│   └── componentC
│       ├── style.css
│       └── index.js
│   
├── index.js  
└── index.html

index.js 看起来像这样

import componentA from './components/componentA';
import componentB from './components/componentB';
import componentC from './components/componentC';

componentA();
componentB();
componentC();

1.没有 css-loader 样式加载器

每个*.js 组件通常看起来像这样

export default function () {
  // logic of this component
}

index.html 包含

<link href="components/componentA/style.css" rel="stylesheet" type="text/css">
<link href="components/componentB/style.css" rel="stylesheet" type="text/css">
<link href="components/componentC/style.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="dist/bundle.js"></script>

现在,如果您想重构您的代码,例如禁用 componentB,您必须将其从 index.js 中删除

import componentA from './components/componentA';
// import componentB from './components/componentB';
import componentC from './components/componentC';

componentA();
// componentB();
componentC();

而且由于 css 和 js 是解耦的,你必须对 index.html 中的样式做同样的事情

<link href="components/componentA/style.css" rel="stylesheet" type="text/css">
<!-- <link href="components/componentB/style.css" rel="stylesheet" type="text/css"> -->
<link href="components/componentC/style.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="dist/bundle.js"></script>

大型项目中的这种重复可能会导致留下无效的 css 代码 - 因为您必须在不同的地方做两件事,所以更难维护。

注意: SASS 或 LESS 有同样的问题。它只是从index.html 移动到index.sass

@import './components/componentA';
@import './components/componentB'; // you must disable this manually
@import './components/componentC';

2。使用 css-loader 样式加载器

现在您直接从它指向与某些组件相关的样式(而不是像 1. 点那样在单独的位置) 例如,您的 *.js 组件看起来像

import './style.css';

export default function () {
  // logic of this component
}

index.html

<script type="text/javascript" src="dist/bundle.js"></script>

最重要的是,如果你有这个架构,想禁用componentB,只有你做的就是

import componentA from './components/componentA';
// import componentB from './components/componentB';
import componentC from './components/componentC';

componentA();
// componentB();
componentC();

就是这样!无需再在任何.html.sass.less 中寻找样式componentB/style.css 的参考。如果你想添加新组件也是如此:只需导入 .js 文件,你就可以添加 js 逻辑和 css 样式。这更容易维护!

【讨论】:

  • 感谢您的出色回答。它帮助我真正理解了ץ
  • @ofirfridman 抱歉误导,但我将 css-modules 与 style-loader 混淆了。现在我不得不描述两者。
  • 您提到 css-loader 会将 @import 解释为需要。这是否意味着 webpack 将接管该文件的解析? (对我来说听起来是递归的,但我想验证)。我想相信这一点,但后来我在 css-loader 中看到了“importLoaders”选项,这很令人困惑,因为如果 Webpack 刚刚接管,这个选项就没有必要了?
【解决方案2】:

.js 文件中ES6 importCommonJSrequire() 允许您仅将JavaScript 文件(模块)导入其中。因此,例如,当您通过import from './styles.css'styles.css 包含在.js 文件中时,您首先需要将其转换为.js。这就是 css-loader 来救援的地方。

【讨论】:

    猜你喜欢
    • 2017-12-12
    • 2019-03-03
    • 2020-01-30
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    • 2018-08-27
    • 1970-01-01
    • 2019-02-12
    相关资源
    最近更新 更多