窥探css-loader与style-loader的作用
前言
大家伙都清楚在使用webpack
构建前端项目时都会使用到sass-loader、less-loader、postcss-loader、css-loader、style-loader
,但这些loader
在其中起到什么作用呢?本篇主要阐述css-loader
与style-loader
的作用和实现,加深对loader
的理解。
css-loader
css-loader
会对 @import
和 url()
进行处理,就像 js
解析 import/require()
一样,默认生成一个数组存放存放处理后的样式字符串,并将其导出。
假如有三个样式文件:a.module.scss
,b.module.scss
,c.module.scss
,它们之间的依赖关系是这样的:
// a.module.scss
@import './b.module.scss';
.container {
width: 200px;
height: 200px;
background-color: antiquewhite;
}// b.module.scss
@import url('./c.module.scss');
.text {
font-size: 16px;
color: #da2227;
font-weight: bold;
}// c.module.scss
.name {
font-size: 16px;
;
color: #da7777;
font-weight: bold;
}
在
index.jsx
文件中引入它们// index.jsx
import React from 'react';
import styles from './a.module.scss';
const Index = () => {
return
xxx,hello world!!!}export default Index;
webpack.config.js
构建脚本// webpack.config.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
entry: {
index: './src/index.jsx'
},
output: {
filename: 'js/[name].js',
path: path.resolve(__dirname, './dist'),
library: 'MyComponent',
libraryTarget: 'umd',
},
resolve: {
extensions: ['.js', '.jsx', '.tsx'],
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: false, // 禁止css modules
}
},
'sass-loader'
]
},
{
test: /\.(jpg|jpeg|png|gif)$/,
use: ['url-loader']
}
]
},
plugins: [
new webpack.ProgressPlugin(),
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ['dist']
}),
],
}
.babelrc
配置// .babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-proposal-class-properties"
]
}
在
package.json
配置构建命令"build:dev": "webpack --mode none"
。为了方便分析构建之后的代码,这里将mode
设置为none
。三种
mode
方式:development |
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development 。为模块和 chunk 启用有效的名,也就是将模块id替换成模块名称。文章图片 文章图片 |
---|---|
production |
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production 。为模块和 chunk 启用确定性的混淆名称, FlagDependencyUsagePlugin ,FlagIncludedChunksPlugin ,ModuleConcatenationPlugin ,NoEmitOnErrorsPlugin 和 TerserPlugin 。文章图片 |
none |
不使用任何默认优化选项 |
yarn build:dev
构建,分析生成的文件(1)
a.module.scss
使用@import
引入了b.module.scss
,被处理放入同一个模块的数组___CSS_LOADER_EXPORT___
中并导出文章图片
(2)
b.module.scss
使用@import url()
引入了c.module.scss
,但c.module.scss
被单独处理放入另一个模块的数组___CSS_LOADER_EXPORT___
中并导出文章图片
(3)
a.module.scss
与b.module.scss
被处理放入一个模块数组,c.module.scss
被单独处理放入另一个模块的数组,但是b.module.scss
与c.module.scss
是由引入关系的,这个在构建后怎么关联依赖的呢?a.module.scss
与b.module.scss
被处理放入模块id
为12
的数组,c.module.scss
被处理放入模块id
为15
的数组,模块id
为12
的模块中导入了模块id
为15
中的样式数组,并将其追加到模块id
为12
的数组中,最后统一以数组__WEBPACK_DEFAULT_EXPORT__
导出,css-loader
处理到这一步就结束了。另外css-loader
还提供其他的功能,比如css modules
,想要了解可以参照例子开启css modules
构建,窥其原理,此处不作介绍
文章图片
文章图片
css-loader
导出方式上面说到引入的样式都被转化成样式字符串放入模块数组中,这是默认的处理方式,其实还有另外两种。
配置项
exportType
允许导出样式为'array'
、'string'
或者 'css-style-sheet'
可构造样式(即 CSSStyleSheet
), 默认值:'array'
CSSStyleSheet
接口代表一个 CSS 样式表,并允许检查和编辑样式表中的规则列表。它从父类型 StyleSheet
继承属性和方法。一个
CSS
样式表包含了一组表示规则的 CSSRule
对象。每条 CSS
规则可以通过与之相关联的对象进行操作,这些规则被包含在 CSSRuleList
内,可以通过样式表的 cssRules
(en-US) 属性获取。例如,
CSSStyleRule
对象中的一条规则可能包含这样的样式:h1, h2 {
font-size: 16pt;
}
style-loader
style-loader
的作用是把 CSS
插入到 DOM
中,就是处理css-loader
导出的模块数组,然后将样式通过style
标签或者其他形式插入到DOM
中。配置项
injectType
可配置把 styles
插入到 DOM
中的方式,主要有:styleTag
:通过使用多个自动把
styles
插入到DOM
中。该方式是默认行为singletonStyleTag
:通过使用一个来自动把
styles
插入到DOM
中autoStyleTag
:与styleTag
相同,但是当代码在IE6-9
中运行时,请打开singletonStyleTag
模式lazyStyleTag
:在需要时使用多个把
styles
插入到DOM
中。推荐lazy style
遵循使用.lazy.css
作为后缀的命名约定,style-loader
基本用法是使用.css
作为文件后缀(其他文件也一样,比如:.lazy.less
和.less
)。当使用lazyStyleTag
时,style-loader
将惰性插入styles
,在需要使用styles
时可以通过style.use()
/style.unuse()
使style
可用。lazySingletonStyleTag
:通过使用一个来自动把
styles
插入到DOM
中,如上提供惰性支持lazyAutoStyleTag
:与lazyStyleTag
相同,但是当代码在IE6-9
中运行时,请打开lazySingletonStyleTag
模式linkTag
:使用多个将 styles 插入到 DOM 中。此
loader
会在运行时使用JavaScript
动态地插入。要静态插入
时请使用MiniCssExtractPlugin。
styleTag
插入方式进行分析:上面说到所有的样式都追加到模块
id
为12
的模块数组中,下面先获取模块id
为12
的模块数组,然后生成style
标签将其样式插入DOM
中文章图片
【窥探css-loader与style-loader的作用】上图中
_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()
得到的就是下图模块返回的update
方法,该方法调用了其他很多方法将样式通过style
标签插入DOM
文章图片
参考:
css-loader
style-loader
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- Docker应用:容器间通信与Mariadb数据库主从复制
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量
- 第326天
- Shell-Bash变量与运算符
- 逻辑回归的理解与python示例
- Guava|Guava RateLimiter与限流算法
- 我和你之前距离
- CGI,FastCGI,PHP-CGI与PHP-FPM
- 原生家庭之痛与超越