把 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'],
},
],
},
};
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
injectType | {String} | styleTag | 配置把 styles 插入到 DOM 中的方式 |
attributes | {Object} | {} | 添加自定义属性到插入的标签中 |
insert | {String|Function} | head | 在指定的位置插入标签 |
styleTagTransform | {String|Function} | undefined | 当将 'style' 标签插入到 DOM 中时,转换标签和 css |
base | {Number} | true | 基于 (DLLPlugin) 设置 module ID |
esModule | {Boolean} | false | 使用 ES modules 语法 |
injectType
Type: String
Default: styleTag
配置把 styles 插入到 DOM 中的方式。
可选值:
styleTag
singletonStyleTag
autoStyleTag
lazyStyleTag
lazySingletonStyleTag
lazyAutoStyleTag
linkTag
styleTag
通过使用多个 <style></style>
自动把 styles 插入到 DOM 中。该方式是默认行为。
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'];
导入的对象保存着所有的 locals (class names)。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
// 由于是默认行为,`injectType` 选项可以省略
{ loader: 'style-loader', options: { injectType: 'styleTag' } },
'css-loader',
],
},
],
},
};
此 loader 插入的 style 效果如下:
<style>
.foo {
color: red;
}
</style>
<style>
.bar {
color: blue;
}
</style>
singletonStyleTag
通过使用一个 <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'];
导入的对象保存着所有的 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>
autoStyleTag
与 styleTag
相同,但是当代码在 IE6-9 中运行时,请打开 singletonStyleTag
模式。
lazyStyleTag
在需要时使用多个 <style></style>
把 styles 插入到 DOM 中。
推荐 lazy style 遵循使用 .lazy.css
作为后缀的命名约定,style-loader
基本用法是使用 .css
作为文件后缀(其他文件也一样,比如:.lazy.less
和 .less
)。
当使用 lazyStyleTag
时,style-loader
将惰性插入 styles,在需要使用 styles 时可以通过 style.use()
/ style.unuse()
使 style 可用。
⚠️ 调用
unuse
多于use
时,其表现会不确定。因此,请不要这么做。
component.js
import styles from './styles.lazy.css';
styles.use();
// 要移除 styles 时你可以调用
// 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
属性保存着所有的 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>
lazySingletonStyleTag
在必要时,使用 <style></style>
把 style 插入的 DOM 中。
推荐 lazy style 遵循使用 .lazy.css
作为后缀的命名约定,style-loader
基本用法是使用 .css
作为文件后缀(其他文件也一样,比如:.lazy.less
和 .less
)。
当使用 lazySingletonStyleTag
时,style-loader
将惰性插入 styles,在需要使用 styles 时可以通过 style.use()
/ style.unuse()
使 style 可用。
⚠️ Source maps 不起作用
⚠️ 调用
unuse
多于use
时,其表现会不确定。因此,请不要这么做。
component.js
import styles from './styles.css';
styles.use();
// 要移除 styles 时你可以调用
// 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
属性保存着所有的 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>
lazyAutoStyleTag
与 lazyStyleTag
相同,但是当代码在 IE6-9 中运行时,请打开 lazySingletonStyleTag
模式。
linkTag
使用多个 <link rel="stylesheet" href="path/to/file.css">
将 styles 插入到 DOM 中。
ℹ️ 此 loader 会在运行时使用 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' },
],
},
],
},
};
此 loader 生成的代码如下:
<link rel="stylesheet" href="path/to/style.css" />
<link rel="stylesheet" href="path/to/other-styles.css" />
attributes
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>
insert
Type: String|Function
Default: head
默认情况下,除非指定 insert
,否则 style-loader
会把 <style>
/ <link>
添加到页面的 <head>
标签尾部。
这会使得 style-loader
创建的 CSS 比 <head>
标签内已经存在的 CSS 拥有更高的优先级。
当默认行为不能满足你的需求时,你可以使用其他值,但我们不推荐这么做。
如果你指定 iframe 作为插入的目标时,请确保你有足够的访问权限,styles 将会被插入到 content document 的 head 标签中。
String
Selector
配置 styles 插入 DOM 的自定义 query selector。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: 'style-loader',
options: {
insert: 'body',
},
},
'css-loader',
],
},
],
},
};
Absolute path to function
允许设置自定义函数的绝对路径,该函数能够覆盖默认行为并且能够在任意位置插入样式。
⚠ 不要忘了这个函数会在浏览器中调用,由于不是所有浏览器都支持最新的 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
标签底部。
Function
允许覆盖默认行为并把 styles 插入到任意位置。
⚠ 不要忘了这个函数会在浏览器中调用,由于不是所有浏览器都支持最新的 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
标签顶部插入 styles。
你可以给 style.use(options)
传递任何参数,并且这些值会被传递给 insert
与 styleTagTransform
函数。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: 'style-loader',
options: {
injectType: 'lazyStyleTag',
// 不要忘记这些代码会在浏览器中使用,
// 并且不是所有的浏览器都支持 `let`、`const`、箭头函数表达式等高级 ECMA 特性。
// 我们建议只使用 ECMA 5 特性,
// 但是这取决于你想支持的浏览器
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 });
// 你可以覆盖注入的样式
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;
styleTagTransform
类型:String | Function
默认值: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。
⚠ 不要忘记该代码会在浏览器中使用,并且不是所有的浏览器都支持想
let
、const
、箭头函数
等最新的 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',
],
},
],
},
};
base
这个配置主要是作为使用 DllPlugin 时出现 css clashes 问题时的解决方案。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: Boolean
Default: true
默认情况下,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
模式的构建,建议从你的包中提取 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 的 class 名中使用 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,
},
},
},
],
},
],
},
};
因此,想要生成 source map,则需将 style-loader 之前执行 loader 的 sourceMap
选项设置为true
。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
{ loader: 'css-loader', options: { sourceMap: true } },
],
},
],
},
};
有两种方式使用 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',
],
},
],
},
};
此 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
标签顶部插入 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
类型定义自定义目标。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: 'style-loader',
options: {
injectType: 'lazyStyleTag',
// 不要忘记这些代码会在浏览器中使用,
// 并且不是所有的浏览器都支持 `let`、`const`、箭头函数表达式等高级 ECMA 特性。
// 我们建议只使用 ECMA 5 特性,
// 但是这取决于你想支持的浏览器
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 });
// 你可以覆盖注入的样式
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;
Please take a moment to read our contributing guidelines if you haven't yet done so.
Webpack 5 现已正式发布。请阅读我们的 发布公告。如还未准备升级,请阅读 webpack 4 文档。