文檔全文請查看 根目錄的文檔說明。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 是什麼再說吧,略略略。