This README is for babel-loader v8 + Babel v7 Check the 7.x branch for docs with Babel v6
此 package 允许你使用 Babel 和 webpack 转译 JavaScript
文件。
注意:请在 Babel Issues tracker 上报告输出时遇到的问题。
webpack 4.x | babel-loader 8.x | babel 7.x
npm install -D babel-loader @babel/core @babel/preset-env webpack
webpack 文档:Loaders
在 webpack 配置对象中,需要将 babel-loader 添加到 module 列表中,就像下面这样:
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
];
}
查看 babel 选项。
你可以使用 options 属性,来向 loader 传递 options 选项:
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-proposal-object-rest-spread'],
},
},
},
];
}
此 loader 也支持下面这些 loader 特有的选项:
cacheDirectory
:默认值为 false
。当有设置时,指定的目录将用来缓存 loader 的执行结果。之后的 webpack 构建,将会尝试读取缓存,来避免在每次执行时,可能产生的、高性能消耗的 Babel 重新编译过程(recompilation process)。如果设置了一个空值 (loader: 'babel-loader?cacheDirectory'
) 或者 true
(loader: 'babel-loader?cacheDirectory=true'
),loader 将使用默认的缓存目录 node_modules/.cache/babel-loader
,如果在任何根目录下都没有找到 node_modules
目录,将会降级回退到操作系统默认的临时文件目录。
cacheIdentifier
:默认是由 @babel/core
版本号,babel-loader
版本号,.babelrc
文件内容(存在的情况下),环境变量 BABEL_ENV
的值(没有时降级到 NODE_ENV
)组成的一个字符串。可以设置为一个自定义的值,在 identifier 改变后,来强制缓存失效。
cacheCompression
:默认值为 true
。当设置此值时,会使用 Gzip 压缩每个 Babel transform 输出。如果你想要退出缓存压缩,将它设置为 false
-- 如果你的项目中有数千个文件需要压缩转译,那么设置此选项可能会从中收益。
customize
: 默认值为 null
。导出 custom
回调函数的模块路径,例如传入 .custom()
的 callback 函数。由于你必须创建一个新文件才能使用它,建议改为使用 .custom
来创建一个包装 loader。只有在你必须继续直接使用 babel-loader
但又想自定义的情况下,才使用这项配置。
确保转译尽可能少的文件。你可能使用 /\.m?js$/
来匹配,这样也许会去转译 node_modules
目录或者其他不需要的源代码。
要排除 node_modules
,参考文档中的 loaders
配置的 exclude
选项。
你也可以通过使用 cacheDirectory
选项,将 babel-loader 提速至少两倍。这会将转译的结果缓存到文件系统中。
Babel 对一些公共方法使用了非常小的辅助代码,比如 _extend
。默认情况下会被添加到每一个需要它的文件中。
你可以引入 Babel runtime 作为一个独立模块,来避免重复引入。
下面的配置禁用了 Babel 自动对每个文件的 runtime 注入,而是引入 @babel/plugin-transform-runtime
并且使所有辅助代码从这里引用。
更多信息请查看 文档。
注意:你必须执行 npm install -D @babel/plugin-transform-runtime
来把它包含到你的项目中,然后使用 npm install @babel/runtime
把 @babel/runtime
安装为一个依赖。
rules: [
// 'transform-runtime' 插件告诉 Babel
// 要引用 runtime 来代替注入。
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-transform-runtime'],
},
},
},
];
由于 @babel/plugin-transform-runtime 包含了一个 polyfill,含有自定义的 regenerator-runtime 和 core-js, 下面使用 webpack.ProvidePlugin
来配置 shimming 的常用方法将没有作用:
// ...
new webpack.ProvidePlugin({
'Promise': 'bluebird'
}),
// ...
下面这样的写法也没有作用:
require('@babel/runtime/core-js/promise').default = require('bluebird');
var promise = new Promise();
它其实会生成下面这样 (使用了 runtime
后):
'use strict';
var _Promise = require('@babel/runtime/core-js/promise')['default'];
require('@babel/runtime/core-js/promise')['default'] = require('bluebird');
var promise = new _Promise();
前面的 Promise
library 在被覆盖前已经被引用和使用了。
一种可行的办法是,在你的应用程序中加入一个“引导(bootstrap)”步骤,在应用程序开始前先覆盖默认的全局变量。
// bootstrap.js
require('@babel/runtime/core-js/promise').default = require('bluebird');
// ...
require('./app');
babel
的 Node.js API 已经被移到 babel-core
中。如果你收到这个信息,这说明你有一个已经安装的 babel
npm package,并且在 webpack 配置中使用 loader 简写方式(在 webpack 2.x 版本中将不再支持这种方式):
{
test: /\.m?js$/,
loader: 'babel',
}
webpack 将尝试读取 babel
package 而不是 babel-loader
。
想要修复这个问题,你需要卸载 babel
npm package,因为它在 Babel v6 中已经被废除。(安装 @babel/cli
或者 @babel/core
来替代它)
在另一种场景中,如果你的依赖于 babel
而无法删除它,可以在 webpack 配置中使用完整的 loader 名称来解决:
{
test: /\.m?js$/,
loader: 'babel-loader',
}
core-js
和 webpack/buildin
如果被 Babel 转码会发生错误。
你需要在 babel-loader
中排除它们:
{
"loader": "babel-loader",
"options": {
"exclude": [
// \\ for Windows, \/ for Mac OS and Linux
/node_modules[\\\/]core-js/,
/node_modules[\\\/]webpack[\\\/]buildin/,
],
"presets": [
"@babel/preset-env"
]
}
}
Webpack 支持打包成多种 部署目标 。例如,当需要为不同的部署目标(例如 web
与 node
)指定不同的 Babel 配置时, babel-loader 通过 Babel 的caller API 提供了 target
属性。
例如,根据 webpack 的部署目标改变传给@babel/preset-env
的 targets 选项
// babel.config.js
module.exports = (api) => {
return {
plugins: [
'@babel/plugin-proposal-nullish-coalescing-operator',
'@babel/plugin-proposal-optional-chaining',
],
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'entry',
// caller.target 等于 webpack 配置的 target 选项
targets: api.caller((caller) => caller && caller.target === 'node')
? { node: 'current' }
: { chrome: '58', ie: '11' },
},
],
],
};
};
babel-loader
提供了一个 loader-builder 工具函数,
允许用户为 Babel 处理过的每个文件添加自定义处理选项
.custom
接收一个 callback 函数,
它将被调用,并传入 loader 中的 babel
实例,
因此,此工具函数才能够完全确保它使用与 loader 的 @babel/core
相同的实例。
如果你想自定义,但实际上某个文件又不想调用 .custom
,
可以向 customize
选项传入一个字符串,
此字符串指向一个导出 custom
回调函数的文件。
// 从 "./my-custom-loader.js" 中导出,或者任何你想要的文件中导出。
module.exports = require('babel-loader').custom((babel) => {
function myPlugin() {
return {
visitor: {},
};
}
return {
// 传给 loader 的选项。
customOptions({ opt1, opt2, ...loader }) {
return {
// 获取 loader 可能会有的自定义选项
custom: { opt1, opt2 },
// 传入"移除了两个自定义选项"后的选项
loader,
};
},
// 提供 Babel 的 'PartialConfig' 对象
config(cfg) {
if (cfg.hasFilesystemConfig()) {
// 使用正常的配置
return cfg.options;
}
return {
...cfg.options,
plugins: [
...(cfg.options.plugins || []),
// 在选项中包含自定义 plugin
myPlugin,
],
};
},
result(result) {
return {
...result,
code: result.code + '\n// 自定义loader生成',
};
},
};
});
// 然后,在你的 webpack config 文件中
module.exports = {
// ..
module: {
rules: [
{
// ...
loader: path.join(__dirname, 'my-custom-loader.js'),
// ...
},
],
},
};
customOptions(options: Object): { custom: Object, loader: Object }
指定的 loader 的选项,
从 babel-loader
选项中分离出自定义选项。
config(cfg: PartialConfig): Object
指定的 Babel 的 PartialConfig
对象,
返回应该被传递给 babel.transform
的 option
对象。
result(result: Result): Result
指定的 Babel 结果对象,允许 loaders 对它进行额外的调整。
Compile CoffeeScript to JavaScript.
安装 coffeescript
和 coffee-loader
:
npm install --save-dev coffeescript coffee-loader
然后添加 plugin 到 webpack
配置文件. 例:
file.coffee
# 任务:
number = 42
opposite = true
# 条件:
number = -42 if opposite
# 函数:
square = (x) -> x * x
# 数组:
list = [1, 2, 3, 4, 5]
# 对象:
math =
root: Math.sqrt
square: square
cube: (x) -> x * square x
# Splats:
race = (winner, runners...) ->
print winner, runners
# 存在性:
alert "I knew it!" if elvis?
# 数组推导(comprehensions):
cubes = (math.cube num for num in list)
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.coffee$/,
loader: "coffee-loader",
},
],
},
};
替代方案:
import coffee from "coffee-loader!./file.coffee";
然后按偏好运行 webpack
类型:Object
默认:{ bare: true }
所有 coffeescript 选项的文档 点击查看.
transpile
选项的文档 点击查看.
ℹ️
sourceMap
选项从compiler.devtool
中选取一个值作为默认值。
ℹ️
filename
选项从 webpack loader API 中选取一个值。 选项值将被忽略。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.coffee$/,
loader: "coffee-loader",
options: {
bare: false,
transpile: {
presets: ["@babel/env"],
},
},
},
],
},
};
来自 CoffeeScript 2 的文档:
CoffeeScript 2 使用最新的句法生成 JavaScript。 代码运行所在的运行时或浏览器有可能无法支持全部相关句法。 这种情况下,新的 JavaScript 句法将被转换为旧的 JavaScript 句法,以便在较低版本 Node 环境或浏览器中运行这些代码。比如将
{ a } = obj
转换为a = obj.a
。 这个转换的过程是由一些诸如 Babel, Bublé or Traceur Compiler 等转换工具完成的。
安装 @babel/core
和 @babel/preset-env
然后创建配置文件:
npm install --save-dev @babel/core @babel/preset-env
echo '{ "presets": ["@babel/env"] }' > .babelrc
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.coffee$/,
loader: "coffee-loader",
options: {
transpile: {
presets: ["@babel/env"],
},
},
},
],
},
};
开启 Literate CoffeeScript 时需要设置:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.coffee$/,
loader: "coffee-loader",
options: {
literate: true,
},
},
],
},
};
如果您尚未了解,建议您阅读以下贡献指引。
css-loader
会对 @import
和 url()
进行处理,就像 js 解析 import/require()
一样。
如果要使用 css-loader,你需要安装 webpack@5
首先,你需要先安装 css-loader
:
npm install --save-dev css-loader
然后把 loader 引用到你 webpack
的配置中。如下所示:
file.js
import css from 'file.css';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
};
然后运行 webpack
。
如果由于某种原因你需要将 CSS 提取为一个文件(即不要将 CSS 存储在 JS 模块中),你可能想要查看 推荐示例。
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
url | {Boolean|Function} | true | 启用/禁用 url() /image-set() 函数处理 |
import | {Boolean|Function} | true | 启用/禁用 @import 规则进行处理 |
modules | {Boolean|String|Object} | {auto: true} | 启用/禁用 CSS 模块及其配置 |
sourceMap | {Boolean} | compiler.devtool | 启用/禁用生成 SourceMap |
importLoaders | {Number} | 0 | 启用/禁用或者设置在 css-loader 前应用的 loader 数量 |
esModule | {Boolean} | true | 使用 ES 模块语法 |
exportType | {'array' | 'string' | 'css-style-sheet'} | array | 允许导出样式为模块数组、字符串或者 可构造样式(即 CSSStyleSheet ) |
url
类型: Boolean|Object
默认值: true
启用/禁用 url
/image-set
函数进行处理。
如果设置为 false
,css-loader
将不会解析 url
或者 image-set
中的任何路径。
还可以传递给一个函数基于资源的路径动态地控制这种行为。
绝对路径和根目录的相对 URL 现在会被解析(版本 4.0.0。
示例解决方案:
url(image.png) => require('./image.png')
url('image.png') => require('./image.png')
url(./image.png) => require('./image.png')
url('./image.png') => require('./image.png')
url('http://dontwritehorriblecode.com/2112.png') => require('http://dontwritehorriblecode.com/2112.png')
image-set(url('image2x.png') 1x, url('image1x.png') 2x) => require('./image1x.png') and require('./image2x.png')
要从 node_modules
目录(包括 resolve.modules
)导入资源,而对于 alias
,请加上一个前缀 ~
:
url(~module/image.png) => require('module/image.png')
url('~module/image.png') => require('module/image.png')
url(~aliasDirectory/image.png) => require('otherDirectory/image.png')
Boolean
启用/禁用 url()
解析。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
url: true,
},
},
],
},
};
Object
允许过滤 url()
。所有过滤的内容 url()
都不会解析(保留编写时的代码)。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
url: {
filter: (url, resourcePath) => {
// resourcePath - css 文件的路径
// 不处理 `img.png` url
if (url.includes('img.png')) {
return false;
}
return true;
},
},
},
},
],
},
};
import
类型: Boolean|Object
默认值: true
启用/禁用 @import
规则进行处理。
控制 @import
的解析。@import
中的绝对 URL 会被直接移到运行时去处理。
示例解决方案:
@import 'style.css' => require('./style.css')
@import url(style.css) => require('./style.css')
@import url('style.css') => require('./style.css')
@import './style.css' => require('./style.css')
@import url(./style.css) => require('./style.css')
@import url('./style.css') => require('./style.css')
@import url('http://dontwritehorriblecode.com/style.css') => @import url('http://dontwritehorriblecode.com/style.css') in runtime
要从 node_modules
目录(包括 resolve.modules
)导入样式,而对于 alias
,请加上一个前缀 ~
:
@import url(~module/style.css) => require('module/style.css')
@import url('~module/style.css') => require('module/style.css')
@import url(~aliasDirectory/style.css) => require('otherDirectory/style.css')
Boolean
启用/禁用 @import
解析。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
import: true,
},
},
],
},
};
Object
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
filter | {Function} | undefined | 允许过滤 @import |
filter
类型:Function
默认值:undefined
允许过滤 @import
。所有过滤的内容 @import
都不会解析(保留编写时的代码)。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
import: {
filter: (url, media, resourcePath) => {
// resourcePath - css 文件路径
// 不处理 `style.css` 的导入
if (url.includes('style.css')) {
return false;
}
return true;
},
},
},
},
],
},
};
modules
类型:Boolean|String|Object
默认值:undefined
启用/禁用 CSS 模块或者 ICSS 及其配置:
undefined
- 为所有匹配 /\.module\.\w+$/i.test(filename)
与 /\.icss\.\w+$/i.test(filename)
正则表达式的文件启用 CSS 模块。true
- 对所有文件启用 CSS 模块。false
- 对所有文件禁用 CSS 模块。string
- 对所有文件禁用 CSS 模块并设置 mode
配置项,你可以在 这里 获得更多信息。object
- 如果没有配置 modules.auto
则对所有文件启用 CSS 模块,否则 modules.auto
配置项则会决定其是否为 CSS 模块,你可以在 这里 获得更多信息。该 modules
选项启用/禁用 CSS 模块 规范并且设置基本的行为。
设置为 false
值会提升性能,因为避免了 CSS Modules 特性的解析,这对于使用普通 CSS 或者其他技术的开发人员是非常有用的。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
};
Features
Scope
使用 local
值要求你指定 :global
类。
使用 global
值要求你指定 :local
类。
使用 pure
值则要求必须至少包含一个局部类或者 id。
你可以点击 此处 了解更多。
样式可以在局部作用域中,避免影响全局作用域的样式。
语法 :local(.className)
可以被用来在局部作用域中声明 className。局部的作用域标识符会以模块形式暴露出去。
使用 :local
(无括号)可以为此选择器启用局部模式。
:global(.className)
可以用来声明一个明确的全局选择器。
使用 :global
(无括号)可以将此选择器切换至全局模式。
loader 会用唯一的标识符 (identifier) 来替换局部选择器。所选择的唯一标识符以模块形式暴露出去。
:local(.className) {
background: red;
}
:local .className {
color: green;
}
:local(.className .subClass) {
color: green;
}
:local .className .subClass :global(.global-class-name) {
color: blue;
}
._23_aKvs-b8bW2Vg3fwHozO {
background: red;
}
._23_aKvs-b8bW2Vg3fwHozO {
color: green;
}
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 {
color: green;
}
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 .global-class-name {
color: blue;
}
ℹ️ 被导出的标识符
exports.locals = {
className: '_23_aKvs-b8bW2Vg3fwHozO',
subClass: '_13LGdX8RMStbBE9w-t0gZ1',
};
本地选择器推荐使用驼峰命名。它们在导入的 JS 模块中更容易使用。
你也可以使用 :local(#someId)
,但这并不推荐。应该使用类去代替 id。
Composing
声明本地类名时,可以从另一个本地类名组成一个本地类。
:local(.className) {
background: red;
color: yellow;
}
:local(.subClass) {
composes: className;
background: blue;
}
这不会导致 CSS 本身发生任何变化,但是会导出多个类名。
exports.locals = {
className: '_23_aKvs-b8bW2Vg3fwHozO',
subClass: '_13LGdX8RMStbBE9w-t0gZ1 _23_aKvs-b8bW2Vg3fwHozO',
};
._23_aKvs-b8bW2Vg3fwHozO {
background: red;
color: yellow;
}
._13LGdX8RMStbBE9w-t0gZ1 {
background: blue;
}
Importing
从另一个模块导入本地类名。
我强烈建议您在导入文件时指定扩展名,因为可以导入具有任何扩展名的文件,而且事先并不能知道要使用哪个文件。
:local(.continueButton) {
composes: button from 'library/button.css';
background: red;
}
:local(.nameEdit) {
composes: edit highlight from './edit.css';
background: red;
}
要从多个模块导入,请使用多个 composes:
规则。
:local(.className) {
composes: edit hightlight from './edit.css';
composes: button from 'module/button.css';
composes: classFromThisModule;
background: red;
}
Values
可以使用 @value
来指定在整个文档中都能被重复使用的值,
我们推荐对特定的值使用 v-
的前缀,给选择器使用 s-
的前缀,并且为媒体规则使用 m-
前缀。
@value v-primary: #BF4040;
@value s-black: black-selector;
@value m-large: (min-width: 960px);
.header {
color: v-primary;
padding: 0 10px;
}
.s-black {
color: black;
}
@media m-large {
.header {
padding: 0 20px;
}
}
Boolean
启用 CSS 模块 功能。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
};
String
启用 CSS 模块 功能和设置 mode
。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
// 使用 `local` 同使用 `modules: true` 的效果是一样的
modules: 'global',
},
},
],
},
};
Object
启用 CSS 模块 功能和设置选项。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
mode: 'local',
auto: true,
exportGlobals: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]',
localIdentContext: path.resolve(__dirname, 'src'),
localIdentHashSalt: 'my-custom-hash',
namedExport: true,
exportLocalsConvention: 'camelCase',
exportOnlyLocals: false,
},
},
},
],
},
};
auto
类型:Boolean|RegExp|Function
默认值:undefined
当 modules
配置项为对象时允许基于文件名自动启用 CSS 模块或者 ICSS。
有效值:
undefined
- 为所有文件启用 CSS 模块。true
- 为所有匹配 /\.module\.\w+$/i.test(filename)
和 /\.icss\.\w+$/i.test(filename)
正则表达式的文件启用 CSS 模块。false
- 禁用 CSS 模块。RegExp
- 为所有匹配 /RegExp/i.test(filename)
正则表达式的文件禁用 CSS 模块。function
- 为所有通过基于文件名的过滤函数校验的文件启用 CSS 模块。Boolean
可能的值:
true
- 启用 CSS 模块或者可交互 CSS 格式,为所有满足 /\.module(s)?\.\w+$/i.test(filename)
条件的文件设置 modules.mode
选项为 local
,或者为所有满足 /\.icss\.\w+$/i.test(filename)
条件的文件设置 modules.mode
选项为 icss
false
- 禁用 css 模块或者基于文件名的可交互 CSS 格式webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
auto: true,
},
},
},
],
},
};
RegExp
根据正则表达式检查文件名,为匹配的文件启用 css 模块。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
auto: /\.custom-module\.\w+$/i,
},
},
},
],
},
};
Function
根据过滤器检查文件名,为满足过滤要求的文件启用 css 模块。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
auto: (resourcePath) => resourcePath.endsWith('.custom-module.css'),
},
},
},
],
},
};
mode
类型:String|Function
默认:'local'
设置 mode
选项。需要 local
模式时可以忽略该值。
控制应用于输入样式的编译级别。
local
、global
和 pure
处理 class
和 id
域以及 @value
值。
icss
只会编译底层的 Interoperable CSS
格式,用于声明 CSS 和其他语言之间的 :import
和 :export
依赖关系。
ICSS 提供 CSS Module 支持,并且为其他工具提供了一个底层语法,以实现它们自己的 css-module 变体。
String
可选值 - local
、global
、pure
和 icss
。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
mode: 'global',
},
},
},
],
},
};
Function
允许根据文件名设置不同的 mode
选项值。
可能的返回值 - local
、global
、pure
和 icss
。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
// 回调必须返回 `local`,`global`,或者 `pure`
mode: (resourcePath) => {
if (/pure.css$/i.test(resourcePath)) {
return 'pure';
}
if (/global.css$/i.test(resourcePath)) {
return 'global';
}
return 'local';
},
},
},
},
],
},
};
localIdentName
类型:String
默认:'[hash:base64]'
允许配置生成的本地标识符(ident)。
更多关于配置项的信息可以查看:
支持的模板字符串:
[name]
源文件名称[folder]
文件夹相对于 compiler.context
或者 modules.localIdentContext
配置项的相对路径。[path]
源文件相对于 compiler.context
或者 modules.localIdentContext
配置项的相对路径。[file]
- 文件名和路径。[ext]
- 文件拓展名。[hash]
- 字符串的哈希值。基于 localIdentHashSalt
、localIdentHashFunction
、localIdentHashDigest
、localIdentHashDigestLength
、localIdentContext
、resourcePath
和 exportName
生成。[<hashFunction>:hash:<hashDigest>:<hashDigestLength>]
- 带有哈希设置的哈希。[local]
- 原始类名。建议:
'[path][name]__[local]'
'[hash:base64]'
[local]
占位符包含原始的类。
**注意:**所有保留 (<>:"/\|?*
) 和控制文件系统字符 (不包括 [local]
占位符) 都将转换为 -
。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
localIdentName: '[path][name]__[local]--[hash:base64:5]',
},
},
},
],
},
};
localIdentContext
类型:String
默认:compiler.context
允许为本地标识符名称重新定义基本的 loader 上下文。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
localIdentContext: path.resolve(__dirname, 'src'),
},
},
},
],
},
};
localIdentHashSalt
类型:String
默认:undefined
允许添加自定义哈希值以生成更多唯一类。 更多信息请查看 output.hashSalt。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
localIdentHashSalt: 'hash',
},
},
},
],
},
};
localIdentHashFunction
类型:String
默认值:md4
允许设置生成 class 的哈希函数。 更多信息请查看 output.hashFunction。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
localIdentHashFunction: 'md4',
},
},
},
],
},
};
localIdentHashDigest
类型:String
默认值:hex
允许设置生成 class 的哈希摘要。 更多信息请查看 output.hashDigest。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
localIdentHashDigest: 'base64',
},
},
},
],
},
};
localIdentHashDigestLength
$#localidentHashdigestlength$类型:Number
默认值:20
允许设置生成 class 的哈希摘要长度。 更多信息请查看 output.hashDigestLength。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
localIdentHashDigestLength: 5,
},
},
},
],
},
};
localIdentRegExp
类型:String|RegExp
默认:undefined
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
localIdentRegExp: /page-(.*)\.css/i,
},
},
},
],
},
};
getLocalIdent
类型:Function
默认:undefined
可以指定自定义 getLocalIdent
函数的绝对路径,以基于不同的架构生成类名。
默认情况下,我们使用内置函数来生成 classname。
如果自定义函数返回 null
或者 undefined
,
我们将降级使用内置函数来生成 classname。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
getLocalIdent: (context, localIdentName, localName, options) => {
return 'whatever_random_class_name';
},
},
},
},
],
},
};
namedExport
类型:Boolean
默认:false
本地环境启用/禁用 export 的 ES 模块。
⚠ 本地环境的命名将转换为驼峰格式,即
exportLocalsConvention
选项默认设置了camelCaseOnly
。
⚠ 不允许在 CSS 类名中使用 JavaScript 保留字。
styles.css
.foo-baz {
color: red;
}
.bar {
color: blue;
}
index.js
import { fooBaz, bar } from './styles.css';
console.log(fooBaz, bar);
可以使用以下命令启用 export 的 ES 模块:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
esModule: true,
modules: {
namedExport: true,
},
},
},
],
},
};
可以为 namedExport 设置一个自定义名称,可以使用 exportLocalsConvention
配置项作为一个函数。
可前往 examples
章节查看示例。
exportGlobals
类型:Boolean
默认:false
允许 css-loader
从全局类或 ID 导出名称,因此您可以将其用作本地名称。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
exportGlobals: true,
},
},
},
],
},
};
exportLocalsConvention
类型:String|Function
默认:取决于 modules.namedExport
选项值,如果为 true
则对应的是 camelCaseOnly
,反之对应的是 asIs
导出的类名称的样式。
String
默认情况下,导出的 JSON 密钥反映了类名(即 asIs
值)。
⚠ 如果你设置
namedExport
为true
那么只有camelCaseOnly
被允许。
名称 | 类型 | 描述 |
---|---|---|
'asIs' | {String} | 类名将按原样导出。 |
'camelCase' | {String} | 类名将被驼峰化,原类名不会从局部环境删除 |
'camelCaseOnly' | {String} | 类名将被驼峰化,原类名从局部环境删除 |
'dashes' | {String} | 类名中只有破折号会被驼峰化 |
'dashesOnly' | {String} | 类名中破折号会被驼峰,原类名从局部环境删除 |
file.css
.class-name {
}
file.js
import { className } from 'file.css';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
exportLocalsConvention: 'camelCase',
},
},
},
],
},
};
Function
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
exportLocalsConvention: function (name) {
return name.replace(/-/g, '_');
},
},
},
},
],
},
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
exportLocalsConvention: function (name) {
return [
name.replace(/-/g, '_'),
// dashesCamelCase
name.replace(/-+(\w)/g, (match, firstLetter) =>
firstLetter.toUpperCase()
),
];
},
},
},
},
],
},
};
exportOnlyLocals
类型:Boolean
默认:false
仅导出局部环境。
使用 css 模块 进行预渲染(例如 SSR)时很有用。
要进行预渲染,预渲染包 应使用 mini-css-extract-plugin
选项而不是 style-loader!css-loader
。
它不嵌入 CSS,而仅导出标识符映射。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
exportOnlyLocals: true,
},
},
},
],
},
};
importLoaders
类型:Number
默认:0
允许为 @import
样式规则、CSS 模块或者 ICSS 启用/禁用或设置在 CSS loader 之前应用的 loader 的数量,例如:@import
/composes
/@value value from './values.css'
等。
importLoaders
选项允许你配置在 css-loader
之前有多少 loader 应用于 @import
ed 资源与 CSS 模块/ICSS 导入。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
// 0 => no loaders (default);
// 1 => postcss-loader;
// 2 => postcss-loader, sass-loader
},
},
'postcss-loader',
'sass-loader',
],
},
],
},
};
当模块系统(即 webpack)支持按来源匹配 loader 时,这种情况将来可能会改变。
sourceMap
类型:Boolean
默认值:取决于 compiler.devtool
值
source map 的生成默认依赖 devtool
配置项。除了 eval
与 false
之外的值都会启用 source map。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
sourceMap: true,
},
},
],
},
};
esModule
类型:Boolean
默认:true
默认情况下,css-loader
生成使用 ES 模块语法的 JS 模块。
在某些情况下,使用 ES 模块是有益的,例如在模块串联或 tree shaking 时。
你可以使用以下方式启用 CommonJS 模块语法:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
esModule: false,
},
},
],
},
};
exportType
类型:'array' | 'string' | 'css-style-sheet'
默认值:'array'
允许导出样式为模块数组、字符串或者 可构造样式(即 CSSStyleSheet
)。
默认值为 'array'
,即 loader 导出具有特定 API 的模块数组,用于 style-loader
或其他。
webpack.config.js
module.exports = {
module: {
rules: [
{
assert: { type: 'css' },
loader: 'css-loader',
options: {
exportType: 'css-style-sheet',
},
},
],
},
};
src/index.js
import sheet from './styles.css' assert { type: 'css' };
document.adoptedStyleSheets = [sheet];
shadowRoot.adoptedStyleSheets = [sheet];
'array'
loader 导出具有特定 API 的模块数组,用于 style-loader
或其他。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/i,
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
},
],
},
};
src/index.js
// `style-loader` applies styles to DOM
import './styles.css';
'string'
⚠ 你不再需要
style-loader
,请移除它。 ⚠ 如果你想使用CSS modules
,应该启用esModules
配置项,默认情况下,本地变量会被 具名导出。
默认导出为 string
。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/i,
use: ['css-loader', 'postcss-loader', 'sass-loader'],
},
],
},
};
src/index.js
import sheet from './styles.css';
console.log(sheet);
'css-style-sheet'
⚠ 不再允许使用
@import
规则,更多 信息 ⚠ 你不再需要style-loader
,请移除它。 ⚠ 如果你想使用CSS modules
,应该启用esModules
配置项,默认情况下,本地变量会被 具名导出。 ⚠ 目前在Chrome
中不支持 Source maps,因为有该 bug
默认导出是一个 可构造样式 (即 CSSStyleSheet
)。
对 自定义元素 以及 shadow DOM 有用处。
更多信息:
webpack.config.js
module.exports = {
module: {
rules: [
{
assert: { type: 'css' },
loader: 'css-loader',
options: {
exportType: 'css-style-sheet',
},
},
// For Sass/SCSS:
//
// {
// assert: { type: "css" },
// rules: [
// {
// loader: "css-loader",
// options: {
// exportType: "css-style-sheet",
// // Other options
// },
// },
// {
// loader: "sass-loader",
// options: {
// // Other options
// },
// },
// ],
// },
],
},
};
src/index.js
// Example for Sass/SCSS:
// import sheet from "./styles.scss" assert { type: "css" };
// Example for CSS modules:
// import sheet, { myClass } from "./styles.scss" assert { type: "css" };
// Example for CSS:
import sheet from './styles.css' assert { type: 'css' };
document.adoptedStyleSheets = [sheet];
shadowRoot.adoptedStyleSheets = [sheet];
对于迁移,你可以使用以下配置:
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
oneOf: [
{
assert: { type: 'css' },
loader: 'css-loader',
options: {
exportType: 'css-style-sheet',
// Other options
},
},
{
use: [
'style-loader',
{
loader: 'css-loader',
options: {
// Other options
},
},
],
},
],
},
],
},
};
推荐 production
环境的构建将 CSS 从你的 bundle 中分离出来,这样可以使用 CSS/JS 文件的并行加载。
这可以通过使用 mini-css-extract-plugin
来实现,因为它可以创建单独的 CSS 文件。
对于 development
模式(包括 webpack-dev-server
),你可以使用 style-loader,因为它可以使用多个 标签将 CSS 插入到 DOM 中,并且反应会更快。
i 不要同时使用
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$/i,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
],
},
],
},
plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};
/* webpackIgnore: true */
注释禁用 url 解析有了 /* webpackIgnore: true */
注释,可以禁用对规则和单个声明的源处理。
/* webpackIgnore: true */
@import url(./basic.css);
@import /* webpackIgnore: true */ url(./imported.css);
.class {
/* 对 'background' 声明中的所有 url 禁用 url 处理 */
color: red;
/* webpackIgnore: true */
background: url('./url/img.png'), url('./url/img.png');
}
.class {
/* 对 'background' 声明中第一个 url 禁用 url 处理 */
color: red;
background:
/* webpackIgnore: true */ url('./url/img.png'), url('./url/img.png');
}
.class {
/* 对 'background' 声明中第二个 url 禁用 url 处理 */
color: red;
background: url('./url/img.png'),
/* webpackIgnore: true */ url('./url/img.png');
}
/* prettier-ignore */
.class {
/* 对 'background' 声明中第二个 url 禁用 url 处理 */
color: red;
background: url("./url/img.png"),
/* webpackIgnore: true */
url("./url/img.png");
}
/* prettier-ignore */
.class {
/* 对 'background-image' 声明中第三和第六个 url 禁用 url 处理 */
background-image: image-set(
url(./url/img.png) 2x,
url(./url/img.png) 3x,
/* webpackIgnore: true */ url(./url/img.png) 4x,
url(./url/img.png) 5x,
url(./url/img.png) 6x,
/* webpackIgnore: true */
url(./url/img.png) 7x
);
}
如下配置的 webpack.config.js
可以加载 CSS 文件,嵌入小的 PNG/JPG/GIF/SVG 图片以及字体作为数据 URL,并将较大的文件复制到输出目录。
对于 webpack v5:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
// 更多信息请点击这里 https://webpack.js.org/guides/asset-modules/
type: 'asset',
},
],
},
};
For production builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on.
This can be achieved by using the mini-css-extract-plugin to extract the CSS when running in production mode.
As an alternative, if seeking better development performance and css outputs that mimic production. extract-css-chunks-webpack-plugin offers a hot module reload friendly, extended version of mini-css-extract-plugin. HMR real CSS files in dev, works like mini-css in non-dev
如果项目中没有纯 CSS(没有 CSS 模块),CSS 模块和 PostCSS,则可以使用以下设置:
webpack.config.js
module.exports = {
module: {
rules: [
{
// 对于 pure CSS - /\.css$/i,
// 对于 Sass/SCSS - /\.((c|sa|sc)ss)$/i,
// 对于 Less - /\.((c|le)ss)$/i,
test: /\.((c|sa|sc)ss)$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
// 每一个 CSS 的 `@import` 与 CSS 模块/ICSS 都会运行 `postcss-loader`,不要忘了 `sass-loader` 将不属于 CSS 的 `@import` 编译到一个文件中
// 如果您需要在每个 CSS 的 `@import` 上运行 `sass-loader` 和 `postcss-loader`,请将其设置为 `2`。
importLoaders: 1,
},
},
{
loader: 'postcss-loader',
options: { plugins: () => [postcssPresetEnv({ stage: 0 })] },
},
// 也可能是 `less-loader`
{
loader: 'sass-loader',
},
],
},
// 对于 webpack v5
{
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
// More information here https://webpack.js.org/guides/asset-modules/
type: 'asset',
},
],
},
};
index.css
.class {
background: url(/assets/unresolved/img.png);
}
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
resolve: {
alias: {
'/assets/unresolved/img.png': path.resolve(
__dirname,
'assets/real-path-to-img/img.png'
),
},
},
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
namedExport: true,
exportLocalsConvention: function (name) {
return name.replace(/-/g, '_');
},
},
},
},
],
},
};
可交互的 CSS
使其与 CSS Module
特性分离下面是有关配置的示例代码,通过为所有未匹配到 *.module.scss
命名约定文件设置 mode
选项,只允许使用 可交互的 CSS
特性(如 :import
和 :export
),而不使用其他的 CSS Module
特性。此处仅供参考,因为在 v4 之前,css-loader
默认将 ICSS
特性应用于所有文件。
同时,在本示例中,匹配到 *.module.scss
的所有文件都将被视为 CSS Modules
。
假设项目中有这样一个需求,要求 canvas 绘制使用的变量与 CSS 同步,换句话说就是 canvas 绘制使用的颜色(在 JavaScript 中设置的颜色名)与 HTML 背景(在 CSS 中通过 class 设置)相同。
webpack.config.js
module.exports = {
module: {
rules: [
// ...
// --------
// SCSS ALL EXCEPT MODULES
{
test: /\.scss$/i,
exclude: /\.module\.scss$/i,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: {
mode: 'icss',
},
},
},
{
loader: 'sass-loader',
},
],
},
// --------
// SCSS MODULES
{
test: /\.module\.scss$/i,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: {
mode: 'local',
},
},
},
{
loader: 'sass-loader',
},
],
},
// --------
// ...
],
},
};
variables.scss
文件被视为仅使用 ICSS
。
$colorBackground: red;
:export {
colorBackgroundCanvas: $colorBackground;
}
Component.module.scss
文件被视为 CSS Module
。
@import 'variables.scss';
.componentClass {
background-color: $colorBackground;
}
Component.jsx
在 JavaScript 中直接使用 CSS Module
的特性以及 SCSS 声明的变量。
import svars from 'variables.scss';
import styles from 'Component.module.scss';
// Render DOM with CSS modules class name
// <div className={styles.componentClass}>
// <canvas ref={mountsCanvas}/>
// </div>
// Somewhere in JavaScript canvas drawing code use the variable directly
// const ctx = mountsCanvas.current.getContext('2d',{alpha: false});
ctx.fillStyle = `${svars.colorBackgroundCanvas}`;
如果您还没有阅读,请花一点时间阅读我们的贡献指南。
允许对源文件设置 module.exports
/export
。
当源文件不包含 exports 或者有一些内容没有 export 时是有用的。
想要获取有关兼容性的进一步提示,请查看官方文档中的 Shimming。
⚠ 默认情况下,loader 生成具名的 ES module。
⚠ 请注意,原始代码中现有的 exports(
export
/module.exports
/exports
)和导出新值可能会导致失败。
首先,你需要安装 exports-loader
:
npm install exports-loader --save-dev
可以使用 |
或者 %20
(空格)分隔 export 中的 syntax
,name
和 alias
。
可以在这里获取文档和语法实例。
⚠
%20
是查询字符串中的空格,因为你不能在 URL 中使用空格
然后将 loader 添加到所需的 import
语句或 require
调用中。例如:
import { myFunction } from 'exports-loader?exports=myFunction!./file.js';
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// export { myFunction }
myFunction('Hello world');
import {
myVariable,
myFunction,
} from 'exports-loader?exports=myVariable,myFunction!./file.js';
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// export { myVariable, myFunction };
const newVariable = myVariable + '!!!';
console.log(newVariable);
myFunction('Hello world');
const {
myFunction,
} = require('exports-loader?type=commonjs&exports=myFunction!./file.js');
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// module.exports = { myFunction }
myFunction('Hello world');
// 替换语法:
// import myFunction from 'exports-loader?exports=default%20myFunction!./file.js';
import myFunction from 'exports-loader?exports=default|myFunction!./file.js';
// `%20` 是查询字符串中的空格,等同于 `default myFunction`
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// exports default myFunction;
myFunction('Hello world');
const myFunction = require('exports-loader?type=commonjs&exports=single|myFunction!./file.js');
// `|` 是查询字符串中的分隔符, 等同于 `single|myFunction`
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// module.exports = myFunction;
myFunction('Hello world');
import { myFunctionAlias } from 'exports-loader?exports=named|myFunction|myFunctionAlias!./file.js';
// `|` 是查询字符串中的分隔符, 等同于 `named|myFunction|myFunctionAlias`
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// exports { myFunction as myFunctionAlias };
myFunctionAlias('Hello world');
可以在下面的文档中找到字段值的含义。
webpack.config.js
module.exports = {
module: {
rules: [
{
// 你可以使用 `regexp`
// test: /vendor\.js/$
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
exports: 'myFunction',
},
},
],
},
};
然后用你喜欢的方式运行 webpack
。
Name | Type | Default | Description |
---|---|---|---|
type | {String} | module | 生成导出的格式 |
exports | {String|Object|Array<String|Object>} | undefined | 导出的列表 |
type
类型:String
默认值:module
生成导出的格式
可选值 - commonjs
(CommonJS 模块语法)和 module
(ES 模块语法)。
commonjs
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'Foo',
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
module.exports = { Foo };
module
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
type: 'module',
exports: 'Foo',
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
export { Foo };
exports
类型:String|Array
默认值:undefined
导出的列表。
String
允许使用一个字符串来描述导出。
Syntax
可以使用 |
或者 %20
(空格)分隔 export 中的 syntax
,name
和 alias
。
字符串语法 - [[syntax] [name] [alias]]
或者 [[syntax]|[name]|[alias]]
,含义如下:
[syntax]
(可以省略) -
type
为 module
- 可以是 default
和 named
,type
为 commonjs
- 可以使 single
和 multiple
[name]
- 导出值的名称 (必填项)
[alias]
- 导出值的别名 (可以省略)
Examples:
[Foo]
- 生成 export { Foo };
.[default Foo]
- 生成 export default Foo;
.[named Foo]
- 生成 export { Foo };
.[named Foo FooA]
- 生成 export { Foo as FooA };
.[single Foo]
- 生成 module.exports = Foo;
.[multiple Foo]
- 生成 module.exports = { Foo };
.[multiple Foo FooA]
- 生成 module.exports = { 'FooA': Foo };
.[named [name] [name]Alias]
- 生成名为 exports 的 ES 模块,并导出等于另一个名称下的文件名的值., 对于 single.js
将会是 single
and 和singleAlias
, 生成 export { single as singleAlias };
.⚠ 你需要设置
type: "commonjs"
才能使用single
或者multiple
语法。
⚠ 别名不能与
default
或者single
语法一起使用。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
exports: 'default Foo',
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
export default Foo;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
exports: 'named Foo FooA',
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
export { Foo as FooA };
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single Foo',
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
module.exports = Foo;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'multiple Foo FooA',
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
module.exports = { FooA: Foo };
Object
允许使用对象来描述导出。
属性:
syntax
- 对于 module
类型(ES modules
模块格式)可以是 default
或者 named
,对于 commonjs
类型(CommonJS
模块格式)可以是 single
或者 multiple
(可以省略)name
- 导出值的名称 (required)alias
- 导出值的别名 (may be omitted)webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
exports: {
syntax: 'default',
name: 'Foo',
},
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
export default Foo;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
exports: {
syntax: 'named',
name: 'Foo',
alias: 'FooA',
},
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
export { Foo as FooA };
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: {
syntax: 'single',
name: 'Foo',
},
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
module.exports = Foo;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: {
syntax: 'multiple',
name: 'Foo',
alias: 'FooA',
},
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
module.exports = { FooA: Foo };
Array
允许指定多个导出。 每一个可以是 string
或者 object
.
⚠ 因为 CommonJS 格式限制,不能将
single
与multiple
语法一起使用。
⚠ 因为 ES module 格式限制,不能导出多个
default
值。
⚠ 因为 CommonJS 格式限制,不能导出多个
single
值。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: ['Foo', 'multiple Bar', 'multiple Baz BazA'],
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
module.exports = { Foo, Bar, BazA: Bar };
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
exports: ['default Foo', 'named Bar BarA'],
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
export default Foo;
export { Bar as BarA };
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/vendor.js'),
loader: 'exports-loader',
options: {
exports: [
{ syntax: 'named', name: 'Foo', alias: 'FooA' },
{ syntax: 'named', name: 'Bar' },
'Baz',
],
},
},
],
},
};
生成的输出结果:
// ...
// Code
// ...
export { Foo as FooA, Bar, Baz };
如果您还没有阅读,请花一点时间阅读我们的贡献指南。
expose-loader
允许暴露一个模块(整体或者部分)给全局对象(self
、window
和 global
)。
想要获取有关兼容性的进一步提示,请查看官方文档中的 Shimming。
首先,你需要安装 expose-loader
:
npm install expose-loader --save-dev
(如果你在使用 webpack4,请安装 expose-loader@1
并按照 相应说明 进行配置。)
然后你可以用两种方法来用 expose-loader
。
可以使用 |
或者 %20
(空格)分隔 expose 中的 globalName
、moduleLocalName
和 override
。
可以在这里获取文档和语法实例。
⚠
%20
是查询字符串中的空格,因为你不能在 URL 中使用空格
import $ from 'expose-loader?exposes=$,jQuery!jquery';
//
// 将 `jquery` 添加到全局对象中,其名称为 `$` 和 `jQuery`
import { concat } from 'expose-loader?exposes=_.concat!lodash/concat';
//
// 将 `lodash/concat` 添加到全局对象中,其名称为 `_.concat`
import {
map,
reduce,
} from 'expose-loader?exposes=_.map|map,_.reduce|reduce!underscore';
//
// 将 `underscore` 中的 `map` 和 `reduce` 方法分别添加到全局对象中,其名称为 `_.map` 和 `_.reduce`
src/index.js
import $ from 'jquery';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('jquery'),
loader: 'expose-loader',
options: {
exposes: ['$', 'jQuery'],
},
},
{
test: require.resolve('underscore'),
loader: 'expose-loader',
options: {
exposes: [
'_.map|map',
{
globalName: '_.reduce',
moduleLocalName: 'reduce',
},
{
globalName: ['_', 'filter'],
moduleLocalName: 'filter',
},
],
},
},
],
},
};
require.resolve
调用是一个 Node.js 函数(和 webpack 进程中的 require.resolve
无关)。
require.resolve
给出模块的绝对路径 ("/.../app/node_modules/jquery/dist/jquery.js"
)。
所以 expose 只应用于 jquery
模块。并且只会在 bundle 中使用时才会被暴露。
然后用你喜欢的方式运行 webpack
。
Name | Type | Default | Description |
---|---|---|---|
exposes | {String|Object|Array<String|Object>} | undefined | List of exposes |
exposes
类型:String|Object|Array<String|Object>
默认值:undefined
List of exposes.
String
允许用一个 string 来描述 expose。
Syntax
可以使用 |
或者 %20
(空格)分隔 expose 中的 globalName
、moduleLocalName
和 override
。
字符串语法 - [[globalName] [moduleLocalName] [override]]
或者 [[globalName]|[moduleLocalName]|[override]]
,含义如下:
globalName
- 全局对象的名称,比如 window.$
用于浏览器环境(必填项)moduleLocalName
- 模块的方法/变量/等的名称(该模块必须导出它)(可以省略)override
- 允许覆盖在全局对象中存在的值(可以省略)如果 moduleLocalName
没有指定,它将整个模块暴露给全局对象,否则它只暴露 moduleLocalName
的值。
src/index.js
import _ from 'underscore';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('jquery'),
loader: 'expose-loader',
options: {
// 对于 `underscore`,它可以是 `_.map map` 或者 `_.map|map`
exposes: 'jquery',
},
},
],
},
};
Object
允许用一个对象来描述 expose。
globalName
类型:String|Array<String>
默认值:undefined
全局对象中的名字。(必填项)。
src/index.js
import _ from 'underscore';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('underscore'),
loader: 'expose-loader',
options: {
exposes: {
// 可以是 `['_', 'filter']`
globalName: '_.filter',
moduleLocalName: 'filter',
},
},
},
],
},
};
moduleLocalName
类型:String
默认值:undefined
模块中的方法/变量/等的名称(该模块必须导出它)。
如果指定了 moduleLocalName
,它只暴露 moduleLocalName
的值。
src/index.js
import _ from 'underscore';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('underscore'),
loader: 'expose-loader',
options: {
exposes: {
globalName: '_.filter',
moduleLocalName: 'filter',
},
},
},
],
},
};
override
类型:Boolean
默认值:false
默认情况下,loader 不会覆盖全局对象中的现有值,因为它是不安全的。
在 development
模式下,如果值已经出现在全局对象中则抛出一个错误。
但是你可以使用此选项配置 loader 以覆盖全局对象中的现有值。
为了强制覆盖已经存在在全局对象中的现有值,你可以设置 override
选项值为 true
。
src/index.js
import $ from 'jquery';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('jquery'),
loader: 'expose-loader',
options: {
exposes: {
globalName: '$',
override: true,
},
},
},
],
},
};
Array
src/index.js
import _ from 'underscore';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('underscore'),
loader: 'expose-loader',
options: {
exposes: [
'_.map map',
{
globalName: '_.filter',
moduleLocalName: 'filter',
},
{
globalName: ['_', 'find'],
moduleLocalName: 'myNameForFind',
},
],
},
},
],
},
};
它将 只 暴露 map
、filter
和 find
方法(名称为 myNameForFind
) 给全局对象。
在浏览器中,这些方法可以在 windows._.map(..args)
、windows._.filter(...args)
和 windows._.myNameForFind(...args)
下使用。
如果你还没有阅读,请花一点时间阅读我们的贡献指南。
将 HTML 导出为字符串。当编译器需要时,将压缩 HTML 字符串。
首先,你需要安装 html-loader
:
npm install --save-dev html-loader
然后将插件添加到你的 webpack
配置中。例如:
file.js
import html from './file.html';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
},
],
},
};
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
sources | {Boolean|Object} | true | 启用/禁用 sources 处理 |
preprocessor | {Function} | undefined | 允许在处理前对内容进行预处理 |
minimize | {Boolean|Object} | 在生产模式下为 true ,其他情况为 false | 通知 html-loader 压缩 HTML |
esModule | {Boolean} | true | 启用/禁用 ES modules 语法 |
sources
类型: Boolean|Object
默认值: true
默认情况下,每个可加载属性(例如 - <img src="image.png"/>
)都将被导入( const img = require ('./image.png')
或 import img from "./image.png""
)。
你可能需要为配置中的图片指定 loader(推荐使用 asset modules
)。
支持的标签和属性:
audio
标签的 src
属性embed
标签的 src
属性img
标签的 src
属性img
标签的 srcset
属性input
标签的 src
属性object
标签的 data
属性script
标签的 src
属性script
标签的 href
属性script
标签的 xlink:href
属性source
标签的 src
属性source
标签的 srcset
属性track
标签的 src
属性video
标签的 poster
属性video
标签的 src
属性image
标签的 xlink:href
属性image
标签的 href
属性use
标签的 xlink:href
属性use
标签的 href
属性rel
属性值包含 stylesheet
、icon
、shortcut icon
、mask-icon
、apple-touch-icon
、apple-touch-icon-precomposed
、apple-touch-startup-image
、manifest
、prefetch
、preload
或者当 itemprop
属性为 image
、logo
、screenshot
、thumbnailurl
、contenturl
、downloadurl
、duringmedia
、embedurl
、installurl
、layoutimage
时,支持 link
标签的 href
属性rel
属性值包含 stylesheet
、icon
、shortcut icon
、mask-icon
、apple-touch-icon
、apple-touch-icon-precomposed
、apple-touch-startup-image
、manifest
、prefetch
、preload
时,支持 link
标签的 imagesrcset
属性name
属性为 msapplication-tileimage
、msapplication-square70x70logo
、msapplication-square150x150logo
、msapplication-wide310x150logo
、msapplication-square310x310logo
、msapplication-config
、twitter:image
或者当 property
属性为 og:image
、og:image:url
、og:image:secure_url
、og:audio
、og:audio:secure_url
、og:video
、og:video:secure_url
、vk:image
,支持 meta
标签的 content
属性。name
属性为 msapplication-task
时,支持 meta
标签的 content
属性中的 icon-uri
值组件Boolean
当设置为 true
时,则启用所有默认元素和属性的处理,而 false
则禁用所有属性的处理。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
// Disables attributes processing
sources: false,
},
},
],
},
};
Object
你可以配置要处理的标签和属性,来过滤它们,过滤 URL 并处理以 /
开头的资源地址。
例如:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
sources: {
list: [
// All default supported tags and attributes
'...',
{
tag: 'img',
attribute: 'data-src',
type: 'src',
},
{
tag: 'img',
attribute: 'data-srcset',
type: 'srcset',
},
],
urlFilter: (attribute, value, resourcePath) => {
// `attribute` 参数包含一个 HTML 属性的名称。
// `value` 参数包含一个 HTML 属性的值。
// `resourcePath` 参数包含一个已加载 HTML 文件的路径。
if (/example\.pdf$/.test(value)) {
return false;
}
return true;
},
},
},
},
],
},
};
list
类型:Array
默认值:支持的标签和属性列表
允许设置要处理的标签和属性以及处理方式,以及过滤其中一些标签和属性的能力。
使用 ...
语法可以使用所有默认支持的标签和属性。
例如:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
sources: {
list: [
// All default supported tags and attributes
'...',
{
tag: 'img',
attribute: 'data-src',
type: 'src',
},
{
tag: 'img',
attribute: 'data-srcset',
type: 'srcset',
},
{
// Tag name
tag: 'link',
// Attribute name
attribute: 'href',
// Type of processing, can be `src` or `scrset`
type: 'src',
// Allow to filter some attributes
filter: (tag, attribute, attributes, resourcePath) => {
// The `tag` argument contains a name of the HTML tag.
// The `attribute` argument contains a name of the HTML attribute.
// The `attributes` argument contains all attributes of the tag.
// The `resourcePath` argument contains a path to the loaded HTML file.
if (/my-html\.html$/.test(resourcePath)) {
return false;
}
if (!/stylesheet/i.test(attributes.rel)) {
return false;
}
if (
attributes.type &&
attributes.type.trim().toLowerCase() !== 'text/css'
) {
return false;
}
return true;
},
},
],
},
},
},
],
},
};
如果未指定标签名称,它将处理所有标签。
你可以使用自定义过滤器指定要处理的 html 元素。
例如:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
sources: {
list: [
{
// Attribute name
attribute: 'src',
// Type of processing, can be `src` or `scrset`
type: 'src',
// Allow to filter some attributes (optional)
filter: (tag, attribute, attributes, resourcePath) => {
// The `tag` argument contains a name of the HTML tag.
// The `attribute` argument contains a name of the HTML attribute.
// The `attributes` argument contains all attributes of the tag.
// The `resourcePath` argument contains a path to the loaded HTML file.
// choose all HTML tags except img tag
return tag.toLowerCase() !== 'img';
},
},
],
},
},
},
],
},
};
filter 也可以用来扩展支持的元素和属性。
例如,filter 可以帮助处理引用资源的 meta 标签:
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
sources: {
list: [
{
tag: 'meta',
attribute: 'content',
type: 'src',
filter: (tag, attribute, attributes, resourcePath) => {
if (
attributes.value === 'og:image' ||
attributes.name === 'twitter:image'
) {
return true;
}
return false;
},
},
],
},
},
},
],
},
};
请注意: 带有 tag
配置项的 source 优先级要比没有 tag
配置项的高。
filter 可以用于禁用默认 source。
示例:
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
sources: {
list: [
'...',
{
tag: 'img',
attribute: 'src',
type: 'src',
filter: () => false,
},
],
},
},
},
],
},
};
urlFilter
类型:Function
默认值: undefined
允许配置要过滤的 url。所有过滤的 url 都参与解析(会保持原样)。
默认情况下,所有非请求资源类型的值(例如 <img src="javascript:void (0)" />
)都不处理。
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
sources: {
urlFilter: (attribute, value, resourcePath) => {
// The `attribute` argument contains a name of the HTML attribute.
// The `value` argument contains a value of the HTML attribute.
// The `resourcePath` argument contains a path to the loaded HTML file.
if (/example\.pdf$/.test(value)) {
return false;
}
return true;
},
},
},
},
],
},
};
preprocessor
类型:Function
默认值:undefined
允许在处理之前对内容进行预处理。
⚠ 你应该始终返回有效的 HTML
file.hbs
<div>
<p>{{firstname}} {{lastname}}</p>
<img src="image.png" alt="alt" />
<div>
Function
你可以将 preprocessor
选项设置为 Function
实例。
webpack.config.js
const Handlebars = require('handlebars');
module.exports = {
module: {
rules: [
{
test: /\.hbs$/i,
loader: 'html-loader',
options: {
preprocessor: (content, loaderContext) => {
let result;
try {
result = Handlebars.compile(content)({
firstname: 'Value',
lastname: 'OtherValue',
});
} catch (error) {
loaderContext.emitError(error);
return content;
}
return result;
},
},
},
],
},
};
你还可以将 preprocessor
选项设置为异步函数实例。
例如:
webpack.config.js
const Handlebars = require('handlebars');
module.exports = {
module: {
rules: [
{
test: /\.hbs$/i,
loader: 'html-loader',
options: {
preprocessor: async (content, loaderContext) => {
let result;
try {
result = await Handlebars.compile(content)({
firstname: 'Value',
lastname: 'OtherValue',
});
} catch (error) {
await loaderContext.emitError(error);
return content;
}
return result;
},
},
},
],
},
};
minimize
类型:Boolean|Object
默认值:在生产模式下为 true
,否则为 false
告诉 html-loader
编译时需要压缩 HTML 字符串。
Boolean
默认情况下,启用压缩的规则如下:
({
caseSensitive: true,
collapseWhitespace: true,
conservativeCollapse: true,
keepClosingSlash: true,
minifyCSS: true,
minifyJS: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
});
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
minimize: true,
},
},
],
},
};
Object
webpack.config.js
关于可用选项的更多信息,请参阅 html-minifier-terser 文档。
可以在 webpack.conf.js
中使用以下选项来禁用规则
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
minimize: {
removeComments: false,
collapseWhitespace: false,
},
},
},
],
},
};
esModule
类型:Boolean
默认值:false
默认情况下, html-loader
生成使用 ES modules 语法的 JS 模块。
在某些情况下,使用 ES modules 会更好,例如在进行模块合并和 tree shaking 时。
你可以使用以下方法启用 CommonJS 模块语法:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
esModule: false,
},
},
],
},
};
<!-- webpackIgnore: true -->
注释禁用 url 解析通过 <!-- webpackIgnore: true -->
注释,可以禁止处理下一个标签的源。
<!-- 禁止对 src 属性进行 url 处理 -->
<!-- webpackIgnore: true -->
<img src="image.png" />
<!-- 禁止对 src 与 srcset 属性进行 url 处理 -->
<!-- webpackIgnore: true -->
<img
srcset="image.png 480w, image.png 768w"
src="image.png"
alt="Elva dressed as a fairy"
/>
<!-- 禁止对 content 属性进行 url 处理 -->
<!-- webpackIgnore: true -->
<meta itemprop="image" content="./image.png" />
<!-- 禁止对 href 属性进行 url 处理 -->
<!-- webpackIgnore: true -->
<link rel="icon" type="image/png" sizes="192x192" href="./image.png" />
使用 resolve.roots
可以指定解析相对服务端的 URL(以 '/' 开头)请求的目录列表。
webpack.config.js
module.exports = {
context: __dirname,
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {},
},
{
test: /\.jpg$/,
type: 'asset/resource',
},
],
},
resolve: {
roots: [path.resolve(__dirname, 'fixtures')],
},
};
file.html
<img src="/image.jpg" />
// => image.jpg in __dirname/fixtures will be resolved
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.jpg$/,
type: 'asset/resource',
},
{
test: /\.png$/,
type: 'asset/inline',
},
],
},
output: {
publicPath: 'http://cdn.example.com/[fullhash]/',
},
};
file.html
<img src="image.jpg" data-src="image2x.png" />
index.js
require('html-loader!./file.html');
// => '<img src="http://cdn.example.com/49eba9f/a992ca.jpg" data-src="image2x.png"/>'
require('html-loader?{"sources":{"list":[{"tag":"img","attribute":"data-src","type":"src"}]}}!./file.html');
// => '<img src="image.jpg" data-src="data:image/png;base64,..." />'
require('html-loader?{"sources":{"list":[{"tag":"img","attribute":"src","type":"src"},{"tag":"img","attribute":"data-src","type":"src"}]}}!./file.html');
// => '<img src="http://cdn.example.com/49eba9f/a992ca.jpg" data-src="data:image/png;base64,..." />'
script
和 link
标签script.file.js
console.log(document);
style.file.css
a {
color: red;
}
file.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Title of the document</title>
<link rel="stylesheet" type="text/css" href="./style.file.css" />
</head>
<body>
Content of the document......
<script src="./script.file.js"></script>
</body>
</html>
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/,
type: 'asset/resource',
generator: {
filename: '[name][ext]',
},
},
{
test: /\.html$/i,
use: ['extract-loader', 'html-loader'],
},
{
test: /\.js$/i,
exclude: /\.file.js$/i,
loader: 'babel-loader',
},
{
test: /\.file.js$/i,
type: 'asset/resource',
},
{
test: /\.css$/i,
exclude: /\.file.css$/i,
loader: 'css-loader',
},
{
test: /\.file.css$/i,
type: 'asset/resource',
},
],
},
};
你可以使用任何模板系统。以下是 handlebars 的示例。
file.hbs
<div>
<p>{{firstname}} {{lastname}}</p>
<img src="image.png" alt="alt" />
<div>
webpack.config.js
const Handlebars = require('handlebars');
module.exports = {
module: {
rules: [
{
test: /\.hbs$/i,
loader: 'html-loader',
options: {
preprocessor: (content, loaderContext) => {
let result;
try {
result = Handlebars.compile(content)({
firstname: 'Value',
lastname: 'OtherValue',
});
} catch (error) {
loaderContext.emitError(error);
return content;
}
return result;
},
},
},
],
},
};
你可以使用 PostHTML 而无需任何其他加载程序。
file.html
<img src="image.jpg" />
webpack.config.js
const posthtml = require('posthtml');
const posthtmlWebp = require('posthtml-webp');
module.exports = {
module: {
rules: [
{
test: /\.hbs$/i,
loader: 'html-loader',
options: {
preprocessor: (content, loaderContext) => {
let result;
try {
result = posthtml().use(plugin).process(content, { sync: true });
} catch (error) {
loaderContext.emitError(error);
return content;
}
return result.html;
},
},
},
],
},
};
一种非常常见的情况是将 HTML 导出到自己的 .html 文件中,以直接使用, 而非注入到 javascript。 可以使用以下 2 种 loader 的组合来实现:
html-loader 将解析 URL,同时引入图片以及你需要的所有内容。
extract loader 会将 javascript 解析为正确的 html 文件,
然后确保图片被引入且路径正确,
asset modules
会为你生成 .html 文件。例如:
webpack.config.js
module.exports = {
output: {
assetModuleFilename: '[name][ext]',
},
module: {
rules: [
{
test: /\.html$/,
type: 'asset/resource',
generator: {
filename: '[name][ext]',
},
},
{
test: /\.html$/i,
use: ['extract-loader', 'html-loader'],
},
],
},
};
如果你还没有阅读,请花一点时间阅读我们的贡献指南。
imports loader 允许使用依赖于特定全局变量的模块。
这对于依赖 window
对象下的全局变量(比如 $
或 this
)的第三方模块非常有用。
imports loader 可以添加必要的 require('whatever')
调用,因此这些模块可以与 webpack 一起使用。
有关兼容性问题的进一步提示,可以查看官方文档中的 Shimming。
⚠ 默认情况下,loader 生成具名 ES module。
⚠ 请注意,在原始代码中已存在的 imports(
import
/require
)与引入新值会导致失败。
首先,你需要安装 imports-loader
:
npm install imports-loader --save-dev
如果你有这个文件:
example.js
$('img').doSomeAwesomeJqueryPluginStuff();
然后你可以使用两个方法来配置 imports-loader
,就可以把 jquery
值注入到模块中。
可以使用 |
或者 %20
(空格)分隔 import 语句中的 syntax
、moduleName
、name
和 alias
。
可以在 这里 获取文档和语法示例。
⚠
%20
是查询字符串中的空格,因为你不能在 URL 中使用空格。
// 可供选择的语法:
//
// import myLib from 'imports-loader?imports=default%20jquery%20$!./example.js';
//
// `%20` 是查询字符串中的空格,相当于 `default jquery $`
import myLib from 'imports-loader?imports=default|jquery|$!./example.js';
// 在 example.js 的开头添加如下代码:
//
// import $ from "jquery";
//
// ...
// Code
// ...
import myLib from 'imports-loader?imports=default|jquery|$,angular!./example.js';
// `|` 是查询字符串中的分隔符,相当于 `default|jquery|$` 与 `angular`
// 在 example.js 的开头添加如下代码:
//
// import $ from "jquery";
// import angular from "angular";
//
// ...
// Code
// ...
import myLib from 'imports-loader?imports=named|library|myMethod,angular!./example.js';
// `|` 是查询字符串中的分隔符,相当于 `named|library|myMethod` 与 `angular`
// 在 example.js 的开头添加如下代码:
//
// import { myMethod } from "library";
// import angular from "angular";
//
// ...
// Code
// ...
const myLib = require(`imports-loader?type=commonjs&imports=single|jquery|$,angular!./example.js`);
// `|` 是查询字符串中的分隔符,相当于 `single|jquery|$` 与 `angular`
// 在 example.js 的开头添加如下代码:
//
// var $ = require("jquery");
// var angular = require("angular");
//
// ...
// Code
// ...
const myLib = require(`imports-loader?type=commonjs&imports=single|myLib|myMethod&wrapper=window&!./example.js`);
// `|` 是查询字符串中的分隔符,相当于 `single|myLib|myMethod` 与 `angular`
// 在 example.js 中添加如下代码:
//
// const myMethod = require('myLib');
//
// (function () {
// ...
// Code
// ...
// }.call(window));
import myLib from 'imports-loader?additionalCode=var%20myVariable%20=%20false;!./example.js';
// 在 example.js 的开头添加如下代码:
//
// var myVariable = false;
//
// ...
// Code
// ...
webpack.config.js
module.exports = {
module: {
rules: [
{
// 你可以使用 `regexp`
// test: /example\.js/$
test: require.resolve('example.js'),
use: [
{
loader: 'imports-loader',
options: {
imports: [
'default jquery $',
'default lib_2 lib_2_default',
'named lib_3 lib2_method_1',
'named lib_3 lib2_method_2 lib_2_method_2_short',
'namespace lib_4 my_namespace',
'side-effects lib_5',
{
syntax: 'default',
moduleName: 'angular',
name: 'angular',
},
],
},
},
],
},
],
},
};
生成输出:
import $ from 'jquery';
import lib_2_default from 'lib_2';
import { lib2_method_1, lib2_method_2 as lib_2_method_2_short } from 'lib_3';
import * as my_namespace from 'lib_4';
import 'lib_5';
import angular from 'angular';
然后用你喜欢的方式运行 webpack
Name | Type | Default | Description |
---|---|---|---|
type | {String} | module | 生成 import 的格式 |
imports | {String|Object|Array<String|Object>} | undefined | import 列表 |
wrapper | {Boolean|String|Object} | undefined | 关闭函数中的模块代码 ((function () { ... }).call(); ) |
additionalCode | {String} | undefined | 添加自定义代码 |
type
类型:String
默认值:module
生成 exports 的格式。
可选值 - commonjs
(CommonJS module 语法) 和 module
(ES module 语法)。
commonjs
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('example.js'),
loader: 'imports-loader',
options: {
syntax: 'default',
type: 'commonjs',
imports: 'Foo',
},
},
],
},
};
生成输出:
var Foo = require('Foo');
// ...
// Code
// ...
module
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('example.js'),
loader: 'imports-loader',
options: {
type: 'module',
imports: 'Foo',
},
},
],
},
};
生成输出:
import Foo from 'Foo';
// ...
// Code
// ...
imports
类型:String|Object|Array<String|Object>
默认值:undefined
import
列表。
String
允许使用字符串描述 export
。
Syntax
使用 |
或者 %20
(空格)分隔 import 中的 syntax
、moduleName
、name
与 alias
。
字符串语法 - [[syntax] [moduleName] [name] [alias]]
或者 [[syntax]|[moduleName]|[name]|[alias]]
,其含义为:
[syntax]
(可以被省略):
type
值为 module
- 可以是 default
、named
、namespace
或者 side-effects
,默认值为 default
。type
值为 commonjs
- 可以是 single
、multiple
或者 pure
,默认值为 single
。[moduleName]
- 被导入模块的名称(必填)
[name]
- 被导入值的名称(必填)
[alias]
- 被导入值的别名(可以被省略)
示例:
如果 type 值为 module
:
[Foo]
- 生成 import Foo from "Foo";
.[default Foo]
- 生成 import Foo from "Foo";
.[default ./my-lib Foo]
- 生成 import Foo from "./my-lib";
.[named Foo FooA]
- 生成 import { FooA } from "Foo";
.[named Foo FooA Bar]
- 生成 import { FooA as Bar } from "Foo";
.[namespace Foo FooA]
- 生成 import * as FooA from "Foo";
.[side-effects Foo]
- 生成 import "Foo";
.如果 type 值为 commonjs
:
[Foo]
- 生成 const Foo = require("Foo");
.[single Foo]
- 生成 const Foo = require("Foo");
.[single ./my-lib Foo]
- 生成 const Foo = require("./my-lib");
.[multiple Foo FooA Bar]
- 生成 const { FooA: Bar } = require("Foo");
.[pure Foo]
- 生成 require("Foo");
.⚠ 你需要设置
type: "commonjs"
以使用single
、multiple
与pure
语法。
⚠ Aliases 不能与
default
、namespace
、side-effects
、single
与pure
语法同时使用。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/example.js'),
loader: 'imports-loader',
options: {
imports: 'default lib myName',
},
},
],
},
};
生成输出:
import myName from 'lib';
// ...
// Code
// ...
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('./path/to/example.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
imports: 'single lib myName',
},
},
],
},
};
生成输出:
var myName = require('lib');
// ...
// Code
// ...
Object
允许使用一个对象来描述 import
。
属性:
syntax
:
type
值为 module
- 可以是 default
、named
、namespace
或 side-effects
type
值为 commonjs
- 可以是 single、
multiple或
pure`moduleName
- 被导入模块的名称 (必填)
name
- 被导入值的名称 (必填)
alias
- 被导入值的别名 (可以被省略)
⚠ Alias 不能与
default
、namespace
、side-effects
、single
与pure
语法同时使用。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('example.js'),
use: [
{
loader: 'imports-loader',
options: {
imports: {
syntax: 'named',
moduleName: 'lib_2',
name: 'lib2_method_2',
alias: 'lib_2_method_2_alias',
},
},
},
],
},
],
},
};
生成输出:
import { lib2_method_2 as lib_2_method_2_alias } from 'lib_2';
// ...
// Code
// ...
Array
允许指定多个导入。
每一项可以为 string
或者 object
。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('example.js'),
use: [
{
loader: 'imports-loader',
options: {
imports: [
{
moduleName: 'angular',
},
{
syntax: 'default',
moduleName: 'jquery',
name: '$',
},
'default lib_2 lib_2_default',
'named lib_2 lib2_method_1',
'named lib_2 lib2_method_2 lib_2_method_2_alias',
'namespace lib_3 lib_3_all',
'side-effects lib_4',
],
},
},
],
},
],
},
};
生成输出:
import angular from 'angular';
import $ from 'jquery';
import lib_2_default from 'lib_2';
import { lib2_method_1, lib2_method_2 as lib_2_method_2_alias } from 'lib_2';
import * as lib_3_all from 'lib_3';
import 'lib_4';
// ...
// Code
// ...
wrapper
类型:Boolean|String|Object
默认值:undefined
用给定的 thisArg
和 args
关闭函数中的模块代码 ((function () { ... }).call();
)。
⚠ 如果源码中包含 ES module
import
的话,请不要使用该配置。
Boolean
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('example.js'),
use: [
{
loader: 'imports-loader',
options: {
imports: {
moduleName: 'jquery',
name: '$',
},
wrapper: true,
},
},
],
},
],
},
};
生成输出:
import $ from 'jquery';
(function () {
// ...
// Code
// ...
}.call());
String
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('example.js'),
use: [
{
loader: 'imports-loader',
options: {
imports: {
moduleName: 'jquery',
name: '$',
},
wrapper: 'window',
},
},
],
},
],
},
};
生成输出:
import $ from 'jquery';
(function () {
// ...
// Code
// ...
}.call(window));
Object
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('example.js'),
use: [
{
loader: 'imports-loader',
options: {
imports: {
moduleName: 'jquery',
name: '$',
},
wrapper: {
thisArg: 'window',
args: ['myVariable', 'myOtherVariable'],
},
},
},
],
},
],
},
};
生成输出:
import $ from 'jquery';
(function (myVariable, myOtherVariable) {
// ...
// Code
// ...
}.call(window, myVariable, myOtherVariable));
Object
with different parameter nameswebpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('example.js'),
use: [
{
loader: 'imports-loader',
options: {
imports: {
moduleName: 'jquery',
name: '$',
},
wrapper: {
thisArg: 'window',
args: {
myVariable: 'var1',
myOtherVariable: 'var2',
},
},
},
},
],
},
],
},
};
生成输出:
import $ from 'jquery';
(function (var1, var2) {
// ...
// Code
// ...
}.call(window, myVariable, myOtherVariable));
additionalCode
类型:String
默认值:undefined
在模块代码之前添加自定义代码作为前导。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('example.js'),
use: [
{
loader: 'imports-loader',
options: {
imports: {
moduleName: 'jquery',
name: '$',
},
additionalCode: 'var myVariable = false;',
},
},
],
},
],
},
};
生成输出:
import $ from 'jquery';
var myVariable = false;
// ...
// Code
// ...
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('example.js'),
use: [
{
loader: 'imports-loader',
options: {
imports: {
moduleName: 'jquery',
name: '$',
},
additionalCode:
'var define = false; /* Disable AMD for misbehaving libraries */',
},
},
],
},
],
},
};
生成输出:
import $ from 'jquery';
var define = false; /* Disable AMD for misbehaving libraries */
// ...
// Code
// ...
如果你还没有阅读,请花一点时间阅读我们的贡献指南。
Webpack 支持使用 loader 对文件进行预处理。你可以构建包括 JavaScript 在内的任何静态资源。并且可以使用 Node.js 轻松编写自己的 loader。
在 require()
语句中使用 loadername!
作为前缀的方式来使用 loader,或者在 webpack 配置中配置 regex 来自动应用它们 - 请参阅 配置 。
val-loader
将代码作为模块执行,并将其导出为 JS 代码ref-loader
用于手动建立文件之间的依赖关系cson-loader
加载并转换 CSON 文件babel-loader
使用 Babel 加载 ES2015+ 代码并将其转换为 ES5esbuild-loader
加载 ES2015+ 代码并使用 esbuild 转译到 ES6+buble-loader
使用 Bublé 加载 ES2015+ 代码并将其转换为 ES5traceur-loader
使用 Traceur 加载 ES2015+ 代码并将其转换为 ES5ts-loader
像加载 JavaScript 一样加载 TypeScript 2.0+coffee-loader
像加载 JavaScript 一样加载 CoffeeScriptfengari-loader
使用 fengari 加载 Lua 代码elm-webpack-loader
像加载 JavaScript 一样加载 Elmhtml-loader
将 HTML 导出为字符串,需要传入静态资源的引用路径pug-loader
加载 Pug 和 Jade 模板并返回一个函数markdown-loader
将 Markdown 编译为 HTMLreact-markdown-loader
使用 markdown-parse 解析器将 Markdown 编译为 React 组件posthtml-loader
使用 PostHTML 加载并转换 HTML 文件handlebars-loader
将 Handlebars 文件编译为 HTMLmarkup-inline-loader
将 SVG/MathML 文件内嵌到 HTML 中。在将图标字体或 CSS 动画应用于 SVG 时,此功能非常实用。twig-loader
编译 Twig 模板并返回一个函数remark-loader
通过 remark
加载 markdown,且支持解析内容中的图片style-loader
将模块导出的内容作为样式并添加到 DOM 中css-loader
加载 CSS 文件并解析 import 的 CSS 文件,最终返回 CSS 代码less-loader
加载并编译 LESS 文件sass-loader
加载并编译 SASS/SCSS 文件postcss-loader
使用 PostCSS 加载并转换 CSS/SSS 文件stylus-loader
加载并编译 Stylus 文件vue-loader
加载并编译 Vue 组件angular2-template-loader
加载并编译 Angular 组件有关更多第三方 loader,请参阅 awesome-webpack 中的列表。
webpack 将 Less 编译为 CSS 的 loader。
首先,你需要先安装 less
和 less-loader
:
npm install less less-loader --save-dev
然后将该 loader 添加到 webpack
的配置中去,例如:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
// compiles Less to CSS
'style-loader',
'css-loader',
'less-loader',
],
},
],
},
};
接着使用你习惯的方式运行 webpack
。
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
lessOptions | {Object|Function} | { relativeUrls: true } | Less 的可选项。 |
additionalData | {String|Function} | undefined | 在入口文件起始或末尾添加 Less 代码。 |
sourceMap | {Boolean} | compiler.devtool | 是否生成 source map。 |
webpackImporter | {Boolean} | true | 是否启用默认的 webpack importer。 |
implementation | {Object|String} | less | 配置 Less 使用的实现库 |
lessOptions
类型: Object|Function
默认值: { relativeUrls: true }
通过 lessOptions
属性,你可以设置 loader options 中的任意特定的选项值给 less-loader
。所有可用的选项值请参看 Less 命令行可选参数文档。由于我们是通过编程的方式将这些选项传递给 Less,因此您需要将破折号(dash-case)转换为驼峰值(camelCase)后传递它们。
Object
使用对象(Object)的形式传递 options 给 Less。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
options: {
lessOptions: {
strictMath: true,
},
},
},
],
},
],
},
};
Function
允许根据 loader 的 context 来设置 options,再传递给 Less。
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
lessOptions: (loaderContext) => {
// 更多可用的属性见 https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.less') {
return {
paths: ['absolute/path/c', 'absolute/path/d'],
};
}
return {
paths: ['absolute/path/a', 'absolute/path/b'],
};
},
},
},
],
},
],
},
};
additionalData
类型: String|Function
默认值: undefined
在实际入口文件的起始位置添加 Less
代码。
这种情况下,less-loader
只会追加并不会覆盖文件内容。
当你的 Less 变量依赖环境变量时这个属性将非常有用:
ℹ 由于你注入了代码,因此它将破坏入口文件的源映射关系。通常有比这更简单的解决方案,例如多个 Less 入口文件。
String
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
additionalData: `@env: ${process.env.NODE_ENV};`,
},
},
],
},
],
},
};
Function
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
additionalData: (content, loaderContext) => {
// 更多可用的属性见 https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.less') {
return '@value: 100px;' + content;
}
return '@value: 200px;' + content;
},
},
},
],
},
],
},
};
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
additionalData: async (content, loaderContext) => {
// More information about available properties https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.less') {
return '@value: 100px;' + content;
}
return '@value: 200px;' + content;
},
},
},
],
},
],
},
};
sourceMap
类型: Boolean
默认值: 取决于 compiler.devtool
的值
默认生成的 source map 取决于 compiler.devtool
的值。除了值等于 eval
和 false
外,其他值都能生成 source map
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'less-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
};
webpackImporter
类型:Boolean
默认值:true
启用/禁用 webpack 默认的 importer。
在某些情况下,这样做可以提高性能,但是请慎用,因为可能会使得 aliases 和以 ~
开头的 @import
规则失效。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
webpackImporter: false,
},
},
],
},
],
},
};
implementation
类型:Object | String
⚠ less-loader 已兼容 Less 3 和 Less 4。
特殊的 implementation
选项决定使用 Less 的哪个实现。重载本地安装的 less
的 peerDependency
版本。
此选项只对下游的工具作者有效,以便于 Less 3 到 Less 4 的过渡。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
implementation: require('less'),
},
},
],
},
],
},
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
implementation: require.resolve('less'),
},
},
],
},
],
},
};
将 less-loader
、css-loader
和 style-loader
串联起来使用可立即将所有样式应用于 DOM。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
{
loader: 'style-loader', // 从 JS 中创建样式节点
},
{
loader: 'css-loader', // 转化 CSS 为 CommonJS
},
{
loader: 'less-loader', // 编译 Less 为 CSS
},
],
},
],
},
};
不幸的是,Less 并没有将所有选项 1 对 1 映射为 camelCase(驼峰值)。如有疑问,请检查执行文件并搜索破折号选项。
为了生成 CSS 的 source map, 你需要在 loader 的可选项中设置 sourceMap
属性。如果没设置的话 loader 将会继承你 webpack 中为生成 source map 设置的属性值 devtool
。
webpack.config.js
module.exports = {
devtool: 'source-map', // 任何类似于 "source-map" 的 devtool 值都可以
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'less-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
};
如果你想在 Chrome 中修改原始的 Less 文件,可以参考这篇不错的博客。这篇博客虽然写的 Sass,但也适合于 Less。
在生产环境中推荐使用 MiniCssExtractPlugin 来提取样式表到专门的文件中,这样你的样式就不需要依赖 JavaScript。
首先我们会尝试使用内置 less
解析逻辑,然后再使用 webpack
解析逻辑(alias 和 ~
)。
webpack
提供了一种 解析文件的高级机制。如果 less
不能解析 @import
的话,less-loader
作为 Less 的插件将所有的查询结果传递给 webpack 解析器。因此你可以从 node_modules
中导入 Less 模块。
@import 'bootstrap/less/bootstrap';
~
用法已被废弃,可以从代码中删除(我们建议这么做),但是我们会因为一些历史原因一直支持这种写法。
为什么你可以移除它呢?loader 首先会尝试以相对路径解析 @import
,如果它不能被解析,loader 将会尝试在 node_modules
中解析 @import
。
只要在包名前加上 ~
,告诉 webpack 在 modules
中进行查找。
@import '~bootstrap/less/bootstrap';
可以通过 resolve.byDependency
修改默认解析器配置:
webpack.config.js
module.exports = {
devtool: 'source-map', // "source-map" 类的 devtool 都是可以的
module: {
rules: [
{
test: /\.less$/i,
use: ['style-loader', 'css-loader', 'less-loader'],
},
],
},
resolve: {
byDependency: {
// 更多的配置项可以在这里找到 https://webpack.js.org/configuration/resolve/
less: {
mainFiles: ['custom'],
},
},
},
};
在其前面加上 〜
很关键,因为 〜/
会解析到根目录。webpack 需要区分 bootstrap
和 〜bootstrap
,因为 CSS 和 Less 文件没有用于导入相对路径文件的特殊语法。写 @import“ file”
等同于 @import“ ./file”;
如果指定 paths
选项,将从指定的 paths
中搜索模块,这是 less
的默认行为。paths
应该是具有绝对路径的数组:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
options: {
lessOptions: {
paths: [path.resolve(__dirname, 'node_modules')],
},
},
},
],
},
],
},
};
想要使用 插件,只需要简单设置下 plugins
选项即可,
具体配置如下:
webpack.config.js
const CleanCSSPlugin = require('less-plugin-clean-css');
module.exports = {
...
{
loader: 'less-loader',
options: {
lessOptions: {
plugins: [
new CleanCSSPlugin({ advanced: true }),
],
},
},
},
...
};
ℹ️ 使用
pluginManager.webpackLoaderContext
属性可以访问自定义插件中的 loader context。
module.exports = {
install: function (less, pluginManager, functions) {
functions.add('pi', function () {
// Loader context is available in `pluginManager.webpackLoaderContext`
return Math.PI;
});
},
};
通过 webpack 打包 CSS 有很多好处,比如给引用图片和字体文件路径添加 hash, 在开发环境可以 模块热替换。另一方面,在生产环境,根据 JS 来控制应用样式表不是一个好的方式,可能会导致延迟渲染,甚至可能会出现闪烁现象。因此,在你最终的生产环境中将它们拆分成单独的文件来存放通常是比较好的选择。
有两种从 bundle 中提取样式表的方式:
extract-loader
(简单,但得专门指定 css-loader
的 output)Less 和 CSS modules 有一个已知的问题,关于 url(...)
语句中的相对文件路径,看下这个问题的解释。
如果你还没有看过我们的贡献者指南请先花点时间看一下。
处理 Node.js 插件(add-ons) 的 loader。
允许使用 .node
拓展名与原生 node module 相关联。
⚠
node-loader
只对node
/electron-main
/electron-main
/electron-renderer
/electron-preload
生效。
首先,你需要安装 node-loader
:
npm install node-loader --save-dev
设置 target
配置项为 node
/async-node
/electron-main
/electron-renderer
/electron-preload
,并且需禁用 __dirname
全局变量。
webpack.config.js
module.exports = {
target: 'node',
node: {
__dirname: false,
},
module: {
rules: [
{
test: /\.node$/,
loader: 'node-loader',
},
],
},
};
index.js
import node from 'node-loader!./file.node';
然后通过你喜欢的方式运行 webpack
。
index.js
import node from 'file.node';
然后在你的 webpack
配置中添加该 loader。例如:
webpack.config.js
module.exports = {
target: 'node',
node: {
__dirname: false,
},
module: {
rules: [
{
test: /\.node$/,
loader: 'node-loader',
},
],
},
};
然后通过你喜欢的方式运行 webpack
。
Name | Type | Default | Description |
---|---|---|---|
flags | {Number} | undefined | 启用/禁用 url /image-set 函数处理 |
name | {String|Function} | '[contenthash].[ext]' | 指定一个或多个目标文件的自定义文件名模板。 |
flags
类型:Number
默认值:undefined
flags
参数是一个允许指定 dlopen 行为的整数。
请查阅 process.dlopen
文档了解更多。
index.js
import node from 'file.node';
webpack.config.js
const os = require('os');
module.exports = {
target: 'node',
node: {
__dirname: false,
},
module: {
rules: [
{
test: /\.node$/,
loader: 'node-loader',
options: {
flags: os.constants.dlopen.RTLD_NOW,
},
},
],
},
};
name
类型:String|Function
默认值:'[contenthash].[ext]'
指定一个或多个目标文件的自定义文件名模板。
String
webpack.config.js
module.exports = {
target: 'node',
node: {
__dirname: false,
},
module: {
rules: [
{
test: /\.node$/,
loader: 'node-loader',
options: {
name: '[path][name].[ext]',
},
},
],
},
};
Function
webpack.config.js
module.exports = {
target: 'node',
node: {
__dirname: false,
},
module: {
rules: [
{
test: /\.node$/,
loader: 'node-loader',
options: {
name(resourcePath, resourceQuery) {
// `resourcePath` - `/absolute/path/to/file.js`
// `resourceQuery` - `?foo=bar`
if (process.env.NODE_ENV === 'development') {
return '[path][name].[ext]';
}
return '[contenthash].[ext]';
},
},
},
],
},
};
如果你还未阅读贡献指南,请抽时间进行阅读。
使用 PostCSS
处理 CSS 的 loader。
如果要使用最新版本的话,你需要使用 webpack v5。如果使用 webpack v4 的话,你需要安装 postcss-loader v4。
为了使用本 loader,你需要安装 postcss-loader
和 postcss
:
npm install --save-dev postcss-loader postcss
然后添加本 loader 的相关配置到你的 webpack
的配置文件。例如:
In the following configuration the plugin
postcss-preset-env
is used, which is not installed by default.
file.js
import css from 'file.css';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env',
{
// 其他选项
},
],
],
},
},
},
],
},
],
},
};
或者使用 PostCSS 本身的 配置文件:
postcss.config.js
module.exports = {
plugins: [
[
'postcss-preset-env',
{
// 其他选项
},
],
],
};
Loader 将会自动搜索配置文件。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader', 'postcss-loader'],
},
],
},
};
最后,通过你喜欢的方式运行 webpack
。
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
execute | {Boolean} | undefined | 在 CSS-in-JS 中启动 PostCSS Parser 支持 |
postcssOptions | {Object|Function} | Postcss.process的默认值 | 设置 PostCSS 选项与插件 |
sourceMap | {Boolean} | compiler.devtool | 开启 / 关闭 source map 的生成 |
implementation | {Function|String} | postcss | 为 PostCSS 设置对应实现并使用 |
execute
类型:Boolean
默认值:undefined
如果你在 JS 文件中编写样式,请使用 postcss-js
parser,并且添加 execute
选项。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.style.js$/,
use: [
'style-loader',
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
parser: 'postcss-js',
},
execute: true,
},
},
],
},
],
},
};
postcssOptions
类型:Object|Function
默认值:undefined
允许设置 PostCSS 选项
和插件。
支持所有的 PostCSS
选项。
这是配置文件中特殊的 配置
选项。它如何工作、如何配置再接下来的部分将会有详细的描述。
因为可能会导致 source map 中错误的文件路径,我们不推荐使用指定的 from
、to
和 map
选项。
如果你需要 source map,请使用 sourcemap
选项。
Object
设置 plugins
:
webpack.config.js (recommended)
const myOtherPostcssPlugin = require('postcss-my-plugin');
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-import',
['postcss-short', { prefix: 'x' }],
require.resolve('my-postcss-plugin'),
myOtherPostcssPlugin({ myOption: true }),
// 废弃的,将会在下一个主要版本中移除
{ 'postcss-nested': { preserveEmpty: true } },
],
},
},
},
],
},
};
webpack.config.js (废弃的,将会在下一个主要版本中移除)
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: {
'postcss-import': {},
'postcss-short': { prefix: 'x' },
},
},
},
},
],
},
};
设置 syntax
:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
// 可以是 `String`
syntax: 'sugarss',
// 可以是 `Object`
syntax: require('sugarss'),
},
},
},
],
},
};
设置 parser
:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
// 可以是 `String`
parser: 'sugarss',
// 可以是 `Object`
parser: require('sugarss'),
// 可以是 `Function`
parser: require('sugarss').parse,
},
},
},
],
},
};
设置 stringifier
:
webpack.config.js
const Midas = require('midas');
const midas = new Midas();
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
// 可以是 `String`
stringifier: 'sugarss',
// 可以是 `Object`
stringifier: require('sugarss'),
// 可以是 `Function`
stringifier: midas.stringifier,
},
},
},
],
},
};
Function
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(css|sss)$/i,
loader: 'postcss-loader',
options: {
postcssOptions: (loaderContext) => {
if (/\.sss$/.test(loaderContext.resourcePath)) {
return {
parser: 'sugarss',
plugins: [
['postcss-short', { prefix: 'x' }],
'postcss-preset-env',
],
};
}
return {
plugins: [
['postcss-short', { prefix: 'x' }],
'postcss-preset-env',
],
};
},
},
},
],
},
};
config
类型:Boolean|String
默认值:undefined
允许使用配置文件设置选项。 在配置文件中指定的选项将会和 loader option 进行合并,并且 loader option 将会覆盖配置文件中的选项。
Loader 将会从下面几个地方搜索目录树来寻找配置文件:
package.json
中的 postcss
属性.postcssrc
文件.postcss.json
、.postcss.yaml
、.postcss.yml
、.postcss.js
或者 .postcss.cjs
文件postcss.config.js
或者 postcss.config.cjs
导出一个对象的 CommonJS 模块(推荐)使用 Object
:
postcss.config.js(推荐)
module.exports = {
// 你可以指定下面提到的所有选项 https://postcss.org/api/#processoptions
// parser: 'sugarss',
plugins: [
// PostCSS 插件
['postcss-short', { prefix: 'x' }],
'postcss-preset-env',
],
};
使用 Function
:
postcss.config.js(推荐)
module.exports = (api) => {
// `api.file` - 文件路径
// `api.mode` - webpack 的 `mode` 属性值,请查阅 https://webpack.js.org/configuration/mode/
// `api.webpackLoaderContext` - 在复杂情况下使用的 loader 上下文
// `api.env` - `api.mode` 的别名,与 `postcss-cli` 兼容
// `api.options` - `postcssOptions` 的选项
if (/\.sss$/.test(api.file)) {
return {
//你可以指定下面提到的所有选项 https://postcss.org/api/#processoptions here
parser: 'sugarss',
plugins: [
// PostCSS 插件
['postcss-short', { prefix: 'x' }],
'postcss-preset-env',
],
};
}
return {
// 你可以指定下面提到的所有选项 https://postcss.org/api/#processoptions
plugins: [
// PostCSS 插件
['postcss-short', { prefix: 'x' }],
'postcss-preset-env',
],
};
};
postcss.config.js(废弃的,将会在下一个主要版本中移除)
module.exports = {
// 你可以指定下面提到的所有选项 https://postcss.org/api/#processoptions
// parser: 'sugarss',
plugins: {
// PostCSS 插件
'postcss-short': { prefix: 'x' },
'postcss-preset-env': {},
},
};
你可以在不同的目录中使用不同的 postcss.config.js
文件。
配置文件的寻找从 path.dirname(file)
开始根据文件树向上寻找,直至找到一个配置文件。
|– components
| |– component
| | |– index.js
| | |– index.png
| | |– style.css (1)
| | |– postcss.config.js (1)
| |– component
| | |– index.js
| | |– image.png
| | |– style.css (2)
|
|– postcss.config.js (1 && 2 (recommended))
|– webpack.config.js
|
|– package.json
在设置 postcss.config.js
之后,将 postcss-loader
添加到 webpack.config.js
中。
你可以单独使用它,或者与 css-loader
结合使用(推荐)。
在 css-loader
和 style-loader
之前使用它,但是在其他预处理器(例如:sass|less|stylus-loader
)之后使用 (因为 webpack loader 从右到左 / 从底到顶执行)。
webpack.config.js (推荐)
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
'postcss-loader',
],
},
],
},
};
开启 / 关闭自动加载配置。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
config: false,
},
},
},
],
},
};
允许指定配置文件路径。
webpack.config.js
const path = require('path');
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
config: path.resolve(__dirname, 'custom.config.js'),
},
},
},
],
},
};
sourceMap
类型:Boolean
默认值:依赖于 compiler.devtool
的值
默认情况下 source map 的生成依赖于 devtool
选项。
除 eval
和 false
外,其他的值都将打开 source map 生成。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader', options: { sourceMap: true } },
{ loader: 'postcss-loader', options: { sourceMap: true } },
{ loader: 'sass-loader', options: { sourceMap: true } },
],
},
],
},
};
替代设置:
webpack.config.js
module.exports = {
devtool: 'source-map',
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'postcss-loader' },
{ loader: 'sass-loader' },
],
},
],
},
};
implementation
类型:Function | String
默认值:postcss
特殊的 implementation
选项决定使用 PostCSS 哪个实现。重载本地安装的 postcss
的 peerDependency
版本。
此选项只对底层工具的作者有效,以便于 PostCSS 7 到 PostCSS 8 的过渡。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: { implementation: require('postcss') },
},
{ loader: 'sass-loader' },
],
},
],
},
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: { implementation: require.resolve('postcss') },
},
{ loader: 'sass-loader' },
],
},
],
},
};
你需要安装 sugarss
:
npm install --save-dev sugarss
使用 SugarSS
句法分析器。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 },
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
parser: 'sugarss',
},
},
},
],
},
],
},
};
你需要安装 autoprefixer
:
npm install --save-dev autoprefixer
使用 autoprefixer
添加厂商前缀。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 },
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'autoprefixer',
{
// 选项
},
],
],
},
},
},
],
},
],
},
};
⚠️
postcss-preset-env
包含autoprefixer
,因此如果你已经使用了 preset 就无需单独添加它了。更多 信息
你需要安装 postcss-preset-env
:
npm install --save-dev postcss-preset-env
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 },
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env',
{
// 选项
},
],
],
},
},
},
],
},
],
},
};
什么是 CSS Modules
?请 阅读。
在 postcss-loader
中没有额外的设置。
为了使他们正常工作,请添加 css-loader
的 importLoaders
选项。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
},
},
'postcss-loader',
],
},
],
},
};
postcss-js
你需要安装 postcss-js
:
npm install --save-dev postcss-js
如果你想处理写在 JavaScript 中的样式,那么你需要使用 postcss-js
parser。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.style.js$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
parser: 'postcss-js',
},
execute: true,
},
},
'babel-loader',
],
},
],
},
};
接下来你就可以像下面这样书写样式了
import colors from './styles/colors';
export default {
'.menu': {
color: colors.main,
height: 25,
'&_link': {
color: 'white',
},
},
};
⚠️ 如果你正在使用 Babel 且为了程序正常工作,你需要进行下面的步骤:
- 添加
babel-plugin-add-module-exports
到你的配置中。- 你需要在每一个样式模块中有一个默认导出。
webpack.config.js
const isProductionMode = process.env.NODE_ENV === 'production';
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: isProductionMode ? 'production' : 'development',
module: {
rules: [
{
test: /\.css$/,
use: [
isProductionMode ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
'postcss-loader',
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: isProductionMode ? '[name].[contenthash].css' : '[name].css',
}),
],
};
要将资源从 PostCSS 插件写到 webpack,需要向 result.messages
中添加一条消息。
一条符合规范的消息应该包含下面的字段:
type
= asset
- 消息类型(必需字段,并且应该为 asset
)file
- 文件名称(必需)content
- 文件内容(必需)sourceMap
- sourceMapinfo
- 资源信息webpack.config.js
const customPlugin = () => (css, result) => {
result.messages.push({
type: 'asset',
file: 'sprite.svg',
content: '<svg>...</svg>',
});
};
const postcssPlugin = postcss.plugin('postcss-assets', customPlugin);
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [postcssPlugin()],
},
},
},
],
},
],
},
};
当需要在文件变化时进行重新编译时,webpack 为了理解这样的操作需要添加必要的依赖。
由两种方式添加依赖:
result.messages
中触发消息。消息应该包含下面两个字段:
type
= dependency
- 消息类型(必需字段,并且应该为 dependency
、context-dependency
、build-dependency
或 missing-dependency
)file
- 文件的绝对路径(必需)webpack.config.js
const path = require('path');
const customPlugin = () => (css, result) => {
result.messages.push({
type: 'dependency',
file: path.resolve(__dirname, 'path', 'to', 'file'),
});
};
const postcssPlugin = postcss.plugin('postcss-assets', customPlugin);
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [postcssPlugin()],
},
},
},
],
},
],
},
};
loaderContext
。webpack.config.js
const path = require('path');
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
config: path.resolve(__dirname, 'path/to/postcss.config.js'),
},
},
},
],
},
],
},
};
postcss.config.js
module.exports = (api) => ({
plugins: [
require('path/to/customPlugin')({
loaderContext: api.webpackLoaderContext,
}),
],
});
customPlugin.js
const path = require('path');
const customPlugin = (loaderContext) => (css, result) => {
loaderContext.webpack.addDependency(
path.resolve(__dirname, 'path', 'to', 'file')
);
};
module.exports = postcss.plugin('postcss-assets', customPlugin);
如果你还没有读过我们的贡献指南,请花一点时间阅读它。
404: Not Found
通过 remark
加载 markdown。
只需将 loader 添加到您的配置中,并设置 options。
import md from "markdown-file.md";
console.log(md);
webpack.config.js
import RemarkHTML from "remark-html";
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "html-loader",
},
{
loader: "remark-loader",
options: {
remarkOptions: {
plugins: [RemarkHTML],
},
},
},
],
},
],
},
};
下面是 remark
plugins 的完整列表。
我们不再支持任何 react
的特殊功能。
如果您对在 JSX 中使用 Markdown 感兴趣,请参阅很棒的 MDX 项目。
Name | Type | Default | Description |
---|---|---|---|
remarkOptions | {Object} | {} | Remark options |
removeFrontMatter | {Boolean} | true | Remove removeFrontMatter |
Name | Type | Default | Description |
---|---|---|---|
plugins | Array<String|Array> | [] | Allows to connect remark plugins |
settings | {Object} | undefined | Remark settings |
data | {Object} | undefined | Information available to all plugins |
Type: Array<String|Array>
Default: []
可以和 remark
plugins 一起使用
webpack.config.js
import RemarkFrontmatter from "remark-frontmatter";
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
remarkOptions: {
plugins: [RemarkFrontmatter],
},
},
},
],
},
],
},
};
如果需要为插件指定 options,可以使用数组传递插件,其中第二个参数就是将要设置的 options。
webpack.config.js
import RemarkFrontmatter from "remark-frontmatter";
import RemarkBookmarks from "remark-bookmarks";
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
remarkOptions: {
plugins: [
RemarkFrontmatter,
[
RemarkBookmarks,
{
bookmarks: {
npm: "https://npmjs.com/package/remark-bookmarks",
},
},
],
],
},
},
},
],
},
],
},
};
Type: Object
Default: undefined
将 remark-stringify
options 选项和 remark-parse
options 选项传递给 remark
。
webpack.config.js
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
remarkOptions: {
settings: {
bullet: "+",
listItemIndent: "1",
},
},
},
},
],
},
],
},
};
Type: Object
Default: undefined
使用所有插件通用的配置 remark
。
配置信息存储在内存中的键值存储中。
webpack.config.js
function examplePluginUsingData() {
console.log(this.data);
// { alpha: 'bravo', charlie: 'delta' }
}
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
remarkOptions: {
plugins: [examplePluginUsingData],
data: {
alpha: "bravo",
charlie: "delta",
},
},
},
},
],
},
],
},
};
Type: Boolean
Default: true
默认情况下,refortmatter 是被移除的。
如果要覆盖这个配置,需要在插件中添加 remark-frontmatter
,并设置 removeFrontMatter
为 false
。
webpack.config.js
import RemarkFrontmatter from "remark-frontmatter";
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
removeFrontMatter: false,
remarkOptions: {
plugins: [RemarkFrontmatter],
},
},
},
],
},
],
},
};
这个项目收到了以下开源作品的启发:
要获得 html,需要在 remark 插件中添加 remark-html
,并在 webpack.config
中添加 html-loader
。
import md from "markdown-file.md";
console.log(md);
webpack.config.js
import RemarkHTML from "remark-html";
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "html-loader",
},
{
loader: "remark-loader",
options: {
remarkOptions: {
plugins: [RemarkHTML],
},
},
},
],
},
],
},
};
index.js
import md from "markdown-file.md";
console.log(md);
webpack.config.js
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
},
],
},
],
},
};
如果您还没有贡献代码,请花点时间阅读我们的贡献指南。
加载 Sass/SCSS 文件并将他们编译为 CSS。
首先,你需要安装 sass-loader
:
npm install sass-loader sass webpack --save-dev
sass-loader
需要预先安装 Dart Sass 或 Node Sass(可以在这两个链接中找到更多的资料)。这可以控制所有依赖的版本, 并自由的选择使用的 Sass 实现。
这样可以控制所有依赖项的版本,并选择要使用的 Sass 实现。
ℹ️ 我们推荐使用 Dart Sass。
将 sass-loader
、css-loader 与 style-loader 进行链式调用,可以将样式以 style 标签的形式插入 DOM 中,或者使用 mini-css-extract-plugin 将样式输出到独立的文件中。
然后将本 loader 添加到你的 Webpack 配置中。例如:
app.js
import './style.scss';
style.scss
$body-color: red;
body {
color: $body-color;
}
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// 将 JS 字符串生成为 style 节点
'style-loader',
// 将 CSS 转化成 CommonJS 模块
'css-loader',
// 将 Sass 编译成 CSS
'sass-loader',
],
},
],
},
};
最后通过你喜欢的方式运行 webpack
。
import
的规则Webpack 提供一种 解析文件的高级机制。
sass-loader
使用 Sass 提供的 custom importer 特性,将所有 query 传递给 Webpack 解析引擎。
因此你可以从 node_modules
中引入 Sass modules。
@import "bootstrap";
~
用法已被废弃,可以从代码中删除(我们建议这么做),但是我们会因为一些历史原因一直支持这种写法。
为什么你可以移除它呢?loader 首先会尝试以相对路径解析 @import
,如果它不能被解析,loader 将会尝试在 node_modules
中解析 @import
。
在包名前加上 ~
就会告诉 Webpack 在 modules
中进行查找。
@import "~bootstrap";
重要的是,只在前面加上 ~
,因为~/
将会解析到用户的主目录(home directory)。
因为 CSS 和 Sass 文件没有用于导入相关文件的特殊语法,所以 Webpack 需要区分 bootstrap
和 ~bootstrap
。
@import "style.scss"
和 @import "./style.scss";
两种写法是相同的。
url(...)
的问题由于 Sass 的实现没有提供 url 重写的功能,所以相关的资源都必须是相对于输出文件(ouput)而言的。
css-loader
,则所有的 url 规则都必须是相对于入口文件的(例如:main.scss
)。css-loader
,那么所有的 url 都是相对于网站的根目录的。第一种情况可能会带来一些困扰。通常情况下我们希望相对路径引用的解析是相对于声明它的 .sass
/.scss
文件(如同在 .css
文件中一样)。
幸运的是,有两种方法可以解决这个问题:
sass-loader
之前,就可以重写 url。$icon-font-path
进行设置。名称 | 类型 | 默认值 | Description |
---|---|---|---|
implementation | {Object|String} | sass | 设置使用的 Sass 的实现。 |
sassOptions | {Object|Function} | Sass 实现的默认值 | Sass 自身选项。 |
sourceMap | {Boolean} | compiler.devtool | 启用 / 禁用 source maps 的生成。 |
additionalData | {String|Function} | undefined | 在实际的输入文件之前添加 Sass /SCSS 代码。 |
webpackImporter | {Boolean} | true | 启用 / 禁用默认的 Webpack importer。 |
warnRuleAsWarning | {Boolean} | false | 将 @warn 规则视为 webpack 警告。 |
implementation
类型: Object | String
默认值: sass
特殊的 implementation
选项确定要使用的 Sass 实现。
默认情况下,loader 将会根据你的依赖解析需要使用的实现。
只需将必需的实现添加到 package.json
(sass
或 node-sass
包)中并安装依赖项即可。
示例,此时 sass-loader
将会使用 sass
(dart-sass
)实现:
package.json
{
"devDependencies": {
"sass-loader": "^7.2.0",
"sass": "^1.22.10"
}
}
示例,此时 sass-loader
将会使用 node-sass
实现:
package.json
{
"devDependencies": {
"sass-loader": "^7.2.0",
"node-sass": "^5.0.0"
}
}
需注意同时安装 node-sass
和 sass
的情况!默认情况下,sass-loader
会选择 sass
。
为了避免这种情况,你可以使用 implementation
选项。
implementation
选项可以以模块的形式接受 sass
(Dart Sass
)或 node-sass
。
例如,为了使用 Dart Sass,你应该传递:
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
// `dart-sass` 是首选
implementation: require('sass'),
},
},
],
},
],
},
};
例如,为了使用 Dart Sass,你应该传递:
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
// Prefer `dart-sass`
implementation: require.resolve('sass'),
},
},
],
},
],
},
};
需要注意的是,当使用 sass
(Dart Sass
)时,由于异步回调的开销,通常情况下同步编译的速度是异步编译速度的两倍。
为了避免这种开销,你可以使用 fibers 包从同步代码中调用异步导入程序。
如果可能,我们会为小于 v16.0.0 的 Node.js
自动注入 fibers
软件包(设置 sassOptions.fiber
)(当然需要你安装 fibers
包)。
Fibers 不兼容
Node.js
v16.0.0 以及更高的版本(查看介绍)。
package.json
{
"devDependencies": {
"sass-loader": "^7.2.0",
"sass": "^1.22.10",
"fibers": "^4.0.1"
}
}
你可以通过向 sassOptions.fiber
传递 false
参数关闭自动注入的 fibers
包。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
sassOptions: {
fiber: false,
},
},
},
],
},
],
},
};
你还可以通过一下代码传递 fiber
:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
sassOptions: {
fiber: require('fibers'),
},
},
},
],
},
],
},
};
sassOptions
类型:Object|Function
默认值:Sass 实现的默认值
ℹ️
dart-sass
的charset
选项默认为true
,我们强烈建议你将其改为false
,因为 webpack 并不支持utf-8
以外的文件。
ℹ️
indentedSyntax
选项值为true
,是对sass
的扩展。
ℹ️ 像
data
和file
这样的选项是不可用的,且会被忽略。
ℹ 我们坚决反对设置
outFile
,sourceMapContents
,sourceMapEmbed
,sourceMapRoot
这些选项,因为当sourceMap
是true
时,sass-loader
会自动设置这些选项。
ℹ️ 可以使用
this.webpackLoaderContext
属性访问自定义 importer 中的 loader 上下文。
sass
(dart-sass
)和 node-sass
之间的选项略有不同。
在使用他们之前,请查阅有关文档:
sass
选项。node-sass
选项。Object
使用对象设置 Sass 实现的启动选项。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
sassOptions: {
indentWidth: 4,
includePaths: ['absolute/path/a', 'absolute/path/b'],
},
},
},
],
},
],
},
};
Function
允许通过 loader 上下文为 Sass 实现设置不同的选项。
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
sassOptions: (loaderContext) => {
// 有关可用属性的更多信息 https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.scss') {
return {
includePaths: ['absolute/path/c', 'absolute/path/d'],
};
}
return {
includePaths: ['absolute/path/a', 'absolute/path/b'],
};
},
},
},
],
},
],
},
};
sourceMap
类型:Boolean
默认值:取决于 compiler.devtool
的值
开启/关闭生成 source map。
默认情况下 source maps 的生成取决于 devtool
选项。
除 eval
和 false
之外的所有值都将开启 source map 的生成。
ℹ 如果为
true
将会忽略来自sassOptions
的sourceMap
,sourceMapRoot
,sourceMapEmbed
,sourceMapContents
和omitSourceMapUrl
选项。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
};
ℹ 在极少数情况下,
node-sass
会输出无效的 source maps(这是node-sass
的 bug)。
为了避免这种情况,你可以尝试将
node-sass
更新到最新版本,或者可以尝试将sassOptions
中的outputStyle
选项设置为compressed
。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
sourceMap: true,
sassOptions: {
outputStyle: 'compressed',
},
},
},
],
},
],
},
};
additionalData
类型:String|Function
默认值:undefined
在实际的文件之前要添加的 Sass
/ SCSS
代码。
在这种情况下,sass-loader
将不会覆盖 data
选项,而只是将它拼接在入口文件内容之前。
当某些 Sass 变量取决于环境时,这非常有用:
String
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
additionalData: '$env: ' + process.env.NODE_ENV + ';',
},
},
],
},
],
},
};
Function
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
additionalData: (content, loaderContext) => {
// 有关可用属性的更多信息 https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.scss') {
return '$value: 100px;' + content;
}
return '$value: 200px;' + content;
},
},
},
],
},
],
},
};
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
additionalData: async (content, loaderContext) => {
// More information about available properties https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.scss') {
return '$value: 100px;' + content;
}
return '$value: 200px;' + content;
},
},
},
],
},
],
},
};
webpackImporter
类型:Boolean
默认值:true
开启 / 关闭默认的 Webpack importer。
在某些情况下,可以提高性能。但是请谨慎使用,因为 aliases 和以 〜
开头的 @import
规则将不起作用。
你可以传递自己的 importer
来解决这个问题(参阅 importer docs
)。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
webpackImporter: false,
},
},
],
},
],
},
};
warnRuleAsWarning
Type: Boolean
Default: false
将 @warn
规则视为 webpack 警告。
ℹ️ 在下一个大版本发布中它将默认设置为
true
。
style.scss
$known-prefixes: webkit, moz, ms, o;
@mixin prefix($property, $value, $prefixes) {
@each $prefix in $prefixes {
@if not index($known-prefixes, $prefix) {
@warn "Unknown prefix #{$prefix}.";
}
-#{$prefix}-#{$property}: $value;
}
#{$property}: $value;
}
.tilt {
// Oops, we typo'd "webkit" as "wekbit"!
@include prefix(transform, rotate(15deg), wekbit ms);
}
给出的代码将抛出 webpack 警告而不是日志。
要忽略不必要的警告,可以使用 ignoreWarnings 配置项。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
"style-loader",
"css-loader",
{
loader: "sass-loader",
options: {
warnRuleAsWarning: true,
},
},
],
},
],
},
};
对于生产版本,我们建议从 bundle 中提取 CSS,以便之后可以使 CSS/JS 资源并行加载。
从 bundle 中提取样式表,有 2 种实用的方式:
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// 在开发过程中回退到 style-loader
process.env.NODE_ENV !== 'production'
? 'style-loader'
: MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
// 与 webpackOptions.output 中的选项相似
// 所有的选项都是可选的
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
};
开启/关闭 source map 的生成。
为了开启 CSS source maps,需要将 sourceMap
选项作为参数,传递给 sass-loader
和 css-loader
。
webpack.config.js
module.exports = {
devtool: "source-map", // 任何类似于 "source-map" 的选项都是支持的
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
"style-loader",
{
loader: "css-loader",
options: {
sourceMap: true,
},
},
{
loader: "sass-loader",
options: {
sourceMap: true,
},
},
],
},
],
},
};
如果你要在 Chrome 中编辑原始的 Sass 文件,建议阅读 这篇不错的博客。具体示例参考 test/sourceMap。
如果你还没有阅读过我们的贡献指南,请花一点时间阅读它。
从现有的源文件中提取 source maps(从 sourceMappingURL
中提取)。
安装 source-map-loader
:
npm i -D source-map-loader
添加 plugin 至 webpack
配置。例:
file.js
import css from 'file.css';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
enforce: 'pre',
use: ['source-map-loader'],
},
],
},
};
source-map-loader
从 JavaScript 入口提取现有的 source maps.
这些 source maps 既可以是内联的也可以是通过 URL 链接引入的。
所有的 source map 数据都按照选定的 source map style 交给 webpack 处理,这些选定可以在 webpack.config.js 的 devtool
选项中配置。
在使用有自己 source maps 的第三方库时,source-map-loader
就显得尤为重要。
如果相关 source map 数据没有按照规范提取、处理并注入 webpack bundle, 浏览器有可能无法正确解读这些数据。source-map-loader
允许 webpack 跨库且持续的维护 source map 数据,因而更易于调试。
source-map-loader
可以从任何 JavaScript 文件中提取,这也包括 node_modules
目录下的 JavaScript 文件。
在设置 include 和 exclude 规则时,要保证构建性能最优。
最后按偏好运行 webpack
方法。
选项名 | 类型 | 默认值 | 描述 |
---|---|---|---|
filterSourceMappingUrl | {Function} | undefined | 允许控制 SourceMappingURL 的行为 |
类型:Function
默认值:undefined
允许你为 SourceMappingURL
注释指定 loader 的特定行为。
此函数的返回值必须为下列之一:
true
或 'consume'
— 使用 source map 并删除 SourceMappingURL
注释(默认行为)false
或 'remove'
— 不使用 source map 并删除 SourceMappingURL
注释skip
— 不使用 source map 但不删除 SourceMappingURL
注释示例配置:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
enforce: 'pre',
use: [
{
loader: 'source-map-loader',
options: {
filterSourceMappingUrl: (url, resourcePath) => {
if (/broker-source-map-url\.js$/i.test(url)) {
return false;
}
if (/keep-source-mapping-url\.js$/i.test(resourcePath)) {
return 'skip';
}
return true;
},
},
},
],
},
],
},
};
忽略警告可以使用以下配置:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
enforce: 'pre',
use: ['source-map-loader'],
},
],
},
ignoreWarnings: [/Failed to parse source map/],
};
欲了解 ignoreWarnings
的更多信息,请查阅此文。
如果您尚未了解,建议您阅读以下贡献指引。
把 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 的 Stylus loader。将 Stylus 文件编译为 CSS。
首先,你需要安装 stylus
和 stylus-loader
:
npm install stylus stylus-loader --save-dev
然后将该 loader 添加到 webpack
配置中。例如:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
loader: 'stylus-loader', // 将 Stylus 文件编译为 CSS
},
],
},
};
接着按照你习惯的方式运行 webpack
。
Name | Type | Default | Description |
---|---|---|---|
stylusOptions | {Object|Function} | {} | Stylus 的可选项。 |
sourceMap | {Boolean} | compiler.devtool | 启用/禁用生成 SourceMap。 |
webpackImporter | {Boolean} | true | 启用/禁用默认的 webpack importer。 |
additionalData | {String|Function} | undefined | 在入口文件起始或末尾添加 Stylus 代码。 |
implementation | {String|Function} | stylus | 配置 Stylus 使用的实现库。 |
stylusOptions
类型:Object|Function
默认值:{}
通过 stylusOptions
属性,你可以给 stylus-loader
配置 loader options 中任意特定的选项值。
所有可用选项可以查看 Stylus 文档。
这些配置项需要将破折号(dash-case)转换为驼峰值(camelCase)后进行设置。
Object
使用对象(Object)的形式传递 options 给 Stylus。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'stylus-loader',
options: {
stylusOptions: {
/**
* 指定要使用的 Stylus 插件。将插件作为
* 字符串进行传递,而不是从 Webpack 配置中导入。
*
* @type {(string|Function)[]}
* @default []
*/
use: ['nib'],
/**
* 指定 path 的查找路径。
*
* @type {string[]}
* @default []
*/
include: [path.join(__dirname, 'src/styl/config')],
/**
* 导入指定的 Stylus 文件或者路径
*
* @type {string[]}
* @default []
*/
import: ['nib', path.join(__dirname, 'src/styl/mixins')],
/**
* 定义 Stylus 变量或者函数。
*
* @type {Array|Object}
* @default {}
*/
// 定义数组语法的推荐格式:[key, value, raw]
define: [
['$development', process.env.NODE_ENV === 'development'],
['rawVar', 42, true],
],
// Object 语法已经弃用(不可指定 "raw' 选项)
// define: {
// $development: process.env.NODE_ENV === 'development',
// rawVar: 42,
// },
/**
* 是否包含通过 @import 导入的常规 CSS。
*
* @type {boolean}
* @default false
*/
includeCSS: false,
/**
* 解析导入文件中的相对 url()。
*
* @see https://stylus-lang.com/docs/js.html#stylusresolveroptions
*
* @type {boolean|Object}
* @default { nocheck: true }
*/
resolveURL: true,
// resolveURL: { nocheck: true },
/**
* 生成 CSS 后 注入注释并指定其所在 Stylus 文件行。
*
* @see https://stylus-lang.com/docs/executable.html
*
* @type {boolean}
* @default false
*/
lineNumbers: true,
/**
* 将 @import 和 @charset 移至文件顶部。
*
* @see https://stylus-lang.com/docs/executable.html
*
* @type {boolean}
* @default false
*/
hoistAtrules: true,
/**
* 压缩输出的 CSS。
* 生产环境默认值为 `true`
*
* @see https://stylus-lang.com/docs/executable.html
*
* @type {boolean}
* @default false
*/
compress: true,
},
},
},
],
},
],
},
};
Function
允许根据 loader 的 context 来设置 options,再传递给 Stylus。
module.exports = {
module: {
rules: [
{
test: /\.styl/,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
options: {
stylusOptions: (loaderContext) => {
// 更多可用的属性参见 https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.styl') {
return {
paths: ['absolute/path/c', 'absolute/path/d'],
};
}
return {
paths: ['absolute/path/a', 'absolute/path/b'],
};
},
},
},
],
},
],
},
};
sourceMap
类型:Boolean
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'stylus-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
};
webpackImporter
类型:Boolean
默认值:true
启用/禁用 webpack 默认的 importer。
在某些情况下,这样做可以提高性能。
但是请慎用,因为可能会使得 aliases 和以 ~
开头的 @import
规则失效。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl/i,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
options: {
webpackImporter: false,
},
},
],
},
],
},
};
additionalData
类型:String|Function
默认值:undefined
在实际入口文件的起始位置添加 Stylus
代码。
这种情况下,stylus-loader
只会追加并不会覆盖文件内容。
当你的 Stylus 变量依赖环境变量时这个属性将非常有用:
ℹ 由于你注入了代码,因此它将破坏入口文件的源映射关系。通常有比这更简单的解决方案,例如多个 Stylus 入口文件。
String
module.exports = {
module: {
rules: [
{
test: /\.styl/,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
options: {
additionalData: `@env: ${process.env.NODE_ENV};`,
},
},
],
},
],
},
};
Function
module.exports = {
module: {
rules: [
{
test: /\.styl/,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
options: {
additionalData: (content, loaderContext) => {
// 更多可用的属性参见 https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.styl') {
return 'value = 100px' + content;
}
return 'value 200px' + content;
},
},
},
],
},
],
},
};
module.exports = {
module: {
rules: [
{
test: /\.styl/,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
options: {
additionalData: async (content, loaderContext) => {
// 更多可用的属性参见 https://webpack.js.org/api/loaders/
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath === 'styles/foo.styl') {
return 'value = 100px' + content;
}
return 'value 200px' + content;
},
},
},
],
},
],
},
};
implementation
类型:Function | String
特殊的 implementation
选项决定使用 Stylus 的哪个实现。将会覆盖本地安装的 stylus
的 peerDependency
版本。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl/i,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
options: {
implementation: require('stylus'),
},
},
],
},
],
},
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl/i,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
options: {
implementation: require.resolve('stylus'),
},
},
],
},
],
},
};
将 stylus-loader
、css-loader
和 style-loader
串联起来使用可立即将所有样式更新到 DOM。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
{
loader: 'style-loader', // 从 JS 中创建样式节点
},
{
loader: 'css-loader', // 将 CSS 转为 CommonJS
},
{
loader: 'stylus-loader', // 将 Stylus 编译为 CSS
},
],
},
],
},
};
为了生成 CSS 的 source map, 你需要在 loader 的可选项中设置 sourceMap
属性。如果没设置的话 loader 将会继承你 webpack 中为生成 source map 设置的属性值 devtool
。
webpack.config.js
module.exports = {
devtool: 'source-map', // 任何类似于 "source-map" 的 devtool 值都可以
module: {
rules: [
{
test: /\.styl$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'stylus-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
{
loader: 'style-loader', // 从 JS 中创建样式节点
},
{
loader: 'css-loader', // 将 CSS 转为 CommonJS
},
{
loader: 'stylus-loader', // 将 Stylus 编译为 CSS
options: {
stylusOptions: {
use: [require('nib')()],
import: ['nib'],
},
},
},
],
},
],
},
};
Stylus 在 json
函数中无效。
因此 webpack 解析器不适用于 .json
文件。
可使用 stylus resolver
。
index.styl
// 假设文件位置在这里 `node_modules/vars/vars.json`
json('vars.json')
@media queries-small
body
display nope
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
options: {
stylusOptions: {
// 指定文件查找路径。
paths: ['node_modules/vars'],
},
},
},
],
},
],
},
};
在生产环境中推荐使用 MiniCssExtractPlugin 来提取样式表到专门的文件中,这样你的样式就不需要依赖 JavaScript。
webpack
提供了一种 解析文件的高级机制。
stylus-loader
将所有的查询结果传递给了 webpack 解析器。
因此你可以从 node_modules
中导入 Stylus 模块。
@import 'bootstrap-styl/bootstrap/index.styl';
~
用法已被废弃,可以从代码中删除(我们建议这么做),但是我们会因为一些历史原因一直支持这种写法。
为什么你可以移除它呢?loader 首先会尝试以相对路径解析 @import
,如果它不能被解析,loader 将会尝试在 node_modules
中解析 @import
。
只要在包名前加上 ~
,告诉 webpack 在 modules
中进行查找。
@import "~bootstrap-styl/bootstrap/index.styl";
重要的是只在它的前面加上 ~
,因为 ~/
会被解析到根目录。
webpack
需要区分 bootstrap
和 ~bootstrap
,因为 CSS 和 Stylus 文件没有特殊的语法可以导入相对路径的文件。
@import "file"
和 @import "./file";
写法是等价的。
如果指定 paths
选项,将从指定的 paths
中搜索模块。
这是 Stylus 的默认行为。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'stylus-loader',
options: {
stylusOptions: {
paths: [path.resolve(__dirname, 'node_modules')],
},
},
},
],
},
],
},
};
通过 webpack 打包 CSS 有很多好处,比如给引用图片和字体文件路径添加 hash, 在开发环境可以模块热更新。另一方面,在生产环境,根据 JS 来控制应用样式表不是一个好的方式,可能会导致延迟渲染,甚至可能会出现闪烁现象。因此,在你最终的生产环境中将它们拆分成单独的文件来存放通常是比较好的选择。
有两种从 bundle 中提取样式表的方式:
extract-loader
(简单,但得专门指定 css-loader
的 output)如果你还没有看过我们的贡献者指南请先花点时间看一下。
运行以下 loader 在 worker pool 中。
npm install --save-dev thread-loader
使用时,需将此 loader 放置在其他 loader 之前。放置在此 loader 之后的 loader 会在一个独立的 worker 池中运行。
在 worker 池中运行的 loader 是受到限制的。例如:
每个 worker 都是一个独立的 node.js 进程,其开销大约为 600ms 左右。同时会限制跨进程的数据交换。
请仅在耗时的操作中使用此 loader!
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
include: path.resolve('src'),
use: [
"thread-loader",
// 耗时的 loader (例如 babel-loader)
],
},
],
},
};
with options
use: [
{
loader: "thread-loader",
// 有同样配置的 loader 会共享一个 worker 池
options: {
// 产生的 worker 的数量,默认是 (cpu 核心数 - 1),或者,
// 在 require('os').cpus() 是 undefined 时回退至 1
workers: 2,
// 一个 worker 进程中并行执行工作的数量
// 默认为 20
workerParallelJobs: 50,
// 额外的 node.js 参数
workerNodeArgs: ['--max-old-space-size=1024'],
// 允许重新生成一个僵死的 work 池
// 这个过程会降低整体编译速度
// 并且开发环境应该设置为 false
poolRespawn: false,
// 闲置时定时删除 worker 进程
// 默认为 500(ms)
// 可以设置为无穷大,这样在监视模式(--watch)下可以保持 worker 持续存在
poolTimeout: 2000,
// 池分配给 worker 的工作数量
// 默认为 200
// 降低这个数值会降低总体的效率,但是会提升工作分布更均一
poolParallelJobs: 50,
// 池的名称
// 可以修改名称来创建其余选项都一样的池
name: "my-pool"
},
},
// 耗时的 loader(例如 babel-loader)
];
预警
可以通过预警 worker 池来防止启动 worker 时的高延时。
这会启动池内最大数量的 worker 并把指定的模块加载到 node.js 的模块缓存中。
const threadLoader = require('thread-loader');
threadLoader.warmup(
{
// 池选项,例如传递给 loader 选项
// 必须匹配 loader 选项才能启动正确的池
},
[
// 加载模块
// 可以是任意模块,例如
'babel-loader',
'babel-preset-es2015',
'sass-loader',
]
);
如果还未阅读贡献指南,请抽时间进行阅读。
A webpack loader which executes a given module, and returns the result of the execution at build-time, when the module is required in the bundle. In this way, the loader changes a module from code to a result.
Another way to view val-loader
, is that it allows a user a way to make their
own custom loader logic, without having to write a custom loader.
The target module is called with two arguments: (options, loaderContext)
options
: The loader options (for instance provided in the webpack config. See the example below).loaderContext
: The loader context.To begin, you'll need to install val-loader
:
npm install val-loader --save-dev
Then add the loader to your webpack
config. For example:
target-file.js
module.exports = (options, loaderContext) => {
return { code: 'module.exports = 42;' };
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /target-file.js$/,
use: [
{
loader: `val-loader`,
},
],
},
],
},
};
src/entry.js
const answer = require('target-file');
And run webpack
via your preferred method.
Name | Type | Default | Description |
---|---|---|---|
executableFile | {String} | undefined | Allows to specify path to the executable file |
Type: String
Default: undefined
Allows to specify path to the executable file
data.json
{
"years": "10"
}
executable-file.js
module.exports = function yearsInMs(options, loaderContext, content) {
const { years } = JSON.parse(content);
const value = years * 365 * 24 * 60 * 60 * 1000;
return {
cacheable: true,
code: 'module.exports = ' + value,
};
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(json)$/i,
rules: [
{
loader: 'val-loader',
options: {
executableFile: path.resolve(
__dirname,
'fixtures',
'executableFile.js'
),
},
},
],
},
{
test: /\.json$/i,
type: 'asset/resource',
},
],
},
};
Targeted modules of this loader must export a Function
that returns an object,
or a Promise
resolving an object (e.g. async function), containing a code
property at a minimum, but can
contain any number of additional properties.
code
Type: String|Buffer
Default: undefined
Required
Code passed along to webpack or the next loader that will replace the module.
sourceMap
Type: Object
Default: undefined
A source map passed along to webpack or the next loader.
ast
Type: Array[Object]
Default: undefined
An Abstract Syntax Tree that will be passed to the next loader. Useful to speed up the build time if the next loader uses the same AST.
dependencies
Type: Array[String]
Default: []
An array of absolute, native paths to file dependencies that should be watched by webpack for changes.
Dependencies can also be added using loaderContext.addDependency(file: string)
.
contextDependencies
Type: Array[String]
Default: []
An array of absolute, native paths to directory dependencies that should be watched by webpack for changes.
Context dependencies can also be added using loaderContext.addContextDependency(directory: string)
.
buildDependencies
Type: Array[String]
Default: []
An array of absolute, native paths to directory dependencies that should be watched by webpack for changes.
Build dependencies can also be added using loaderContext.addBuildDependency(file: string)
.
cacheable
Type: Boolean
Default: false
If true
, specifies that the code can be re-used in watch mode if none of the
dependencies
have changed.
In this example the loader is configured to operator on a file name of
years-in-ms.js
, execute the code, and store the result in the bundle as the
result of the execution. This example passes years
as an option
, which
corresponds to the years
parameter in the target module exported function:
years-in-ms.js
module.exports = function yearsInMs({ years }) {
const value = years * 365 * 24 * 60 * 60 * 1000;
// NOTE: this return value will replace the module in the bundle
return {
cacheable: true,
code: 'module.exports = ' + value,
};
};
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('src/years-in-ms.js'),
use: [
{
loader: 'val-loader',
options: {
years: 10,
},
},
],
},
],
},
};
In the bundle, requiring the module then returns:
import tenYearsMs from 'years-in-ms';
console.log(tenYearsMs); // 315360000000
Example shows how to build modernizr
.
entry.js
import modenizr from './modernizr.js';
modernizr.js
const modernizr = require('modernizr');
module.exports = function (options) {
return new Promise(function (resolve) {
// It is impossible to throw an error because modernizr causes the process.exit(1)
modernizr.build(options, function (output) {
resolve({
cacheable: true,
code: `var modernizr; var hadGlobal = 'Modernizr' in window; var oldGlobal = window.Modernizr; ${output} modernizr = window.Modernizr; if (hadGlobal) { window.Modernizr = oldGlobal; } else { delete window.Modernizr; } export default modernizr;`,
});
});
});
};
webpack.config.js
const path = require('path');
module.exports = {
module: {
rules: [
{
test: path.resolve(__dirname, 'src', 'modernizr.js'),
use: [
{
loader: 'val-loader',
options: {
minify: false,
options: ['setClasses'],
'feature-detects': [
'test/css/flexbox',
'test/es6/promises',
'test/serviceworker',
],
},
},
],
},
],
},
};
Example shows how to build figlet
.
entry.js
import { default as figlet } from './figlet.js';
console.log(figlet);
figlet.js
const figlet = require('figlet');
function wrapOutput(output, config) {
let figletOutput = '';
if (config.textBefore) {
figletOutput += encodeURI(`${config.textBefore}\n`);
}
output.split('\n').forEach((line) => {
figletOutput += encodeURI(`${line}\n`);
});
if (config.textAfter) {
figletOutput += encodeURI(`${config.textAfter}\n`);
}
return `module.exports = decodeURI("${figletOutput}");`;
}
module.exports = function (options) {
const defaultConfig = {
fontOptions: {
font: 'ANSI Shadow',
horizontalLayout: 'default',
kerning: 'default',
verticalLayout: 'default',
},
text: 'FIGLET-LOADER',
textAfter: null,
textBefore: null,
};
const config = Object.assign({}, defaultConfig, options);
return new Promise(function (resolve, reject) {
figlet.text(config.text, config.fontOptions, (error, output) => {
if (error) {
return reject(error);
}
resolve({
cacheable: true,
code: 'module.exports = ' + wrapOutput(output, config),
});
});
});
};
webpack.config.js
const path = require('path');
module.exports = {
module: {
rules: [
{
test: path.resolve(__dirname, 'src', 'figlet.js'),
use: [
{
loader: 'val-loader',
options: {
text: 'FIGLET',
},
},
],
},
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.