style-loader詳細使用說明

STYLE-LOADER配置簡述

前注:

文檔全文請查看 根目錄的文檔說明css

若是能夠,請給本項目加【Star】和【Fork】持續關注。html

有疑義請點擊這裏,發【Issues】。前端

DEMO地址node

一、概述

簡單來講,style-loader是將css-loader打包好的css代碼以<style>標籤的形式插入到html文件中。webpack

對於簡單項目,打包而後插入也就足夠了,可是碰見覆雜狀況,例如:git

  1. 須要使用webpack的服務器熱加載服務進行特殊配置;
  2. 對css文件二次處理(更改類名,添加額外css屬性之類);
  3. 合併 <style> 標籤(默認是不合並的);
  4. 啓用sourceMap等(雖然實際根本無效嘛);
  5. 路徑轉換(相對路徑轉爲絕對路徑);
  6. <style> 標籤添加自定義屬性;
  7. 手動掛載、移除 <style> 標籤等;

顯然就不行了。es6

因此須要經過配置來進行設置。github

二、配置

有幾個屬性須要和其餘東西(好比某些loader)配合,才能生效。web

因此先介紹功能明確的幾個,再簡述很難直接應用的幾個。瀏覽器

2.0、普通

導入方式有兩種

  1. 直接import 'foo.css'
  2. es6語法 import foo from 'foo.css';

前者沒啥好說的。

當使用後者導入時,有一些特殊特性:

  1. 在使用局部做用域時(css-loadermodules屬性的應用),會有生成的(局部)標識符(identifier)。,能夠經過foo.className來獲取
  2. 當使用useable特性時,能夠經過foo.use()以及foo.unuse()來讓css生效/失效;
  3. url 特性嘗試失敗。

2.一、attrs

名稱 類型 默認值 描述
attrs {Object} {} 添加自定義 attrs 到 style 標籤

attrs 屬性最好理解。

  1. attrs的值是一個對象;
  2. 對象 key , val 成對出現的;
  3. 插入形式是以 key=val的形式插入;
  4. 但例如 [name] 或者 [hash] 之類的,無效;

例如:

{
    loader: 'style-loader',
    options: {
        attrs: {
            id: 'foo'
        }
    }
}
複製代碼

插入到html後,style標籤變爲以下形式:<style id="foo" type="text/css">css代碼略</style>

可是缺點是不能變爲哈希值,因此若是想要實現css的局部做用域,還須要其餘東西配合(這裏略略略)。

2.二、transform

名稱 類型 默認值 描述
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 函數,將顏色值替換爲亮色的。

2.三、insertAt和insertInto

名稱 類型 默認值 描述
insertAt {String|Object} bottom 在給定位置處插入style標籤
insertInto {String} 給定位置中插入style標籤

簡單來講,insertAtinsertInto 共通決定style標籤插入哪裏。

兩種狀況:

  1. insertAt 值爲 string 類型。能夠是 top 或者 bottom,表示插入某個標籤 的頂部或者結尾,和該標籤是父子關係;
  2. insertAt 值爲 object 類型。key只能是 before(見 node_modules/style-loader/lib/addStyles.js 第173行),表示插入到某個標籤以前(和該標籤是兄弟關係),例如如下:
insertAt: {
    before: '#app'
},
insertInto: 'body'
複製代碼

以上代碼表示,先在<body> 標籤能找到<div id='app'></div>這個標籤,而後插入到這個標籤以前;

假如找不到符合要求的標籤,則默認插入到 <head></head> 標籤的末尾。

整個插入邏輯以下:

  1. 假如 insertAt 是值是 top 或者 bottom ,那麼 style 標籤將插入到 insertInto 所指向的DOM(經過document.querySelector(target)獲取)的開頭或末尾( style 標籤爲指向DOM的子元素);
  2. 假如 insertAt 的值是對象,那麼則插入 insertInto 的子元素的 insertAt.before 所指向的DOM以前(即 document.querySelector("insertInto insertAt.before") 指向的DOM)。

注意,兩個屬性的標籤選擇器,都是經過 document.querySelector 實現的,因此存在兩個問題:

  1. 屬性的值,須要符合 document.querySelector 的語法;
  2. 低版本瀏覽器(好比IE)可能不支持這個選擇器API;

2.四、sourceMap和convertToAbsoluteUrls

名稱 類型 默認值 描述
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-loadersourceMap屬性賦值的(我沒有去跟源代碼,但測試後推斷就是這樣的)。

其次,從相對路徑轉爲絕對路徑,是在前端經過js代碼轉換的。

第三,convertToAbsoluteUrls 的效果如官方描述同樣,具體下面舉例。

幾種狀況以下(截止style-loader版本0.19.0):

  1. convertToAbsoluteUrls 值爲false時,依然使用相對路徑,即例如./foo.png
  2. css-loadersourceMap 的值爲true,且convertToAbsoluteUrls 值爲true時,更改成絕對路徑,即例如http://127.0.0.1:8080/foo.png
  3. 多是bug,因此目前不受style-loadersourceMap屬性的影響;

bug的demo如連接

2.五、useable

做用

讓全部引入的css文件,變爲手動加載;

使用方法

loader: 'style-loader/useable'

說明:

  1. 當使用這個特性時,transform屬性失效(打包正常,但掛載的時候表示會報錯)
  2. 示例代碼以下,效果解釋:
  3. 用一個變量標記當前是否掛載,點擊後進行判斷;
  4. 若是掛載了,經過style.unref()從DOM樹中移出(這些樣式會失效);
  5. 若是沒有掛載,那麼經過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(結束) */
複製代碼

2.六、singleton

做用

使用一個的 <style> 標籤加載全部css屬性,或者是每一個css模塊一個 <style> 標籤。

默認值是false(每一個css模塊一個 <style> 標籤);

使用方法

{
    loader: 'style-loader',
    options: {
        singleton: true
    }
}
複製代碼

說明:

  1. 默認狀況下,咱們會發現,每個css文件會變爲一個<style>標籤,所以實際加載中,可能有多個<style>標籤;
  2. 默認值爲 false (而不是原文中說的默認狀況下啓用此選項
  3. 當該值設置爲 true 時,那麼,本來多個<style>標籤會被合併成一個<style>標籤。

注:

官方文檔上寫的是默認開啓,其實是不開啓的(v0.19.0)。我已經提了issues

2.七、hmr

名稱 類型 默認值 描述
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吧?

2.八、base

名稱 類型 默認值 描述
base {Number} true 設置模塊 ID 基礎 (DLLPlugin)

當使用一個或多個 DllPlugin 時,此設置主要用做 css 衝突 的修補方案。base 能夠防止 app 的 css(或 DllPlugin2 的 css)覆蓋 DllPlugin1 的 css,方法是指定一個 css 模塊的 id 大於 DllPlugin1 的範圍,例如:

等我搞清楚 DllPlugin 是什麼再說吧,略略略。

相關文章
相關標籤/搜索