简体   繁体   English

webpack中css-loader的目的是什么?

[英]What is the purpose of css-loader in webpack

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


EDIT: In original answer I was describing style-loader not css-loader . 编辑:在原始答案中,我描述的是style-loader而不是css-loader It's easy to forget different purpose of those loader since css-loader can only be used with style-loader . 由于css-loader只能与style-loader一起使用,因此很容易忘记这些加载器的不同用途。


New answer 新答案

css-loader gives you more control over importing .css files. css-loader使您可以更好地控制导入.css文件。

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

Since now require is used, it's enables you to use for example file-loader or url-loader . 由于现在使用了require ,因此可以使用例如file-loaderurl-loader Now url(image.png) can be converted to: 现在url(image.png)可以转换为:

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

or with limit property of url-loader creates inline picture: 或者使用url-loader limit属性创建内联图片:

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

2. Enables CSS Modules 2.启用CSS模块

Let's consider styles of componentA and componentB : 让我们考虑componentAcomponentB样式:

componentA/style.css

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

componentB/style.css

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

componentA looks: componentA看起来:

import './style.css';

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

and componentB looks: componentB看起来:

import './style.css';

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

What color of background color those components would have? 这些组件的背景颜色是什么颜色的? This problem is related with leaking of styles, it's hard to tell if they are will be red or blue (it's hard to predict order of styles created by style-loader ). 这个问题与样式泄漏有关,很难判断它们是红色还是蓝色(很难预测样式style-loader创建的style-loader顺序)。 If you use CSS Modules approach you can deal with this problem. 如果您使用CSS模块方法,您可以处理此问题。 Now import styles to variable and this variable will contain object with mapping class names: 现在将样式导入变量,此变量将包含具有映射类名称的对象:

componentA with CSS Modules looks: 带有CSS模块的componentA看起来:

import s from './style.css';

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

s object will contain : s对象将包含:

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

componentA/style.css will be converted to componentA/style.css将被转换为

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

and componentB with CSS Modules looks: 和使用CSS模块的componentB看起来:

import s from './style.css';

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

s object will contain : s对象将包含:

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

componentB/style.css will be converted to componentB/style.css将被转换为

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

And now even if you don't use super specific name like wrapper in both components you are sure that they don't overlap and componentA stays blue and componentB red. 现在,即使你不在两个组件中使用超级特定名称(如wrapper ,也可以确保它们不重叠, componentA保持蓝色, componentB保持红色。 It's great power of encapsulation of styles described as CSS Modules - it is possible with help of css-loader . 它是封装描述为CSS模块的样式的强大功能 - 在css-loader帮助下可以实现。

OldAnswer OldAnswer

css-loader style-loader change couples js and css css-loader style-loader更改成员js和css

Let's consider this structure of project 让我们考虑一下这个项目结构

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

index.js looks like this index.js看起来像这样

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

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

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

each of *.js components in general looks like this 每个*.js组件通常都是这样的

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

index.html contains 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>

Now if you want to refactor your code and for example disable componentB you must remove it from index.js 现在,如果要重构代码,例如禁用componentB ,则必须将其从index.js删除

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

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

and since css and js are decoupled you must do the same for styles in index.html 并且因为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>

This duplication in large project can lead to leaving dead css code - it's harder to maintain since you must do two things in separate places. 大型项目中的这种重复可能会导致死css代码 - 因为你必须在不同的地方做两件事,所以它很难维护。

NOTE: SASS or LESS have the same problem. 注意: SASS或LESS有同样的问题。 It's only moved from index.html to index.sass : 它只从index.html移到index.sass

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

2. With css-loader style-loader 2.使用css-loader样式加载器

Now you point to styles related to some component directly from it (not in separate place like in 1. point) For example your *.js component will look like 现在你直接从它指向与某个组件相关的样式(不是在1. point中的单独位置)例如你的*.js组件看起来像

import './style.css';

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

and index.html index.html

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

The most important is that if you have this architecture and want to disable componentB , only what you do is 最重要的是,如果你有这个架构并想要禁用componentB ,那么你所做的只是

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

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

It's all! 这就是全部! No more looking for reference of styles componentB/style.css in any .html or .sass or .less . 不再需要在任何.html.sass.less查找样式componentB/style.css引用。 The same goes if you want to add new components: by simply importing .js file you add js logic and css styles. 如果要添加新组件,也是如此:只需导入.js文件即可添加js逻辑和css样式。 This is much easier to maintain! 这更容易维护!

In .js file ES6 import or CommonJS 's require() allows you to import only JavaScript files(modules) into it. .js文件中, ES6 importCommonJSrequire()允许您只将JavaScript文件(模块)导入其中。 So when you include your styles.css , for instance, in .js file via import from './styles.css' , you'll need to convert in into .js in the first place. 因此,当您通过import from './styles.css'包含styles.css ,例如,在.js文件中时,您需要首先转换为.js And here is where css-loader comes to the rescue. 这里是css-loader来救援的地方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM