文档全文请查看 根目录的文档说明。css
若是能够,请给本项目加【Star】和【Fork】持续关注。html
有疑义请点击这里,发【Issues】。前端
DEMO地址node
简单来讲,style-loader
是将css-loader
打包好的css代码以<style>
标签的形式插入到html文件中。webpack
对于简单项目,打包而后插入也就足够了,可是碰见复杂状况,例如:git
<style>
标签(默认是不合并的);<style>
标签添加自定义属性;<style>
标签等;显然就不行了。es6
因此须要经过配置来进行设置。github
有几个属性须要和其余东西(好比某些loader)配合,才能生效。web
因此先介绍功能明确的几个,再简述很难直接应用的几个。浏览器
导入方式有两种
import 'foo.css'
;import foo from 'foo.css'
;前者没啥好说的。
当使用后者导入时,有一些特殊特性:
css-loader
的modules
属性的应用),会有生成的(局部)标识符(identifier)。
,能够经过foo.className
来获取useable
特性时,能够经过foo.use()
以及foo.unuse()
来让css生效/失效;url
特性尝试失败。名称 | 类型 | 默认值 | 描述 |
attrs | {Object} | {} | 添加自定义 attrs 到 style 标签 |
attrs
属性最好理解。
attrs
的值是一个对象;key=val
的形式插入;[name]
或者 [hash]
之类的,无效;例如:
{
loader: 'style-loader',
options: {
attrs: {
id: 'foo'
}
}
}
复制代码
插入到html后,style标签变为以下形式:<style id="foo" type="text/css">css代码略</style>
。
可是缺点是不能变为哈希值,因此若是想要实现css的局部做用域,还须要其余东西配合(这里略略略)。
名称 | 类型 | 默认值 | 描述 |
transform | {Function} | false | 转换/条件加载 CSS,经过传递转换/条件函数 |
简单来讲,这个是拿到以字符串的形式拿到css文件,而后将这个字符串以参数的形式传给处理函数,函数处理完后返回,返回值即实际插入style标签的内容。
使用方法:
一、配置 style-loader
的属性以下:
{
loader: 'style-loader',
options: {
transform: 'transform.js' // 可使用相对路径,这里表示跟 webpack.config.js 同目录
}
}
复制代码
二、在webpack.config.js
的同一个目录下建立文件:transform.js
(即上面写的那个路径)
三、在transform.js
文件内,粘贴以下代码(CommonJS模块形式):
// 这里只有一个参数,即css字符串
module.exports = function (css) {
console.log(css)
const transformed = css.replace(/}/g, 'box-sizing: border-box;\n}')
return transformed
}
复制代码
这段代码的做用,至关于给每一个css样式里,添加了一个box-sizing: border-box;
属性。
例如css文件以下:
// foo.css 转换前
#app {
position: relative;
}
复制代码
转换完后的结果变为:
// foo.css 转换后
#app {
position: relative;
box-sizing: border-box;
}
复制代码
box-sizing:
前面没有空格,是由于转换函数里,replace第二个参数的box-sizing:
前没有空格。
四、每一个css文件都会执行一次这段代码。css字符串,不包含@import
导入的css文件相关的几行代码;
五、重要:这段代码执行的时间不在打包的时候,而是在插入到html文件中的时候。
这意味着你能够取得一些根据当前浏览器环境设置的值。例如经过document.body.clientWidth
拿到浏览器宽度,而后动态计算一些css属性是否插入到页面中(响应式).
应用:
当以字符串形式拿到css代码的时候,咱们能够作不少事情。我举几个例子:
一、判断当前浏览器环境,当须要额外兼容代码的时候,给css属性添加兼容性代码。
例如碰见box-sizing
,添加-webkit-box-sizing:
和-moz-box-sizing:
。
二、能够进行风格设置。
例如同时存在亮色和暗色风格,用户使用的风格在设置后存在cookies或者localStorage,那么写两套代码显然是比较麻烦的。
就能够引入一个颜色映射表(暗色的值->亮色的值),默认使用暗色的值。
当检查到用户使用亮色风格时(读取cookies或者localStorage),经过颜色映射表,利用 replace
函数,将颜色值替换为亮色的。
名称 | 类型 | 默认值 | 描述 |
insertAt | {String|Object} | bottom | 在给定位置处插入style标签 |
insertInto | {String} | 给定位置中插入style标签 |
简单来讲,insertAt
和 insertInto
共通决定style标签插入哪里。
两种状况:
insertAt
值为 string
类型。能够是 top
或者 bottom
,表示插入某个标签 内 的顶部或者结尾,和该标签是父子关系;insertAt
值为 object
类型。key只能是 before
(见 node_modules/style-loader/lib/addStyles.js
第173行),表示插入到某个标签以前(和该标签是兄弟关系),例如如下:insertAt: {
before: '#app'
},
insertInto: 'body'
复制代码
以上代码表示,先在<body>
标签能找到<div id='app'></div>
这个标签,而后插入到这个标签以前;
假如找不到符合要求的标签,则默认插入到 <head></head>
标签的末尾。
整个插入逻辑以下:
insertAt
是值是 top
或者 bottom
,那么 style
标签将插入到 insertInto
所指向的DOM(经过document.querySelector(target)
获取)的开头或末尾( style
标签为指向DOM的子元素);insertAt
的值是对象,那么则插入 insertInto
的子元素的 insertAt.before
所指向的DOM以前(即 document.querySelector("insertInto insertAt.before")
指向的DOM)。注意,两个属性的标签选择器,都是经过 document.querySelector
实现的,因此存在两个问题:
document.querySelector
的语法;名称 | 类型 | 默认值 | 描述 |
sourceMap | {Boolean} | false | 启用/禁用 Sourcemap |
convertToAbsoluteUrls | {Boolean} | false | 启用 source map 后,将相对 URL 转换为绝对 URL |
首先,sourceMap
实测和翻源代码后,感受没有生效。
在跟了一遍代码后,推测缘由在于,sourceMap的取值,取的是 css-laoder
的sourceMap的值。
准确的说,在webpack里,css文件被视为一个模块,所以import
引入的css文件,也是一个模块对象。而在判断的时候,取的是这个模块(是一个object)的属性sourceMap的值,而不是 options.sourceMap
的值。
我已经提了issues给官方了。
而这个模块的值,推测是被css-loader
的sourceMap
属性赋值的(我没有去跟源代码,但测试后推断就是这样的)。
其次,从相对路径转为绝对路径,是在前端经过js代码转换的。
第三,convertToAbsoluteUrls
的效果如官方描述同样,具体下面举例。
几种状况以下(截止style-loader
版本0.19.0
):
convertToAbsoluteUrls
值为false时,依然使用相对路径,即例如./foo.png
;css-loader
的 sourceMap
的值为true,且convertToAbsoluteUrls
值为true时,更改成绝对路径,即例如http://127.0.0.1:8080/foo.png
;style-loader
的sourceMap
属性的影响;bug的demo如连接
做用
让全部引入的css文件,变为手动加载;
使用方法
loader: 'style-loader/useable'
说明:
transform
属性失效(打包正常,但挂载的时候表示会报错)style.unref()
从DOM树中移出(这些样式会失效);style.ref()
插入到DOM树中进行挂载(样式生效)代码:
// app.js
import style from './style/style.css'
/* useable(开始) */
let isUse = false
// 这是一个按钮的点击事件
document.querySelector('#test').onclick = function () {
if (isUse) {
style.unref()
} else {
style.ref()
}
isUse = !isUse
}
/* useable(结束) */
复制代码
做用
使用一个的 <style>
标签加载全部css属性,或者是每一个css模块一个 <style>
标签。
默认值是false(每一个css模块一个 <style>
标签);
使用方法
{
loader: 'style-loader',
options: {
singleton: true
}
}
复制代码
说明:
<style>
标签,所以实际加载中,可能有多个<style>
标签;false
(而不是原文中说的默认状况下启用此选项
)true
时,那么,本来多个<style>
标签会被合并成一个<style>
标签。注:
官方文档上写的是默认开启,其实是不开启的(v0.19.0)。我已经提了issues
名称 | 类型 | 默认值 | 描述 |
hmr | {Boolean} | true | Enable/disable Hot Module Replacement (HMR), if disabled no HMR Code will be added (good for non local development/production) |
谷歌翻译为中文:
启用/禁用热模块更换(HMR),若是禁用,则不会添加HMR代码。 这能够用于非本地开发和生产。
大概就是指默认为true时,容许热加载(就是你改了代码后,不须要刷新页面,马上更新数据),我没实际测试过,不过应该没人会把这个设置为false吧?
名称 | 类型 | 默认值 | 描述 |
base | {Number} | true | 设置模块 ID 基础 (DLLPlugin) |
当使用一个或多个 DllPlugin 时,此设置主要用做 css 冲突 的修补方案。base 能够防止 app 的 css(或 DllPlugin2 的 css)覆盖 DllPlugin1 的 css,方法是指定一个 css 模块的 id 大于 DllPlugin1 的范围,例如:
等我搞清楚 DllPlugin 是什么再说吧,略略略。