将 CSS 注入到 DOM 中。
首先,你需要安装 style-loader
npm install --save-dev style-loader
或
yarn add -D style-loader
或
pnpm add -D style-loader
建议将 style-loader
与 css-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"],
},
],
},
};
此加载器主要用于开发。默认设置不适用于生产环境。有关详细信息,请参阅推荐的示例配置和关于nonce的部分。
injectType
类型
type injectType =
| "styleTag"
| "singletonStyleTag"
| "autoStyleTag"
| "lazyStyleTag"
| "lazySingletonStyleTag"
| "lazyAutoStyleTag"
| "linkTag";
默认值:styleTag
允许你设置样式如何注入到 DOM 中。
可能的值
styleTag
使用多个 <style></style>
标签自动将样式注入到 DOM 中。这是**默认**行为。
component.js
import "./styles.css";
使用 Locals (CSS Modules) 的示例
component-with-css-modules.js
import * as styles from "./styles.css";
const divElement = document.createElement("div");
divElement.className = styles["my-class"];
所有局部变量(类名)都作为命名导出。要实现此行为,你还必须为 css-loader
设置 modules
选项。有关更多信息,请查阅 css-loader
文档。
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" } },
{
loader: "css-loader",
// Uncomment it if you want to use CSS modules
// options: { modules: true }
},
],
},
],
},
};
该加载器注入的样式如下
<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 * as styles from "./styles.css";
const divElement = document.createElement("div");
divElement.className = styles["my-class"];
所有局部变量(类名)都作为命名导出。要实现此行为,你还必须为 css-loader
设置 modules
选项。有关更多信息,请查阅 css-loader
文档。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: { injectType: "singletonStyleTag" },
},
{
loader: "css-loader",
// Uncomment it if you want to use CSS modules
// options: { modules: true }
},
],
},
],
},
};
该加载器注入的样式如下
<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, { "my-class" as myClass } from "./styles.lazy.css";
styles.use();
const divElement = document.createElement("div");
divElement.className = myClass;
所有局部变量(类名)都作为命名导出。要实现此行为,你还必须为 css-loader
设置 modules
选项。有关更多信息,请查阅 css-loader
文档。
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" } },
{
loader: "css-loader",
// Uncomment it if you want to use CSS modules
// options: { modules: true }
},
],
},
],
},
};
该加载器注入的样式如下
<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, { "my-class" as myClass } from "./styles.lazy.css";
styles.use();
const divElement = document.createElement("div");
divElement.className = myClass;
所有局部变量(类名)都作为命名导出。要实现此行为,你还必须为 css-loader
设置 modules
选项。有关更多信息,请查阅 css-loader
文档。
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" },
},
{
loader: "css-loader",
// Uncomment it if you want to use CSS modules
// options: { modules: true }
},
],
},
],
},
};
该加载器生成如下
<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 "./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;
默认值:head
默认情况下,style-loader
会将 <style>
/<link>
元素附加到样式目标的末尾,即页面的 <head>
标签,除非由 insert
指定。
这将导致由加载器创建的 CSS 优先于目标中已存在的 CSS。
如果标准行为不适合你,可以使用其他值,但我们不建议这样做。
如果你指定目标为 iframe,请确保你有足够的访问权限;样式将被注入到内容文档的头部。
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("./path-to-insert-module"),
},
},
"css-loader",
],
},
],
},
};
新的 <style>
/<link>
元素将被插入到 body
标签的底部。
示例
在 head
标签顶部插入样式
insert-function.js
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;
}
module.exports = insertAtTop;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: require.resolve("./insert-function"),
},
},
"css-loader",
],
},
],
},
};
你可以将任何参数传递给 style.use(options)
,这个值将被传递给 insert
和 styleTagTransform
函数。
insert-function.js
function insertIntoTarget(element, options) {
var parent = options.target || document.head;
parent.appendChild(element);
}
module.exports = insertIntoTarget;
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 depends what browsers you want to support
insert: require.resolve("./insert-function.js"),
},
},
"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;
默认值:undefined
字符串
允许你设置自定义函数的绝对路径,该函数可以覆盖默认的 styleTagTransform
行为。
[!警告]
请记住,此代码将在浏览器中使用,并非所有浏览器都支持最新的 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: require.resolve("style-tag-transform-code"),
},
},
"css-loader",
],
},
],
},
};
base
type base = number;
此设置主要用作在使用一个或多个 DllPlugin 时解决 CSS 冲突的变通方法。base
允许你通过指定一个大于 DllPlugin1 使用范围的 CSS 模块 ID 基准,来防止应用的 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 模块是有益的,例如模块串联和摇树优化。
你可以使用以下方式启用 CommonJS 模块语法
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "style-loader",
options: {
esModule: false,
},
},
],
},
};
对于 production
构建,建议从你的 bundle 中提取 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()]),
};
[!警告]
不允许在 CSS 类名中使用 JavaScript 保留字。
[!警告]
css-loader
中的esModule
和modules.namedExport
选项应启用(css-loader@7
默认启用)。
styles.css
.fooBaz {
color: red;
}
.bar {
color: blue;
}
.my-class {
color: green;
}
index.js
import { fooBaz, bar, "my-class" as myClass } from "./styles.css";
console.log(fooBaz, bar, myClass);
或者
index.js
import * as styles from "./styles.css";
console.log(styles.fooBaz, styles.bar, styles["my-class"]);
你可以使用以下方式启用 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
标签顶部插入样式。
insert-function.js
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;
}
module.exports = insertAtTop;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: require.resolve("./insert-function.js"),
},
},
"css-loader",
],
},
],
},
};
在 #id
元素之前插入样式。
insert-function.js
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;
}
module.exports = insertBeforeAt;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: require.resolve("./insert-function.js"),
},
},
"css-loader",
],
},
],
},
};
当你使用 lazyStyleTag
类型时,可以为样式定义自定义目标。
insert-function.js
function insertIntoTarget(element, options) {
var parent = options.target || document.head;
parent.appendChild(element);
}
module.exports = insertIntoTarget;
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: require.resolve("./insert-function.js"),
},
},
"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;
我们欢迎所有贡献!如果您是新用户,请在提交问题或拉取请求之前花一些时间阅读我们的贡献指南。