將 CSS 注入 DOM 中。
首先,你需要安裝 style-loader
npm install --save-dev style-loader
或
yarn add -D style-loader
或
pnpm add -D style-loader
建議將 style-loader
與 css-loader
結合使用
然後將 loader 加入你的 webpack
設定中。例如
style.css
body {
background: green;
}
component.js
import "./style.css";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
此 loader 主要用於開發。預設設定並不適合用於生產環境。請參閱 建議範例設定 和 nonce 部分以取得詳細資訊。
injectType
類型
type injectType =
| "styleTag"
| "singletonStyleTag"
| "autoStyleTag"
| "lazyStyleTag"
| "lazySingletonStyleTag"
| "lazyAutoStyleTag"
| "linkTag";
預設值:styleTag
設定樣式將如何注入到 DOM 中。
可能值
styleTag
使用多個 <style></style>
自動將樣式注入到 DOM 中。這是預設行為。
component.js
import "./styles.css";
使用 Locals 的範例(CSS 模組)
component-with-css-modules.js
import styles from "./styles.css";
const divElement = document.createElement("div");
divElement.className = styles["my-class"];
所有 Locals(類別名稱)都儲存在匯入的物件中。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
// The `injectType` option can be avoided because it is default behaviour
{ loader: "style-loader", options: { injectType: "styleTag" } },
"css-loader",
],
},
],
},
};
loader 會注入類似這樣的樣式
<style>
.foo {
color: red;
}
</style>
<style>
.bar {
color: blue;
}
</style>
singletonStyleTag
使用一個 <style></style>
自動將樣式注入到 DOM 中。
警告
原始碼對應表無法使用。
component.js
import "./styles.css";
component-with-css-modules.js
import styles from "./styles.css";
const divElement = document.createElement("div");
divElement.className = styles["my-class"];
所有 Locals(類別名稱)都儲存在匯入的物件中。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: { injectType: "singletonStyleTag" },
},
"css-loader",
],
},
],
},
};
loader 會注入類似這樣的樣式
<style>
.foo {
color: red;
}
.bar {
color: blue;
}
</style>
autoStyleTag
與 styleTag
的運作方式相同,但如果程式碼在 IE6-9 中執行,會開啟 singletonStyleTag
模式。
lazyStyleTag
依需求使用多個 <style></style>
將樣式注入 DOM。建議延遲樣式採用 .lazy.css
命名慣例,而基本 style-loader
用法則採用 .css
(類似其他檔案類型,例如 .lazy.less
和 .less
)。當您 lazyStyleTag
值時,style-loader
會延遲注入樣式,讓它們可透過 style.use()
/ style.unuse()
依需求使用。
⚠️ 如果
unuse
的呼叫次數比use
多,行為將未定義。請勿這麼做。
component.js
import styles from "./styles.lazy.css";
styles.use();
// For removing styles you can use
// styles.unuse();
component-with-css-modules.js
import styles from "./styles.lazy.css";
styles.use();
const divElement = document.createElement("div");
divElement.className = styles.locals["my-class"];
所有當地 (類別名稱) 儲存在匯入物件的 locals
屬性中。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
exclude: /\.lazy\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.lazy\.css$/i,
use: [
{ loader: "style-loader", options: { injectType: "lazyStyleTag" } },
"css-loader",
],
},
],
},
};
loader 會注入類似這樣的樣式
<style>
.foo {
color: red;
}
</style>
<style>
.bar {
color: blue;
}
</style>
lazySingletonStyleTag
依需求使用一個 <style></style>
將樣式注入 DOM。建議延遲樣式採用 .lazy.css
命名慣例,而基本 style-loader
用法則採用 .css
(類似其他檔案類型,例如 .lazy.less
和 .less
)。當您 lazySingletonStyleTag
值時,style-loader
會延遲注入樣式,讓它們可透過 style.use()
/ style.unuse()
依需求使用。
⚠️ 來源對應不適用。
⚠️ 如果
unuse
的呼叫次數比use
多,行為將未定義。請勿這麼做。
component.js
import styles from "./styles.css";
styles.use();
// For removing styles you can use
// styles.unuse();
component-with-css-modules.js
import styles from "./styles.lazy.css";
styles.use();
const divElement = document.createElement("div");
divElement.className = styles.locals["my-class"];
所有當地 (類別名稱) 儲存在匯入物件的 locals
屬性中。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
exclude: /\.lazy\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.lazy\.css$/i,
use: [
{
loader: "style-loader",
options: { injectType: "lazySingletonStyleTag" },
},
"css-loader",
],
},
],
},
};
載入器會產生這個
<style>
.foo {
color: red;
}
.bar {
color: blue;
}
</style>
lazyAutoStyleTag
作用與 lazyStyleTag
相同,但如果在 IE6-9 中執行程式碼,會開啟 lazySingletonStyleTag
模式。
linkTag
使用多個 <link rel="stylesheet" href="path/to/file.css">
將樣式注入 DOM 中。
ℹ️ 載入器會在執行階段透過 JavaScript 動態插入
<link href="path/to/file.css" rel="stylesheet">
標籤。如果您想包含靜態<link href="path/to/file.css" rel="stylesheet">
,您應該使用 MiniCssExtractPlugin。
import "./styles.css";
import "./other-styles.css";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.link\.css$/i,
use: [
{ loader: "style-loader", options: { injectType: "linkTag" } },
{ loader: "file-loader" },
],
},
],
},
};
載入器會產生這個
<link rel="stylesheet" href="path/to/style.css" />
<link rel="stylesheet" href="path/to/other-styles.css" />
attributes
類型
type attributes = HTMLAttributes;
預設值:{}
如果已定義,style-loader
會將指定的屬性及其值附加到 <style>
/ <link>
元素上。
component.js
import style from "./file.css";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: "style-loader", options: { attributes: { id: "id" } } },
{ loader: "css-loader" },
],
},
],
},
};
<style id="id"></style>
insert
類型
type insert =
| string
| ((htmlElement: HTMLElement, options: Record<string, any>) => void);
預設值:head
預設情況下,style-loader
會將 <style>
/<link>
元素附加到樣式目標的結尾,也就是頁面的 <head>
標籤,除非由 insert
指定。這將導致載入器建立的 CSS 優先於目標中已存在的 CSS。如果您不適合標準行為,您可以使用其他值,但我們不建議這麼做。如果您鎖定 iframe,請確保您有足夠的存取權限,樣式會注入到內容文件標頭中。
string
Selector
允許設定自訂 查詢選擇器,將樣式注入 DOM 中。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: "body",
},
},
"css-loader",
],
},
],
},
};
函式的絕對路徑
允許設定自訂函式的絕對路徑,讓您可以覆寫預設行為,並在任何位置插入樣式。
警告
請不要忘記,這段程式碼會在瀏覽器中使用,而並非所有瀏覽器都支援最新的 ECMA 功能,例如
let
、const
、arrow function expression
等。我們建議使用babel-loader
來支援最新的 ECMA 功能。
警告
請勿忘記某些 DOM 方法在舊版瀏覽器中可能無法使用,我們建議僅使用 DOM 核心層級 2 屬性,但這取決於您想要支援的瀏覽器
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: require.resolve("modulePath"),
},
},
"css-loader",
],
},
],
},
};
新的 <style>
/<link>
元素將插入到 body
標籤的底部。
function
允許覆寫預設行為並在任何位置插入樣式。
警告
請勿忘記此程式碼將在瀏覽器中使用,且並非所有瀏覽器都支援最新的 ECMA 功能,例如
let
、const
、arrow function expression
等,我們建議僅使用 ECMA 5 功能,但這取決於您想要支援的瀏覽器
警告
請勿忘記某些 DOM 方法在舊版瀏覽器中可能無法使用,我們建議僅使用 DOM 核心層級 2 屬性,但這取決於您想要支援的瀏覽器
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: function insertAtTop(element) {
var parent = document.querySelector("head");
// eslint-disable-next-line no-underscore-dangle
var lastInsertedElement =
window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, parent.firstChild);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling);
} else {
parent.appendChild(element);
}
// eslint-disable-next-line no-underscore-dangle
window._lastElementInsertedByStyleLoader = element;
},
},
},
"css-loader",
],
},
],
},
};
在 head
標籤的頂端插入樣式。
您可以將任何參數傳遞至 style.use(options)
,此值將傳遞至 insert
和 styleTagTransform
函式。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
injectType: "lazyStyleTag",
// Do not forget that this code will be used in the browser and
// not all browsers support latest ECMA features like `let`, `const`, `arrow function expression` and etc,
// we recommend use only ECMA 5 features,
// but it is depends what browsers you want to support
insert: function insertIntoTarget(element, options) {
var parent = options.target || document.head;
parent.appendChild(element);
},
},
},
"css-loader",
],
},
],
},
};
將樣式插入提供的元素或 head
標籤(如果未提供目標)。現在您可以將樣式注入至 Shadow DOM(或任何其他元素)。
custom-square.css
div {
width: 50px;
height: 50px;
background-color: red;
}
custom-square.js
import customSquareStyles from "./custom-square.css";
class CustomSquare extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
const divElement = document.createElement("div");
divElement.textContent = "Text content.";
this.shadowRoot.appendChild(divElement);
customSquareStyles.use({ target: this.shadowRoot });
// You can override injected styles
const bgPurple = new CSSStyleSheet();
const width = this.getAttribute("w");
const height = this.getAttribute("h");
bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);
this.shadowRoot.adoptedStyleSheets = [bgPurple];
// `divElement` will have `100px` width, `100px` height and `red` background color
}
}
customElements.define("custom-square", CustomSquare);
export default CustomSquare;
styleTagTransform
類型
type styleTagTransform =
| string
| ((
css: string,
styleElement: HTMLStyleElement,
options: Record<string, any>
) => void);
預設:undefined
string
允許設定自訂函式的絕對路徑,以覆寫預設行為 styleTagTransform。
警告
請勿忘記此程式碼將在瀏覽器中使用,且並非所有瀏覽器都支援最新的 ECMA 功能,例如
let
、const
、arrow function expression
等,我們建議僅使用 ECMA 5 功能,但這取決於您想要支援的瀏覽器
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
injectType: "styleTag",
styleTagTransform: require.resolve("module-path"),
},
},
"css-loader",
],
},
],
},
};
function
在將「style」標籤插入 DOM 時,轉換標籤和 css。
警告
請勿忘記此程式碼將在瀏覽器中使用,且並非所有瀏覽器都支援最新的 ECMA 功能,例如
let
、const
、arrow function expression
等,我們建議僅使用 ECMA 5 功能,但這取決於您想要支援的瀏覽器
警告
請勿忘記某些 DOM 方法在舊版瀏覽器中可能無法使用,我們建議僅使用 DOM 核心層級 2 屬性,但這取決於您想要支援的瀏覽器
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
injectType: "styleTag",
styleTagTransform: function (css, style) {
// Do something ...
style.innerHTML = `${css}.modify{}\n`;
document.head.appendChild(style);
},
},
},
"css-loader",
],
},
],
},
};
base
type base = number;
此設定主要用於解決使用一個或多個 DllPlugin 時發生的 CSS 衝突。base
允許您透過指定大於 DllPlugin1 使用範圍的 CSS 模組 ID 基底,來防止 app 的 CSS(或 DllPlugin2 的 CSS)覆寫 DllPlugin1 的 CSS,例如:
webpack.dll1.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
webpack.dll2.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: "style-loader", options: { base: 1000 } },
"css-loader",
],
},
],
},
};
webpack.app.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: "style-loader", options: { base: 2000 } },
"css-loader",
],
},
],
},
};
esModule
類型
type esModule = boolean;
預設值:true
預設情況下,style-loader
會產生使用 ES 模組語法的 JS 模組。在某些情況下,使用 ES 模組是有益的,例如在 模組串接 和 tree shaking 的情況下。
您可以使用以下方式啟用 CommonJS 模組語法
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "style-loader",
options: {
esModule: false,
},
},
],
},
};
對於 production
建置,建議從您的套件中提取 CSS,以便稍後能夠平行載入 CSS/JS 資源。這可以使用 mini-css-extract-plugin 來達成,因為它會建立獨立的 CSS 檔案。對於 development
模式(包括 webpack-dev-server
),您可以使用 style-loader
,因為它會使用多個 <style></style>
將 CSS 注入 DOM,而且執行速度較快。
警告
請勿同時使用
style-loader
和mini-css-extract-plugin
。
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";
module.exports = {
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
devMode ? "style-loader" : MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader",
],
},
],
},
plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};
警告
本機名稱會轉換為
camelCase
。
警告
不允許在 CSS 類別名稱中使用 JavaScript 保留字。
警告
應啟用
css-loader
中的選項esModule
和modules.namedExport
。
styles.css
.foo-baz {
color: red;
}
.bar {
color: blue;
}
index.js
import { fooBaz, bar } from "./styles.css";
console.log(fooBaz, bar);
你可以使用以下方式啟用 ES 模組命名匯出
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
options: {
modules: {
namedExport: true,
},
},
},
],
},
],
},
};
當先前載入器發出原始碼對應時,載入器會自動注入原始碼對應。因此,若要產生原始碼對應,請將前一個載入器的 sourceMap
選項設定為 true
。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
"style-loader",
{ loader: "css-loader", options: { sourceMap: true } },
],
},
],
},
};
如果你正在使用 內容安全政策 (CSP),注入的程式碼通常會遭到封鎖。解決方法是使用 Nonce。不過請注意,使用 Nonce 會大幅降低 CSP 提供的保護。你可以在 規範 中進一步了解安全性影響。較好的解決方案是在製作環境中不要使用這個載入器。
有兩種方法可以使用 nonce
attributes
選項__webpack_nonce__
變數警告
attributes
選項優先於__webpack_nonce__
變數
attributes
component.js
import "./style.css";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
attributes: {
nonce: "12345678",
},
},
},
"css-loader",
],
},
],
},
};
載入器產生
<style nonce="12345678">
.foo {
color: red;
}
</style>
__webpack_nonce__
create-nonce.js
__webpack_nonce__ = "12345678";
component.js
import "./create-nonce.js";
import "./style.css";
require
的替代範例
component.js
__webpack_nonce__ = "12345678";
require("./style.css");
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
載入器產生
<style nonce="12345678">
.foo {
color: red;
}
</style>
在 head
標籤的最上方插入樣式。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: function insertAtTop(element) {
var parent = document.querySelector("head");
var lastInsertedElement =
window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, parent.firstChild);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling);
} else {
parent.appendChild(element);
}
window._lastElementInsertedByStyleLoader = element;
},
},
},
"css-loader",
],
},
],
},
};
插入樣式於 #id
元素之前。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: function insertBeforeAt(element) {
const parent = document.querySelector("head");
const target = document.querySelector("#id");
const lastInsertedElement =
window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, target);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling);
} else {
parent.appendChild(element);
}
window._lastElementInsertedByStyleLoader = element;
},
},
},
"css-loader",
],
},
],
},
};
您可以為 lazyStyleTag
類型定義樣式的自訂目標。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
injectType: "lazyStyleTag",
// Do not forget that this code will be used in the browser and
// not all browsers support latest ECMA features like `let`, `const`, `arrow function expression` and etc,
// we recommend use only ECMA 5 features,
// but it is depends what browsers you want to support
insert: function insertIntoTarget(element, options) {
var parent = options.target || document.head;
parent.appendChild(element);
},
},
},
"css-loader",
],
},
],
},
};
將樣式插入提供的元素或 head
標籤(如果未提供目標)。
custom-square.css
div {
width: 50px;
height: 50px;
background-color: red;
}
custom-square.js
import customSquareStyles from "./custom-square.css";
class CustomSquare extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
const divElement = document.createElement("div");
divElement.textContent = "Text content.";
this.shadowRoot.appendChild(divElement);
customSquareStyles.use({ target: this.shadowRoot });
// You can override injected styles
const bgPurple = new CSSStyleSheet();
const width = this.getAttribute("w");
const height = this.getAttribute("h");
bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);
this.shadowRoot.adoptedStyleSheets = [bgPurple];
// `divElement` will have `100px` width, `100px` height and `red` background color
}
}
customElements.define("custom-square", CustomSquare);
export default CustomSquare;
如果您尚未閱讀我們的貢獻指南,請花點時間閱讀。