把 CSS 插入到 DOM 中。
首先,你需要安裝 ?style-loader
?:
npm install --save-dev 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"],
},
],
},
};
名稱 | 類型 | 默認(rèn)值 | 描述 |
---|---|---|---|
injectType
|
{String}
|
styleTag
|
配置把 styles 插入到 DOM 中的方式 |
attributes
|
{Object}
|
{}
|
添加自定義屬性到插入的標(biāo)簽中 |
insert
|
{String|Function}
|
head
|
在指定的位置插入標(biāo)簽 |
styleTagTransform
|
{String|Function}
|
undefined
|
當(dāng)將 'style' 標(biāo)簽插入到 DOM 中時,轉(zhuǎn)換標(biāo)簽和 css |
base
|
{Number}
|
true
|
基于 (DLLPlugin) 設(shè)置 module ID |
esModule
|
{Boolean}
|
false
|
使用 ES modules 語法 |
Type: String Default: styleTag
配置把 styles 插入到 DOM 中的方式。
可選值:
通過使用多個 <style></style> 自動把 styles 插入到 DOM 中。該方式是默認(rèn)行為。
component.js
import "./styles.css";
使用 Locals (CSS Modules) 的例子:
component-with-css-modules.js
import styles from "./styles.css";
const divElement = document.createElement("div");
divElement.className = styles["my-class"];
導(dǎo)入的對象保存著所有的 locals (class names)。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
// 由于是默認(rèn)行為,`injectType` 選項(xiàng)可以省略
{ loader: 'style-loader', options: { injectType: 'styleTag' } },
'css-loader',
],
},
],
},
};
此 loader 插入的 style 效果如下:
<style>
.foo {
color: red;
}
</style>
<style>
.bar {
color: blue;
}
</style>
通過使用一個 <style></style> 來自動把 styles 插入到 DOM 中。
? Source map 不起作用
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"];
導(dǎo)入的對象保存著所有的 locals (class names)。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: { injectType: "singletonStyleTag" },
},
"css-loader",
],
},
],
},
};
loader 插入的 styles 如下:
<style>
.foo {
color: red;
}
.bar {
color: blue;
}
</style>
與 styleTag 相同,但是當(dāng)代碼在 IE6-9 中運(yùn)行時,請打開 singletonStyleTag 模式。
在需要時使用多個 <style></style> 把 styles 插入到 DOM 中。
推薦 lazy style 遵循使用 .lazy.css 作為后綴的命名約定,style-loader 基本用法是使用 .css 作為文件后綴(其他文件也一樣,比如:.lazy.less 和 .less)。
當(dāng)使用 lazyStyleTag 時,style-loader 將惰性插入 styles,在需要使用 styles 時可以通過 style.use() / style.unuse() 使 style 可用。
?? 調(diào)用 unuse 多于 use 時,其表現(xiàn)會不確定。因此,請不要這么做。
component.js
import styles from "./styles.lazy.css";
styles.use();
// 要移除 styles 時你可以調(diào)用
// 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"];
導(dǎo)入的對象的 locals 屬性保存著所有的 locals (class names)。
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 效果如下:
<style>
.foo {
color: red;
}
</style>
<style>
.bar {
color: blue;
}
</style>
在必要時,使用 <style></style> 把 style 插入的 DOM 中。
推薦 lazy style 遵循使用 .lazy.css 作為后綴的命名約定,style-loader 基本用法是使用 .css 作為文件后綴(其他文件也一樣,比如:.lazy.less 和 .less)。
當(dāng)使用 lazySingletonStyleTag 時,style-loader 將惰性插入 styles,在需要使用 styles 時可以通過 style.use() / style.unuse() 使 style 可用。
?? Source maps 不起作用
?? 調(diào)用 unuse 多于 use 時,其表現(xiàn)會不確定。因此,請不要這么做。
component.js
import styles from "./styles.css";
styles.use();
// 要移除 styles 時你可以調(diào)用
// 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"];
導(dǎo)入的對象的 locals 屬性保存著所有的 locals (class names)。
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",
],
},
],
},
};
此 loader 生成的代碼如下:
<style>
.foo {
color: red;
}
.bar {
color: blue;
}
</style>
與 lazyStyleTag 相同,但是當(dāng)代碼在 IE6-9 中運(yùn)行時,請打開 lazySingletonStyleTag 模式。
使用多個 ?<link rel="stylesheet" href="path/to/file.css">
? 將 styles 插入到 DOM 中。
?? 此 loader 會在運(yùn)行時使用 JavaScript 動態(tài)地插入 。要靜態(tài)插入 時請使用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" },
],
},
],
},
};
此 loader 生成的代碼如下:
<link rel="stylesheet" href="path/to/style.css" />
<link rel="stylesheet" href="path/to/other-styles.css" />
Type: ?Object Default: {}
?
如果配置了 attributes,style-loader 將會在 <style> / <link> 上綁定指定的 attributes 以及它們的值。
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>
Type: ?String|Function
? Default: head
默認(rèn)情況下,除非指定 insert,否則 style-loader 會把 <style> / <link> 添加到頁面的 <head> 標(biāo)簽尾部。
這會使得 style-loader 創(chuàng)建的 CSS 比 <head> 標(biāo)簽內(nèi)已經(jīng)存在的 CSS 擁有更高的優(yōu)先級。 當(dāng)默認(rèn)行為不能滿足你的需求時,你可以使用其他值,但我們不推薦這么做。
如果你指定 iframe 作為插入的目標(biāo)時,請確保你有足夠的訪問權(quán)限,styles 將會被插入到 content document 的 head 標(biāo)簽中。
配置 styles 插入 DOM 的自定義 query selector。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: "body",
},
},
"css-loader",
],
},
],
},
};
允許設(shè)置自定義函數(shù)的絕對路徑,該函數(shù)能夠覆蓋默認(rèn)行為并且能夠在任意位置插入樣式。
? 不要忘了這個函數(shù)會在瀏覽器中調(diào)用,由于不是所有瀏覽器都支持最新的 ECMA 特性,如:let,const,arrow function expression 等。我們推薦使用 babel-loader 以支持最新的 ECMA 特性。 ? 不要忘了版本較舊的瀏覽器中某些 DOM 方法并不可用,所以我們推薦只使用 DOM core level 2 properties,但這取決于想要支持的瀏覽器版本。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: require.resolve("modulePath"),
},
},
"css-loader",
],
},
],
},
};
一個新的 <style> 或 <link> 元素將會被插入到 body 標(biāo)簽底部。
允許覆蓋默認(rèn)行為并把 styles 插入到任意位置。
? 不要忘了這個函數(shù)會在瀏覽器中調(diào)用,由于不是所有瀏覽器都支持最新的 ECMA 特性,如:let,const,arrow function expression 等,我們推薦只使用 ECMA 5 特性,但這取決于你想要支持的瀏覽器版本。
? 不要忘了版本較舊的瀏覽器中某些 DOM 方法并不可用,所以我們推薦只使用 DOM core level 2 properties,但這取決于想要支持的瀏覽器版本。
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 標(biāo)簽頂部插入styles。
你可以給 style.use(options) 傳遞任何參數(shù),并且這些值會被傳遞給 insert 與 styleTagTransform 函數(shù)。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
injectType: "lazyStyleTag",
// 不要忘記這些代碼會在瀏覽器中使用,
// 并且不是所有的瀏覽器都支持 `let`、`const`、箭頭函數(shù)表達(dá)式等高級 ECMA 特性。
// 我們建議只使用 ECMA 5 特性,
// 但是這取決于你想支持的瀏覽器
insert: function insertIntoTarget(element, options) {
var parent = options.target || document.head;
parent.appendChild(element);
},
},
},
"css-loader",
],
},
],
},
};
向指定元素添加樣式,沒有指定時將會插入到 head 標(biāo)簽中?,F(xiàn)在你可以向 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 });
// 你可以覆蓋注入的樣式
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` 將會擁有 `100px` 寬,`100px` 高和 `red` 背景顏色
}
}
customElements.define("custom-square", CustomSquare);
export default CustomSquare;
類型:?String | Function
? 默認(rèn)值:undefined
允許設(shè)置自定義函數(shù)的絕對路徑,該函數(shù)能夠覆蓋 styleTagTransform 默認(rèn)行為。
? 不要忘了這個函數(shù)會在瀏覽器中調(diào)用,由于不是所有瀏覽器都支持最新的 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",
],
},
],
},
};
當(dāng)將 'style' 標(biāo)簽插入到 DOM 中時,轉(zhuǎn)換標(biāo)簽和 css。
? 不要忘記該代碼會在瀏覽器中使用,并且不是所有的瀏覽器都支持想 let、const、箭頭函數(shù) 等最新的 ECMA 特性,我們建議僅使用 ECMA5 特性,但這取決于你想支持什么瀏覽器。 ? 不要忘記有一些 DOM 方法在老的瀏覽器中是不可用的,我們推薦只使用 DOM core level 2 properties,但這取決于你想支持什么瀏覽器。
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",
],
},
],
},
};
這個配置主要是作為使用 DllPlugin 時出現(xiàn) css clashes 問題時的解決方案。base 允許你通過指定一個比 DllPlugin1 使用的 css 模塊 id 大的值,來避免應(yīng)用程序中的 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",
],
},
],
},
};
Type: ?Boolean
? Default: true
默認(rèn)情況下,style-loader 生成使用 ES 模塊語法的 JS 模塊。在某些情況下使用 ES 模塊語法更好,比如:module concatenation 和 tree shaking 時。
你可以使用下面的配置啟用 CommonJS 模塊語法:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "style-loader",
options: {
esModule: false,
},
},
],
},
};
對于 production 模式的構(gòu)建,建議從你的包中提取 CSS,以便以后能夠使用 CSS/JS 資源的并行加載。 可以使用 mini-css-extract-plugin 實(shí)現(xiàn),因?yàn)樗梢詣?chuàng)建單獨(dú)的 css 文件。 對于 development 模式(包括 webpack-dev-server),你可以使用 style-loader,因?yàn)樗褂枚鄠€ <style></style> 將 CSS 插入到 DOM 中,并且運(yùn)行得會更快。
? 不要將 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()]),
};
? 本地命名導(dǎo)出時,會將其名稱轉(zhuǎn)換為 camelCase 的形式。
? 并且不允許在 css 的 class 名中使用 JavaScript 的保留字。
? 在 css-loader 中,應(yīng)啟用 esModule 和 modules.namedExport 配置項(xiàng)。
styles.css
.foo-baz {
color: red;
}
.bar {
color: blue;
}
index.js
import { fooBaz, bar } from "./styles.css";
console.log(fooBaz, bar);
你可以使用如下方法為 ES 模塊啟用命名導(dǎo)出功能:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
options: {
modules: {
namedExport: true,
},
},
},
],
},
],
},
};
因此,想要生成 source map,則需將 style-loader 之前執(zhí)行 loader 的 sourceMap 選項(xiàng)設(shè)置為true。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
"style-loader",
{ loader: "css-loader", options: { sourceMap: true } },
],
},
],
},
};
有兩種方式使用 nonce:
? attributes 擁有比 __webpack_nonce__ 更高的優(yōu)先級
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",
],
},
],
},
};
此 loader 生成代碼如下:
<style nonce="12345678">
.foo {
color: red;
}
</style>
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"],
},
],
},
};
此 loader 生成代碼如下:
<style nonce="12345678">
.foo {
color: red;
}
</style>
在 head 標(biāo)簽頂部插入 style。
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 元素前面插入 style。
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 類型定義自定義目標(biāo)。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
injectType: "lazyStyleTag",
// 不要忘記這些代碼會在瀏覽器中使用,
// 并且不是所有的瀏覽器都支持 `let`、`const`、箭頭函數(shù)表達(dá)式等高級 ECMA 特性。
// 我們建議只使用 ECMA 5 特性,
// 但是這取決于你想支持的瀏覽器
insert: function insertIntoTarget(element, options) {
var parent = options.target || document.head;
parent.appendChild(element);
},
},
},
"css-loader",
],
},
],
},
};
向指定元素添加樣式,沒有指定時將會插入到 head 標(biāo)簽中。
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 });
// 你可以覆蓋注入的樣式
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` 將會擁有 `100px` 寬,`100px` 高和 `red` 背景顏色
}
}
customElements.define("custom-square", CustomSquare);
export default CustomSquare;
如果您尚未了解,建議您閱讀以下貢獻(xiàn)指引。
更多建議: