This README is for babel-loader v8/v9 with Babel v7 If you are using legacy Babel v6, see the 7.x branch docs
This package allows transpiling JavaScript files using Babel and webpack.
Note: Issues with the output should be reported on the Babel Issues tracker.
babel-loader supported webpack versions supported Babel versions supported Node.js versions 8.x 4.x or 5.x 7.x >= 8.9 9.x 5.x ^7.12.0 >= 14.15.0
npm install -D babel-loader @babel/core @babel/preset-env webpack
webpack documentation: Loaders
Within your webpack configuration object, you'll need to add the babel-loader to the list of modules, like so:
module: {
rules: [
{
test: /\.(?:js|mjs|cjs)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
targets: "defaults",
presets: [
['@babel/preset-env']
]
}
}
}
]
}
See the babel
options.
You can pass options to the loader by using the options
property:
module: {
rules: [
{
test: /\.(?:js|mjs|cjs)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
targets: "defaults",
presets: [
['@babel/preset-env']
],
plugins: ['@babel/plugin-proposal-decorators', { version: "2023-11" }]
}
}
}
]
}
The options
passed here will be merged with Babel config files, e.g. babel.config.js
or .babelrc
.
This loader also supports the following loader-specific option:
cacheDirectory
: Default false
. When set, the given directory will be used to cache the results of the loader. Future webpack builds will attempt to read from the cache to avoid needing to run the potentially expensive Babel recompilation process on each run. If the value is set to true
in options ({cacheDirectory: true}
), the loader will use the default cache directory in node_modules/.cache/babel-loader
or fallback to the default OS temporary file directory if no node_modules
folder could be found in any root directory.
cacheIdentifier
: Default is a string composed by the @babel/core
's version and the babel-loader
's version. The final cache id will be determined by the input file path, the merged Babel config via Babel.loadPartialConfigAsync
and the cacheIdentifier
. The merged Babel config will be determined by the babel.config.js
or .babelrc
file if they exist, or the value of the environment variable BABEL_ENV
and NODE_ENV
. cacheIdentifier
can be set to a custom value to force cache busting if the identifier changes.
cacheCompression
: Default true
. When set, each Babel transform output will be compressed with Gzip. If you want to opt-out of cache compression, set it to false
-- your project may benefit from this if it transpiles thousands of files.
customize
: Default null
. The path of a module that exports a custom
callback like the one that you'd pass to .custom()
. Since you already have to make a new file to use this, it is recommended that you instead use .custom
to create a wrapper loader. Only use this if you must continue using babel-loader
directly, but still want to customize.
metadataSubscribers
: Default []
. Takes an array of context function names. E.g. if you passed ['myMetadataPlugin'], you'd assign a subscriber function to context.myMetadataPlugin
within your webpack plugin's hooks & that function will be called with metadata
. See https://github.com/babel/babel-loader/main/test/metadata.test.js
for an example.
Specify the webpack option stats.loggingDebug
to output verbose debug logs.
// webpack.config.js
module.exports = {
// ...
stats: {
loggingDebug: ["babel-loader"]
}
}
Make sure you are transforming as few files as possible. Because you are probably matching /\.m?js$/
, you might be transforming the node_modules
folder or other unwanted source.
To exclude node_modules
, see the exclude
option in the loaders
config as documented above.
You can also speed up babel-loader by as much as 2x by using the cacheDirectory
option. This will cache transformations to the filesystem.
Although we typically recommend not compiling node_modules
, you may need to when using libraries that do not support IE 11 or any legacy targets.
For this, you can either use a combination of test
and not
, or pass a function to your exclude
option. You can also use negative lookahead regex as suggested here.
{
test: /\.(?:js|mjs|cjs)$/,
exclude: {
and: [/node_modules/], // Exclude libraries in node_modules ...
not: [
// Except for a few of them that needs to be transpiled because they use modern syntax
/unfetch/,
/d3-array|d3-scale/,
/@hapi[\\/]joi-date/,
]
},
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { targets: "ie 11" }]
]
}
}
}
Babel uses very small helpers for common functions such as _extend
. By default, this will be added to every file that requires it.
You can instead require the Babel runtime as a separate module to avoid the duplication.
The following configuration disables automatic per-file runtime injection in Babel, requiring @babel/plugin-transform-runtime
instead and making all helper references use it.
See the docs for more information.
NOTE: You must run npm install -D @babel/plugin-transform-runtime
to include this in your project and @babel/runtime
itself as a dependency with npm install @babel/runtime
.
rules: [
// the 'transform-runtime' plugin tells Babel to
// require the runtime instead of inlining it.
{
test: /\.(?:js|mjs|cjs)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { targets: "defaults" }]
],
plugins: ['@babel/plugin-transform-runtime']
}
}
}
]
Since @babel/plugin-transform-runtime includes a polyfill that includes a custom regenerator-runtime and core-js, the following usual shimming method using webpack.ProvidePlugin
will not work:
// ...
new webpack.ProvidePlugin({
'Promise': 'bluebird'
}),
// ...
The following approach will not work either:
require('@babel/runtime/core-js/promise').default = require('bluebird');
var promise = new Promise;
which outputs to (using 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();
The previous Promise
library is referenced and used before it is overridden.
One approach is to have a "bootstrap" step in your application that would first override the default globals before your application:
// bootstrap.js
require('@babel/runtime/core-js/promise').default = require('bluebird');
// ...
require('./app');
babel
has been moved to babel-core
.If you receive this message, it means that you have the npm package babel
installed and are using the short notation of the loader in the webpack config (which is not valid anymore as of webpack 2.x):
{
test: /\.(?:js|mjs|cjs)$/,
loader: 'babel',
}
webpack then tries to load the babel
package instead of the babel-loader
.
To fix this, you should uninstall the npm package babel
, as it is deprecated in Babel v6. (Instead, install @babel/cli
or @babel/core
.)
In the case one of your dependencies is installing babel
and you cannot uninstall it yourself, use the complete name of the loader in the webpack config:
{
test: /\.(?:js|mjs|cjs)$/,
loader: 'babel-loader',
}
core-js
and webpack/buildin
will cause errors if they are transpiled by Babel.
You will need to exclude them form babel-loader
.
{
"loader": "babel-loader",
"options": {
"exclude": [
// \\ for Windows, / for macOS and Linux
/node_modules[\\/]core-js/,
/node_modules[\\/]webpack[\\/]buildin/,
],
"presets": [
"@babel/preset-env"
]
}
}
That function is injected by Webpack itself after running babel-loader
. By default Webpack asumes that your target environment supports some ES2015 features, but you can overwrite this behavior using the output.environment
Webpack option (documentation).
To avoid the top-level arrow function, you can use output.environment.arrowFunction
:
// webpack.config.js
module.exports = {
// ...
output: {
// ...
environment: {
// ...
arrowFunction: false, // <-- this line does the trick
},
},
};
Webpack supports bundling multiple targets. For cases where you may want different Babel configurations for each target (like web
and node
), this loader provides a target
property via Babel's caller API.
For example, to change the environment targets passed to @babel/preset-env
based on the webpack target:
// babel.config.js
module.exports = api => {
return {
presets: [
[
"@babel/preset-env",
{
useBuiltIns: "entry",
// caller.target will be the same as the target option from webpack
targets: api.caller(caller => caller && caller.target === "node")
? { node: "current" }
: { chrome: "58", ie: "11" }
}
]
]
}
}
babel-loader
exposes a loader-builder utility that allows users to add custom handling
of Babel's configuration for each file that it processes.
.custom
accepts a callback that will be called with the loader's instance of
babel
so that tooling can ensure that it using exactly the same @babel/core
instance as the loader itself.
In cases where you want to customize without actually having a file to call .custom
, you
may also pass the customize
option with a string pointing at a file that exports
your custom
callback function.
// Export from "./my-custom-loader.js" or whatever you want.
module.exports = require("babel-loader").custom(babel => {
// Extract the custom options in the custom plugin
function myPlugin(api, { opt1, opt2 }) {
return {
visitor: {},
};
}
return {
// Passed the loader options.
customOptions({ opt1, opt2, ...loader }) {
return {
// Pull out any custom options that the loader might have.
custom: { opt1, opt2 },
// Pass the options back with the two custom options removed.
loader,
};
},
// Passed Babel's 'PartialConfig' object.
config(cfg, { customOptions }) {
if (cfg.hasFilesystemConfig()) {
// Use the normal config
return cfg.options;
}
return {
...cfg.options,
plugins: [
...(cfg.options.plugins || []),
// Include a custom plugin in the options and passing it the customOptions object.
[myPlugin, customOptions],
],
};
},
result(result) {
return {
...result,
code: result.code + "\n// Generated by some custom loader",
};
},
};
});
// And in your Webpack config
module.exports = {
// ..
module: {
rules: [{
// ...
loader: path.join(__dirname, 'my-custom-loader.js'),
// ...
}]
}
};
customOptions(options: Object): { custom: Object, loader: Object }
Given the loader's options, split custom options out of babel-loader
's
options.
config(cfg: PartialConfig, options: { source, customOptions }): Object
Given Babel's PartialConfig
object, return the options
object that should
be passed to babel.transform
.
result(result: Result): Result
Given Babel's result object, allow loaders to make additional tweaks to it.
Compile CoffeeScript to JavaScript.
To begin, you'll need to install coffeescript
and coffee-loader
:
npm install --save-dev coffeescript coffee-loader
or
yarn add -D coffeescript coffee-loader
or
pnpm add -D coffeescript coffee-loader
Then add the plugin to your webpack
config. For example:
file.coffee
# Assignment:
number = 42
opposite = true
# Conditions:
number = -42 if opposite
# Functions:
square = (x) -> x * x
# Arrays:
list = [1, 2, 3, 4, 5]
# Objects:
math =
root: Math.sqrt
square: square
cube: (x) -> x * square x
# Splats:
race = (winner, runners...) ->
print winner, runners
# Existence:
alert "I knew it!" if elvis?
# Array comprehensions:
cubes = (math.cube num for num in list)
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.coffee$/,
loader: "coffee-loader",
},
],
},
};
Alternative usage:
import coffee from "coffee-loader!./file.coffee";
And run webpack
via your preferred method.
Type: Object
Default: { bare: true }
Options for CoffeeScript. All possible options you can find here.
Documentation for the transpile
option you can find here.
[!NOTE]
The
sourceMap
option takes a value from thecompiler.devtool
value by default.
[!NOTE]
The
filename
option takes a value from webpack loader API. The option value will be ignored.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.coffee$/,
loader: "coffee-loader",
options: {
bare: false,
transpile: {
presets: ["@babel/env"],
},
},
},
],
},
};
From CoffeeScript 2 documentation:
[!NOTE]
CoffeeScript 2 generates JavaScript that uses the latest, modern syntax. The runtime or browsers where you want your code to run might not support all of that syntax. In that case, we want to convert modern JavaScript into older JavaScript that will run in older versions of Node or older browsers; for example,
{ a } = obj
intoa = obj.a
. This is done via transpilers like Babel, Bublé or Traceur Compiler.
You'll need to install @babel/core
and @babel/preset-env
and then create a configuration file:
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"],
},
},
},
],
},
};
For using Literate CoffeeScript you should setup:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.coffee$/,
loader: "coffee-loader",
options: {
literate: true,
},
},
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
The css-loader
interprets @import
and url()
like import/require()
and will resolve them.
[!WARNING]
To use the latest version of css-loader, webpack@5 is required
To begin, you'll need to install css-loader
:
npm install --save-dev css-loader
or
yarn add -D css-loader
or
pnpm add -D css-loader
Then add the plugin to your webpack
config. For example:
file.js
import * as css from "file.css";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
And run webpack
via your preferred method.
If, for one reason or another, you need to extract CSS as a file (i.e. do not store CSS in a JS module) you might want to check out the recommend example.
url
Type:
type url =
| boolean
| {
filter: (url: string, resourcePath: string) => boolean;
};
Default: true
Allow to enable/disables handling the CSS functions url
and image-set
.
If set to false
, css-loader
will not parse any paths specified in url
or image-set
.
A function can also be passed to control this behavior dynamically based on the path to the asset.
Starting with version 4.0.0, absolute paths are parsed based on the server root.
Examples resolutions:
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')
To import assets from a node_modules
path (include resolve.modules
) and for alias
, prefix it with a ~
:
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
Enable/disable url()
resolving.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
url: true,
},
},
],
},
};
object
Allow to filter url()
. All filtered url()
will not be resolved (left in the code as they were written).
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
url: {
filter: (url, resourcePath) => {
// resourcePath - path to css file
// Don't handle `img.png` urls
if (url.includes("img.png")) {
return false;
}
// Don't handle images under root-relative /external_images/
if (/^\/external_images\//.test(path)) {
return false;
}
return true;
},
},
},
},
],
},
};
import
Type:
type importFn =
| boolean
| {
filter: (
url: string,
media: string,
resourcePath: string,
supports?: string,
layer?: string,
) => boolean;
};
Default: true
Allows to enables/disables @import
at-rules handling.
Control @import
resolving. Absolute urls in @import
will be moved in runtime code.
Examples resolutions:
@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
To import styles from a node_modules
path (include resolve.modules
) and for alias
, prefix it with a ~
:
@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
Enable/disable @import
resolving.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
import: true,
},
},
],
},
};
object
filter
Type:
type filter = (url: string, media: string, resourcePath: string) => boolean;
Default: undefined
Allow to filter @import
. All filtered @import
will not be resolved (left in the code as they were written).
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
import: {
filter: (url, media, resourcePath) => {
// resourcePath - path to css file
// Don't handle `style.css` import
if (url.includes("style.css")) {
return false;
}
return true;
},
},
},
},
],
},
};
modules
Type:
type modules =
| boolean
| "local"
| "global"
| "pure"
| "icss"
| {
auto: boolean | regExp | ((resourcePath: string) => boolean);
mode:
| "local"
| "global"
| "pure"
| "icss"
| ((resourcePath) => "local" | "global" | "pure" | "icss");
localIdentName: string;
localIdentContext: string;
localIdentHashSalt: string;
localIdentHashFunction: string;
localIdentHashDigest: string;
localIdentRegExp: string | regExp;
getLocalIdent: (
context: LoaderContext,
localIdentName: string,
localName: string,
) => string;
namedExport: boolean;
exportGlobals: boolean;
exportLocalsConvention:
| "as-is"
| "camel-case"
| "camel-case-only"
| "dashes"
| "dashes-only"
| ((name: string) => string);
exportOnlyLocals: boolean;
getJSON: ({
resourcePath,
imports,
exports,
replacements,
}: {
resourcePath: string;
imports: object[];
exports: object[];
replacements: object[];
}) => Promise<void> | void;
};
Default: undefined
Allows to enable/disable CSS Modules or ICSS and setup configuration:
undefined
- enable CSS modules for all files matching /\.module\.\w+$/i.test(filename)
and /\.icss\.\w+$/i.test(filename)
regexp.true
- enable CSS modules for all files.false
- disables CSS Modules for all files.string
- disables CSS Modules for all files and set the mode
option, more information you can read hereobject
- enable CSS modules for all files, if modules.auto
option is not specified, otherwise the modules.auto
option will determine whether if it is CSS modules or not, more information you can read hereThe modules
option enables/disables the CSS Modules specification and setup basic behaviour.
Using false
value increase performance because we avoid parsing CSS Modules features, it will be useful for developers who use vanilla css or use other technologies.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: true,
},
},
],
},
};
Features
Scope
Using local
value requires you to specify :global
classes.
Using global
value requires you to specify :local
classes.
Using pure
value requires selectors must contain at least one local class or id.
You can find more information here.
Styles can be locally scoped to avoid globally scoping styles.
The syntax :local(.className)
can be used to declare className
in the local scope. The local identifiers are exported by the module.
With :local
(without brackets) local mode can be switched on for this selector.
The :global(.className)
notation can be used to declare an explicit global selector.
With :global
(without brackets) global mode can be switched on for this selector.
The loader replaces local selectors with unique identifiers. The chosen unique identifiers are exported by the module.
: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;
}
[!NOTE]
Identifiers are exported
exports.locals = {
className: "_23_aKvs-b8bW2Vg3fwHozO",
subClass: "_13LGdX8RMStbBE9w-t0gZ1",
};
CamelCase is recommended for local selectors. They are easier to use within the imported JS module.
You can use :local(#someId)
, but this is not recommended. Use classes instead of ids.
Composing
When declaring a local classname you can compose a local class from another local classname.
:local(.className) {
background: red;
color: yellow;
}
:local(.subClass) {
composes: className;
background: blue;
}
This doesn't result in any change to the CSS itself but exports multiple classnames.
exports.locals = {
className: "_23_aKvs-b8bW2Vg3fwHozO",
subClass: "_13LGdX8RMStbBE9w-t0gZ1 _23_aKvs-b8bW2Vg3fwHozO",
};
._23_aKvs-b8bW2Vg3fwHozO {
background: red;
color: yellow;
}
._13LGdX8RMStbBE9w-t0gZ1 {
background: blue;
}
Importing
To import a local classname from another module.
[!NOTE]
We strongly recommend that you specify the extension when importing a file, since it is possible to import a file with any extension and it is not known in advance which file to use.
:local(.continueButton) {
composes: button from "library/button.css";
background: red;
}
:local(.nameEdit) {
composes: edit highlight from "./edit.css";
background: red;
}
To import from multiple modules use multiple composes:
rules.
:local(.className) {
composes:
edit highlight from "./edit.css",
button from "module/button.css",
classFromThisModule;
background: red;
}
or
:local(.className) {
composes: edit highlight from "./edit.css";
composes: button from "module/button.css";
composes: classFromThisModule;
background: red;
}
Values
You can use @value
to specific values to be reused throughout a document.
We recommend use prefix v-
for values, s-
for selectors and m-
for media at-rules.
@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
Enable CSS Modules features.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: true,
},
},
],
},
};
string
Enable CSS Modules features and setup mode
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
// Using `local` value has same effect like using `modules: true`
modules: "global",
},
},
],
},
};
object
Enable CSS Modules features and setup options for them.
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: "as-is",
exportOnlyLocals: false,
getJSON: ({ resourcePath, imports, exports, replacements }) => {},
},
},
},
],
},
};
auto
Type:
type auto =
| boolean
| regExp
| ((
resourcePath: string,
resourceQuery: string,
resourceFragment: string,
) => boolean);
Default: undefined
Allows auto enable CSS modules/ICSS based on the filename, query or fragment when modules
option is object.
Possible values:
undefined
- enable CSS modules for all files.true
- enable CSS modules for all files matching /\.module\.\w+$/i.test(filename)
and /\.icss\.\w+$/i.test(filename)
regexp.false
- disables CSS Modules.RegExp
- enable CSS modules for all files matching /RegExp/i.test(filename)
regexp.function
- enable CSS Modules for files based on the filename satisfying your filter function check.boolean
Possible values:
true
- enables CSS modules or interoperable CSS format, sets the modules.mode
option to local
value for all files which satisfy /\.module(s)?\.\w+$/i.test(filename)
condition or sets the modules.mode
option to icss
value for all files which satisfy /\.icss\.\w+$/i.test(filename)
conditionfalse
- disables CSS modules or interoperable CSS format based on filenamewebpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
auto: true,
},
},
},
],
},
};
RegExp
Enable CSS modules for files based on the filename satisfying your regex check.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
auto: /\.custom-module\.\w+$/i,
},
},
},
],
},
};
function
Enable CSS modules for files based on the filename, query or fragment satisfying your filter function check.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
auto: (resourcePath, resourceQuery, resourceFragment) => {
return resourcePath.endsWith(".custom-module.css");
},
},
},
},
],
},
};
mode
Type:
type mode =
| "local"
| "global"
| "pure"
| "icss"
| ((
resourcePath: string,
resourceQuery: string,
resourceFragment: string,
) => "local" | "global" | "pure" | "icss");
Default: 'local'
Setup mode
option. You can omit the value when you want local
mode.
Controls the level of compilation applied to the input styles.
The local
, global
, and pure
handles class
and id
scoping and @value
values.
The icss
will only compile the low level Interoperable CSS
format for declaring :import
and :export
dependencies between CSS and other languages.
ICSS underpins CSS Module support, and provides a low level syntax for other tools to implement CSS-module variations of their own.
string
Possible values - local
, global
, pure
, and icss
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
mode: "global",
},
},
},
],
},
};
function
Allows set different values for the mode
option based on the filename, query or fragment.
Possible return values - local
, global
, pure
and icss
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
// Callback must return "local", "global", or "pure" values
mode: (resourcePath, resourceQuery, resourceFragment) => {
if (/pure.css$/i.test(resourcePath)) {
return "pure";
}
if (/global.css$/i.test(resourcePath)) {
return "global";
}
return "local";
},
},
},
},
],
},
};
localIdentName
Type:
type localIdentName = string;
Default: '[hash:base64]'
Allows to configure the generated local ident name.
For more information on options see:
Supported template strings:
[name]
the basename of the resource[folder]
the folder the resource relative to the compiler.context
option or modules.localIdentContext
option.[path]
the path of the resource relative to the compiler.context
option or modules.localIdentContext
option.[file]
- filename and path.[ext]
- extension with leading .
.[hash]
- the hash of the string, generated based on localIdentHashSalt
, localIdentHashFunction
, localIdentHashDigest
, localIdentHashDigestLength
, localIdentContext
, resourcePath
and exportName
[<hashFunction>:hash:<hashDigest>:<hashDigestLength>]
- hash with hash settings.[local]
- original class.Recommendations:
'[path][name]__[local]'
for development'[hash:base64]'
for productionThe [local]
placeholder contains original class.
Note: all reserved (<>:"/\|?*
) and control filesystem characters (excluding characters in the [local]
placeholder) will be converted to -
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
localIdentName: "[path][name]__[local]--[hash:base64:5]",
},
},
},
],
},
};
localIdentContext
Type:
type localIdentContex = string;
Default: compiler.context
Allows to redefine basic loader context for local ident name.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
localIdentContext: path.resolve(__dirname, "src"),
},
},
},
],
},
};
localIdentHashSalt
Type:
type localIdentHashSalt = string;
Default: undefined
Allows to add custom hash to generate more unique classes. For more information see output.hashSalt.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
localIdentHashSalt: "hash",
},
},
},
],
},
};
localIdentHashFunction
Type:
type localIdentHashFunction = string;
Default: md4
Allows to specify hash function to generate classes . For more information see output.hashFunction.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
localIdentHashFunction: "md4",
},
},
},
],
},
};
localIdentHashDigest
Type:
type localIdentHashDigest = string;
Default: hex
Allows to specify hash digest to generate classes. For more information see output.hashDigest.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
localIdentHashDigest: "base64",
},
},
},
],
},
};
localIdentHashDigestLength
Type:
type localIdentHashDigestLength = number;
Default: 20
Allows to specify hash digest length to generate classes. For more information see output.hashDigestLength.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
localIdentHashDigestLength: 5,
},
},
},
],
},
};
hashStrategy
Type: 'resource-path-and-local-name' | 'minimal-subset'
Default: 'resource-path-and-local-name'
Should local name be used when computing the hash.
'resource-path-and-local-name'
Both resource path and local name are used when hashing. Each identifier in a module gets its own hash digest, always.'minimal-subset'
Auto detect if identifier names can be omitted from hashing. Use this value to optimize the output for better GZIP or Brotli compression.webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
hashStrategy: "minimal-subset",
},
},
},
],
},
};
localIdentRegExp
Type:
type localIdentRegExp = string | RegExp;
Default: undefined
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
localIdentRegExp: /page-(.*)\.css/i,
},
},
},
],
},
};
getLocalIdent
Type:
type getLocalIdent = (
context: LoaderContext,
localIdentName: string,
localName: string,
) => string;
Default: undefined
Allows to specify a function to generate the classname.
By default we use built-in function to generate a classname.
If the custom function returns null
or undefined
, we fallback to the
built-in function to generate the 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
Type:
type namedExport = boolean;
Default: Depends on the value of the esModule
option. If the value of the esModule
options is true
, this value will also be true
, otherwise it will be false
.
Enables/disables ES modules named export for locals.
[!WARNING]
Because it is not allowed to use the
default
class in CSS when thenamedExport
istrue
(since ECMA modules have a reserved keyworddefault
for default export), it will be automatically renamed to the_default
class.
styles.css
.foo-baz {
color: red;
}
.bar {
color: blue;
}
.default {
color: green;
}
index.js
import * as styles from "./styles.css";
// If using `exportLocalsConvention: "as-is"` (default value):
console.log(styles["foo-baz"], styles.bar);
// If using `exportLocalsConvention: "camel-case-only"`:
console.log(styles.fooBaz, styles.bar);
// For the `default` classname
console.log(styles["_default"]);
You can enable a ES module named export using:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
esModule: true,
modules: {
namedExport: true,
},
},
},
],
},
};
To set a custom name for namedExport, can use exportLocalsConvention
option as a function.
Example below in the examples
section.
exportGlobals
Type:
type exportsGLobals = boolean;
Default: false
Allow css-loader
to export names from global class or id, so you can use that as local name.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
exportGlobals: true,
},
},
},
],
},
};
exportLocalsConvention
Type:
type exportLocalsConvention =
| "as-is"
| "camel-case"
| "camel-case-only"
| "dashes"
| "dashes-only"
| ((name: string) => string);
Default: Depends on the value of the modules.namedExport
option, if true
- as-is
, otherwise camel-case-only
.
[!WARNING]
Names of locals are converted to camelcase when the named export is
false
, i.e. theexportLocalsConvention
option hascamelCaseOnly
value by default. You can set this back to any other valid option but selectors which are not valid JavaScript identifiers may run into problems which do not implement the entire modules specification.
Style of exported class names.
string
By default, the exported JSON keys mirror the class names (i.e as-is
value).
Name | Type | Description |
---|---|---|
'as-is' | string | Class names will be exported as is. |
'camel-case' | string | Class names will be camelized, the original class name will not to be removed from the locals |
'camel-case-only' | string | Class names will be camelized, the original class name will be removed from the locals |
'dashes' | string | Only dashes in class names will be camelized |
'dashes-only' | string | Dashes in class names will be camelized, the original class name will be removed from the locals |
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: "camel-case-only",
},
},
},
],
},
};
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
Type:
type exportOnlyLocals = boolean;
Default: false
Export only locals.
Useful when you use css modules for pre-rendering (for example SSR).
For pre-rendering with mini-css-extract-plugin
you should use this option instead of style-loader!css-loader
in the pre-rendering bundle.
It doesn't embed CSS but only exports the identifier mappings.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
exportOnlyLocals: true,
},
},
},
],
},
};
getJSON
Type:
type getJSON = ({
resourcePath,
imports,
exports,
replacements,
}: {
resourcePath: string;
imports: object[];
exports: object[];
replacements: object[];
}) => Promise<void> | void;
Default: undefined
Enables a callback to output the CSS modules mapping JSON. The callback is invoked with an object containing the following:
resourcePath
: the absolute path of the original resource, e.g., /foo/bar/baz.module.css
imports
: an array of import objects with data about import types and file paths, e.g.,
[
{
"type": "icss_import",
"importName": "___CSS_LOADER_ICSS_IMPORT_0___",
"url": "\"-!../../../../../node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!../../../../../node_modules/postcss-loader/dist/cjs.js!../../../../../node_modules/sass-loader/dist/cjs.js!../../../../baz.module.css\"",
"icss": true,
"index": 0
}
]
(Note that this will include all imports, not just those relevant to CSS modules.)
exports
: an array of export objects with exported names and values, e.g.,[
{
"name": "main",
"value": "D2Oy"
}
]
replacements
: an array of import replacement objects used for linking imports
and exports
, e.g.,{
"replacementName": "___CSS_LOADER_ICSS_IMPORT_0_REPLACEMENT_0___",
"importName": "___CSS_LOADER_ICSS_IMPORT_0___",
"localName": "main"
}
Using getJSON
, it's possible to output a files with all CSS module mappings.
In the following example, we use getJSON
to cache canonical mappings and
add stand-ins for any composed values (through composes
), and we use a custom plugin
to consolidate the values and output them to a file:
webpack.config.js
const path = require("path");
const fs = require("fs");
const CSS_LOADER_REPLACEMENT_REGEX =
/(___CSS_LOADER_ICSS_IMPORT_\d+_REPLACEMENT_\d+___)/g;
const REPLACEMENT_REGEX = /___REPLACEMENT\[(.*?)]\[(.*?)]___/g;
const IDENTIFIER_REGEX = /\[(.*?)]\[(.*?)]/;
const replacementsMap = {};
const canonicalValuesMap = {};
const allExportsJson = {};
function generateIdentifier(resourcePath, localName) {
return `[${resourcePath}][${localName}]`;
}
function addReplacements(resourcePath, imports, exportsJson, replacements) {
const importReplacementsMap = {};
// create a dict to quickly identify imports and get their absolute stand-in strings in the currently loaded file
// e.g., { '___CSS_LOADER_ICSS_IMPORT_0_REPLACEMENT_0___': '___REPLACEMENT[/foo/bar/baz.css][main]___' }
importReplacementsMap[resourcePath] = replacements.reduce(
(acc, { replacementName, importName, localName }) => {
const replacementImportUrl = imports.find(
(importData) => importData.importName === importName,
).url;
const relativePathRe = /.*!(.*)"/;
const [, relativePath] = replacementImportUrl.match(relativePathRe);
const importPath = path.resolve(path.dirname(resourcePath), relativePath);
const identifier = generateIdentifier(importPath, localName);
return { ...acc, [replacementName]: `___REPLACEMENT${identifier}___` };
},
{},
);
// iterate through the raw exports and add stand-in variables
// ('___REPLACEMENT[<absolute_path>][<class_name>]___')
// to be replaced in the plugin below
for (const [localName, classNames] of Object.entries(exportsJson)) {
const identifier = generateIdentifier(resourcePath, localName);
if (CSS_LOADER_REPLACEMENT_REGEX.test(classNames)) {
// if there are any replacements needed in the concatenated class names,
// add them all to the replacements map to be replaced altogether later
replacementsMap[identifier] = classNames.replaceAll(
CSS_LOADER_REPLACEMENT_REGEX,
(_, replacementName) =>
importReplacementsMap[resourcePath][replacementName],
);
} else {
// otherwise, no class names need replacements so we can add them to
// canonical values map and all exports JSON verbatim
canonicalValuesMap[identifier] = classNames;
allExportsJson[resourcePath] = allExportsJson[resourcePath] || {};
allExportsJson[resourcePath][localName] = classNames;
}
}
}
function replaceReplacements(classNames) {
return classNames.replaceAll(
REPLACEMENT_REGEX,
(_, resourcePath, localName) => {
const identifier = generateIdentifier(resourcePath, localName);
if (identifier in canonicalValuesMap) {
return canonicalValuesMap[identifier];
}
// Recurse through other stand-in that may be imports
const canonicalValue = replaceReplacements(replacementsMap[identifier]);
canonicalValuesMap[identifier] = canonicalValue;
return canonicalValue;
},
);
}
function getJSON({ resourcePath, imports, exports, replacements }) {
const exportsJson = exports.reduce((acc, { name, value }) => {
return { ...acc, [name]: value };
}, {});
if (replacements.length > 0) {
// replacements present --> add stand-in values for absolute paths and local names,
// which will be resolved to their canonical values in the plugin below
addReplacements(resourcePath, imports, exportsJson, replacements);
} else {
// no replacements present --> add to canonicalValuesMap verbatim
// since all values here are canonical/don't need resolution
for (const [key, value] of Object.entries(exportsJson)) {
const id = `[${resourcePath}][${key}]`;
canonicalValuesMap[id] = value;
}
allExportsJson[resourcePath] = exportsJson;
}
}
class CssModulesJsonPlugin {
constructor(options) {
this.options = options;
}
// eslint-disable-next-line class-methods-use-this
apply(compiler) {
compiler.hooks.emit.tap("CssModulesJsonPlugin", () => {
for (const [identifier, classNames] of Object.entries(replacementsMap)) {
const adjustedClassNames = replaceReplacements(classNames);
replacementsMap[identifier] = adjustedClassNames;
const [, resourcePath, localName] = identifier.match(IDENTIFIER_REGEX);
allExportsJson[resourcePath] = allExportsJson[resourcePath] || {};
allExportsJson[resourcePath][localName] = adjustedClassNames;
}
fs.writeFileSync(
this.options.filepath,
JSON.stringify(
// Make path to be relative to `context` (your project root)
Object.fromEntries(
Object.entries(allExportsJson).map((key) => {
key[0] = path
.relative(compiler.context, key[0])
.replace(/\\/g, "/");
return key;
}),
),
null,
2,
),
"utf8",
);
});
}
}
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: { modules: { getJSON } },
},
],
},
plugins: [
new CssModulesJsonPlugin({
filepath: path.resolve(__dirname, "./output.css.json"),
}),
],
};
In the above, all import aliases are replaced with ___REPLACEMENT[<resourcePath>][<localName>]___
in getJSON
, and they're resolved in the custom plugin. All CSS mappings are contained in allExportsJson
:
{
"foo/bar/baz.module.css": {
"main": "D2Oy",
"header": "thNN"
},
"foot/bear/bath.module.css": {
"logo": "sqiR",
"info": "XMyI"
}
}
This is saved to a local file named output.css.json
.
importLoaders
Type:
type importLoaders = number;
Default: 0
Allows to enables/disables or setups number of loaders applied before CSS loader for @import
at-rules, CSS modules and ICSS imports, i.e. @import
/composes
/@value value from './values.css'
/etc.
The option importLoaders
allows you to configure how many loaders before css-loader
should be applied to @import
ed resources and CSS modules/ICSS imports.
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",
],
},
],
},
};
This may change in the future when the module system (i. e. webpack) supports loader matching by origin.
sourceMap
Type:
type sourceMap = boolean;
Default: depends on the compiler.devtool
value
By default generation of source maps depends on the devtool
option. All values enable source map generation except eval
and false
value.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
sourceMap: true,
},
},
],
},
};
esModule
Type:
type esModule = boolean;
Default: true
By default, css-loader
generates JS modules that use the ES modules syntax.
There are some cases in which using ES modules is beneficial, like in the case of module concatenation and tree shaking.
You can enable a CommonJS modules syntax using:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
esModule: false,
},
},
],
},
};
exportType
Type:
type exportType = "array" | "string" | "css-style-sheet";
Default: 'array'
Allows exporting styles as array with modules, string or constructable stylesheet (i.e. CSSStyleSheet
).
Default value is 'array'
, i.e. loader exports array of modules with specific API which is used in style-loader
or other.
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'
The default export is array of modules with specific API which is used in style-loader
or other.
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'
[!WARNING]
You should not use
style-loader
ormini-css-extract-plugin
with this value.
[!WARNING]
The
esModule
option should be enabled if you want to use it withCSS modules
, by default for locals will be used named export.
The default export is 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'
[!WARNING]
@import
rules not yet allowed, more information
[!WARNING]
You don't need
style-loader
anymore, please remove it.
[!WARNING]
The
esModule
option should be enabled if you want to use it withCSS modules
, by default for locals will be used named export.
[!WARNING]
Source maps are not currently supported in
Chrome
due bug
The default export is a constructable stylesheet (i.e. CSSStyleSheet
).
Useful for custom elements and shadow DOM.
More information:
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];
For migration purposes, you can use the following configuration:
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
},
},
],
},
],
},
],
},
};
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, because it creates separate css files.
For development
mode (including webpack-dev-server
) you can use style-loader, because it injects CSS into the DOM using multiple <style></style>
and works faster.
[!NOTE]
Do not use
style-loader
andmini-css-extract-plugin
together.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";
module.exports = {
module: {
rules: [
{
// If you enable `experiments.css` or `experiments.futureDefaults`, please uncomment line below
// type: "javascript/auto",
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 */
commentWith the help of the /* webpackIgnore: true */
comment, it is possible to disable sources handling for rules and for individual declarations.
/* webpackIgnore: true */
@import url(./basic.css);
@import /* webpackIgnore: true */ url(./imported.css);
.class {
/* Disabled url handling for the all urls in the 'background' declaration */
color: red;
/* webpackIgnore: true */
background: url("./url/img.png"), url("./url/img.png");
}
.class {
/* Disabled url handling for the first url in the 'background' declaration */
color: red;
background:
/* webpackIgnore: true */ url("./url/img.png"), url("./url/img.png");
}
.class {
/* Disabled url handling for the second url in the 'background' declaration */
color: red;
background:
url("./url/img.png"),
/* webpackIgnore: true */ url("./url/img.png");
}
/* prettier-ignore */
.class {
/* Disabled url handling for the second url in the 'background' declaration */
color: red;
background: url("./url/img.png"),
/* webpackIgnore: true */
url("./url/img.png");
}
/* prettier-ignore */
.class {
/* Disabled url handling for third and sixth urls in the 'background-image' declaration */
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
);
}
The following webpack.config.js
can load CSS files, embed small PNG/JPG/GIF/SVG images as well as fonts as Data URLs and copy larger files to the output directory.
For 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,
// More information here 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
When you have pure CSS (without CSS modules), CSS modules and PostCSS in your project you can use this setup:
webpack.config.js
module.exports = {
module: {
rules: [
{
// For pure CSS - /\.css$/i,
// For Sass/SCSS - /\.((c|sa|sc)ss)$/i,
// For Less - /\.((c|le)ss)$/i,
test: /\.((c|sa|sc)ss)$/i,
use: [
"style-loader",
{
loader: "css-loader",
options: {
// Run `postcss-loader` on each CSS `@import` and CSS modules/ICSS imports, do not forget that `sass-loader` compile non CSS `@import`'s into a single file
// If you need run `sass-loader` and `postcss-loader` on each CSS `@import` please set it to `2`
importLoaders: 1,
},
},
{
loader: "postcss-loader",
options: { plugins: () => [postcssPresetEnv({ stage: 0 })] },
},
// Can be `less-loader`
{
loader: "sass-loader",
},
],
},
// For 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, "_");
},
},
},
},
],
},
};
Interoperable CSS
-only and CSS Module
featuresThe following setup is an example of allowing Interoperable CSS
features only (such as :import
and :export
) without using further CSS Module
functionality by setting mode
option for all files that do not match *.module.scss
naming convention. This is for reference as having ICSS
features applied to all files was default css-loader
behavior before v4.
Meanwhile all files matching *.module.scss
are treated as CSS Modules
in this example.
An example case is assumed where a project requires canvas drawing variables to be synchronized with CSS - canvas drawing uses the same color (set by color name in JavaScript) as HTML background (set by class name in CSS).
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
File treated as ICSS
-only.
$colorBackground: red;
:export {
colorBackgroundCanvas: $colorBackground;
}
Component.module.scss
File treated as CSS Module
.
@import "variables.scss";
.componentClass {
background-color: $colorBackground;
}
Component.jsx
Using both CSS Module
functionality as well as SCSS variables directly in JavaScript.
import * as svars from "variables.scss";
import * as 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}`;
Please take a moment to read our contributing guidelines if you haven't yet done so.
Allow to setup exports module.exports
/export
for source files.
Useful when a source file does not contain exports or something does not export.
For further hints on compatibility issues, check out Shimming of the official docs.
[!WARNING]
By default loader generate ES module named syntax.
[!WARNING]
Be careful, existing exports (
export
/module.exports
/exports
) in the original code and exporting new values can cause a failure.
To begin, you'll need to install exports-loader
:
npm install exports-loader --save-dev
or
yarn add -D exports-loader
or
pnpm add -D exports-loader
The |
or %20
(space) allow to separate the syntax
, name
and alias
of export.
The documentation and syntax examples can be read here.
[!WARNING]
%20
is space in a query string, because you can't use spaces in URLs
Then add the loader to the desired import
statement or require
calls. For example:
import { myFunction } from "exports-loader?exports=myFunction!./file.js";
// Adds the following code to the file's source:
//
// ...
// Code
// ...
//
// export { myFunction }
myFunction("Hello world");
import {
myVariable,
myFunction,
} from "exports-loader?exports=myVariable,myFunction!./file.js";
// Adds the following code to the file's source:
//
// ...
// Code
// ...
//
// export { myVariable, myFunction };
const newVariable = myVariable + "!!!";
console.log(newVariable);
myFunction("Hello world");
const {
myFunction,
} = require("exports-loader?type=commonjs&exports=myFunction!./file.js");
// Adds the following code to the file's source:
//
// ...
// Code
// ...
//
// module.exports = { myFunction }
myFunction("Hello world");
// Alternative syntax:
// import myFunction from 'exports-loader?exports=default%20myFunction!./file.js';
import myFunction from "exports-loader?exports=default|myFunction!./file.js";
// `%20` is space in a query string, equivalently `default myFunction`
// Adds the following code to the file's source:
//
// ...
// Code
// ...
//
// exports default myFunction;
myFunction("Hello world");
const myFunction = require("exports-loader?type=commonjs&exports=single|myFunction!./file.js");
// `|` is separator in a query string, equivalently `single|myFunction`
// Adds the following code to the file's source:
//
// ...
// Code
// ...
//
// module.exports = myFunction;
myFunction("Hello world");
import { myFunctionAlias } from "exports-loader?exports=named|myFunction|myFunctionAlias!./file.js";
// `|` is separator in a query string, equivalently `named|myFunction|myFunctionAlias`
// Adds the following code to the file's source:
//
// ...
// Code
// ...
//
// exports { myFunction as myFunctionAlias };
myFunctionAlias("Hello world");
Description of string values can be found in the documentation below.
webpack.config.js
module.exports = {
module: {
rules: [
{
// You can use `regexp`
// test: /vendor\.js/$
test: require.resolve("./path/to/vendor.js"),
loader: "exports-loader",
options: {
exports: "myFunction",
},
},
],
},
};
And run webpack
via your preferred method.
Name | Type | Default | Description |
---|---|---|---|
type | {String} | module | Format of generated exports |
exports | {String|Object|Array<String|Object>} | undefined | List of exports |
type
Type: String
Default: module
Format of generated exports.
Possible values - commonjs
(CommonJS module syntax) and module
(ES module syntax).
commonjs
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve("./path/to/vendor.js"),
loader: "exports-loader",
options: {
type: "commonjs",
exports: "Foo",
},
},
],
},
};
Generate output:
// ...
// 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",
},
},
],
},
};
Generate output:
// ...
// Code
// ...
export { Foo };
exports
Type: String|Array
Default: undefined
List of exports.
String
Allows to use a string to describe an export.
Syntax
The |
or %20
(space) allow to separate the syntax
, name
and alias
of export.
String syntax - [[syntax] [name] [alias]]
or [[syntax]|[name]|[alias]]
, where:
[syntax]
(may be omitted) -
type
is module
- can be default
and named
,type
is commonjs
- can be single
and multiple
[name]
- name of an exported value (required)
[alias]
- alias of an exported value (may be omitted)
Examples:
[Foo]
- generates export { Foo };
.[default Foo]
- generates export default Foo;
.[named Foo]
- generates export { Foo };
.[named Foo FooA]
- generates export { Foo as FooA };
.[single Foo]
- generates module.exports = Foo;
.[multiple Foo]
- generates module.exports = { Foo };
.[multiple Foo FooA]
- generates module.exports = { 'FooA': Foo };
.[named [name] [name]Alias]
- generates ES module named exports and exports a value equal to the filename under other name., for single.js
it will be single
and singleAlias
, generates export { single as singleAlias };
.[!WARNING]
You need to set
type: "commonjs"
to usesingle
ormultiple
syntaxes.
[!WARNING]
Aliases can't be used together with
default
orsingle
syntaxes.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve("./path/to/vendor.js"),
loader: "exports-loader",
options: {
exports: "default Foo",
},
},
],
},
};
Generate output:
// ...
// 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",
},
},
],
},
};
Generate output:
// ...
// 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",
},
},
],
},
};
Generate output:
// ...
// 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",
},
},
],
},
};
Generate output:
// ...
// Code
// ...
module.exports = { FooA: Foo };
Object
Allows to use an object to describe an export.
Properties:
syntax
- can be default
or named
for the module
type (ES modules
module format), and single
or multiple
for the commonjs
type (CommonJS
module format) (may be omitted)name
- name of an exported value (required)alias
- alias of an exported value (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",
},
},
},
],
},
};
Generate output:
// ...
// 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",
},
},
},
],
},
};
Generate output:
// ...
// 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",
},
},
},
],
},
};
Generate output:
// ...
// 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",
},
},
},
],
},
};
Generate output:
// ...
// Code
// ...
module.exports = { FooA: Foo };
Array
Allow to specify multiple exports. Each item can be a string
or an object
.
[!WARNING]
Not possible to use
single
andmultiple
syntaxes together due to CommonJS format limitations.
[!WARNING]
Not possible to use multiple
default
values due to ES module format limitations.
[!WARNING]
Not possible to use multiple
single
values due to CommonJS format limitations.
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"],
},
},
],
},
};
Generate output:
// ...
// 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"],
},
},
],
},
};
Generate output:
// ...
// 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",
],
},
},
],
},
};
Generate output:
// ...
// Code
// ...
export { Foo as FooA, Bar, Baz };
Please take a moment to read our contributing guidelines if you haven't yet done so.
The expose-loader
loader allows to expose a module (in whole or in part) to global object (self
, window
and global
).
For further hints on compatibility issues, check out Shimming of the official docs.
To begin, you'll need to install expose-loader
:
npm install expose-loader --save-dev
or
yarn add -D expose-loader
or
pnpm add -D expose-loader
(If you're using WebPack 4, install expose-loader@1
and follow the corresponding instructions instead.)
Then you can use the expose-loader
using two approaches.
The |
or %20
(space) allow to separate the globalName
, moduleLocalName
and override
of expose.
The documentation and syntax examples can be read here.
[!WARNING]
%20
is space in a query string, because you can't use spaces in URLs
import $ from "expose-loader?exposes=$,jQuery!jquery";
//
// Adds the `jquery` to the global object under the names `$` and `jQuery`
import { concat } from "expose-loader?exposes=_.concat!lodash/concat";
//
// Adds the `lodash/concat` to the global object under the name `_.concat`
import {
map,
reduce,
} from "expose-loader?exposes=_.map|map,_.reduce|reduce!underscore";
//
// Adds the `map` and `reduce` method from `underscore` to the global object under the name `_.map` and `_.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",
},
],
},
},
],
},
};
The require.resolve
call is a Node.js function (unrelated to require.resolve
in webpack processing).
require.resolve
gives you the absolute path to the module ("/.../app/node_modules/jquery/dist/jquery.js"
).
So the expose only applies to the jquery
module. And it's only exposed when used in the bundle.
And run webpack
via your preferred method.
Name | Type | Default | Description |
---|---|---|---|
exposes | {String|Object|Array<String|Object>} | undefined | List of exposes |
globalObject | String | undefined | Object used for global context |
exposes
Type:
type exposes =
| string
| {
globalName: string | Array<string>;
moduleLocalName?: string;
override?: boolean;
}
| Array<
| string
| {
globalName: string | Array<string>;
moduleLocalName?: string;
override?: boolean;
}
>;
Default: undefined
List of exposes.
string
Allows to use a string to describe an expose.
syntax
The |
or %20
(space) allow to separate the globalName
, moduleLocalName
and override
of expose.
String syntax - [[globalName] [moduleLocalName] [override]]
or [[globalName]|[moduleLocalName]|[override]]
, where:
globalName
- the name in the global object, for example window.$
for a browser environment (required)moduleLocalName
- the name of method/variable/etc of the module (the module must export it) (may be omitted)override
- allows to override existing value in the global object (may be omitted)If moduleLocalName
is not specified, it exposes the entire module to the global object, otherwise it exposes only the value of moduleLocalName
.
src/index.js
import $ from "jquery";
import _ from "underscore";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve("jquery"),
loader: "expose-loader",
options: {
// For `underscore` library, it can be `_.map map` or `_.map|map`
exposes: "$",
// To access please use `window.$` or `globalThis.$`
},
},
{
// test: require.resolve("jquery"),
test: /node_modules[/\\]underscore[/\\]modules[/\\]index-all\.js$/,
loader: "expose-loader",
type: "javascript/auto",
options: {
// For `underscore` library, it can be `_.map map` or `_.map|map`
exposes: "_",
// To access please use `window._` or `globalThis._`
},
},
],
},
};
object
Allows to use an object to describe an expose.
globalName
Type:
type globalName = string | Array<string>;
Default: undefined
The name in the global object. (required).
src/index.js
import _ from "underscore";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /node_modules[/\\]underscore[/\\]modules[/\\]index-all\.js$/,
loader: "expose-loader",
type: "javascript/auto",
options: {
exposes: {
// Can be `['_', 'filter']`
globalName: "_.filter",
moduleLocalName: "filter",
},
},
},
],
},
};
moduleLocalName
Type:
type moduleLocalName = string;
Default: undefined
The name of method/variable/etc of the module (the module must export it).
If moduleLocalName
is specified, it exposes only the value of moduleLocalName
.
src/index.js
import _ from "underscore";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /node_modules[/\\]underscore[/\\]modules[/\\]index-all\.js$/,
loader: "expose-loader",
type: "javascript/auto",
options: {
exposes: {
globalName: "_.filter",
moduleLocalName: "filter",
},
},
},
],
},
};
override
Type:
type override = boolean;
Default: false
By default, loader does not override the existing value in the global object, because it is unsafe.
In development
mode, we throw an error if the value already present in the global object.
But you can configure loader to override the existing value in the global object using this option.
To force override the value that is already present in the global object you can set the override
option to the true
value.
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: /node_modules[/\\]underscore[/\\]modules[/\\]index-all\.js$/,
loader: "expose-loader",
type: "javascript/auto",
options: {
exposes: [
"_.map map",
{
globalName: "_.filter",
moduleLocalName: "filter",
},
{
globalName: ["_", "find"],
moduleLocalName: "myNameForFind",
},
],
},
},
],
},
};
It will expose only map
, filter
and find
(under myNameForFind
name) methods to the global object.
In a browser these methods will be available under windows._.map(..args)
, windows._.filter(...args)
and windows._.myNameForFind(...args)
methods.
globalObject
type globalObject = string;
Default: undefined
Object used for global context
import _ from "underscore";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /node_modules[/\\]underscore[/\\]modules[/\\]index-all\.js$/,
loader: "expose-loader",
type: "javascript/auto",
options: {
exposes: [
{
globalName: "_",
},
],
globalObject: "this",
},
},
],
},
};
index.js
import { method1 } from "./my-module.js";
my-module.js
function method1() {
console.log("method1");
}
function method2() {
console.log("method1");
}
export { method1, method2 };
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /my-module\.js$/,
loader: "expose-loader",
options: {
exposes: "mod",
// // To access please use `window.mod` or `globalThis.mod`
},
},
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
Exports HTML as string. HTML is minimized when the compiler demands.
To begin, you'll need to install html-loader
:
npm install --save-dev html-loader
or
yarn add -D html-loader
or
pnpm add -D html-loader
Then add the plugin to your webpack
config. For example:
file.js
import html from "./file.html";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: "html-loader",
},
],
},
};
sources
Type:
type sources =
| boolean
| {
list?: Array<{
tag?: string;
attribute?: string;
type?: string;
filter?: (
tag: string,
attribute: string,
attributes: string,
resourcePath: string,
) => boolean;
}>;
urlFilter?: (
attribute: string,
value: string,
resourcePath: string,
) => boolean;
scriptingEnabled?: boolean;
};
Default: true
By default every loadable attribute (for example - <img src="image.png"/>
) is imported (const img = require('./image.png')
or new URL("./image.png", import.meta.url)
).
You may need to specify loaders for images in your configuration (recommended asset modules
).
Supported tags and attributes:
src
attribute of the audio
tagsrc
attribute of the embed
tagsrc
attribute of the img
tagsrcset
attribute of the img
tagsrc
attribute of the input
tagdata
attribute of the object
tagsrc
attribute of the script
taghref
attribute of the script
tagxlink:href
attribute of the script
tagsrc
attribute of the source
tagsrcset
attribute of the source
tagsrc
attribute of the track
tagposter
attribute of the video
tagsrc
attribute of the video
tagxlink:href
attribute of the image
taghref
attribute of the image
tagxlink:href
attribute of the use
taghref
attribute of the use
taghref
attribute of the link
tag when the rel
attribute contains stylesheet
, icon
, shortcut icon
, mask-icon
, apple-touch-icon
, apple-touch-icon-precomposed
, apple-touch-startup-image
, manifest
, prefetch
, preload
or when the itemprop
attribute is image
, logo
, screenshot
, thumbnailurl
, contenturl
, downloadurl
, duringmedia
, embedurl
, installurl
, layoutimage
imagesrcset
attribute of the link
tag when the rel
attribute contains stylesheet
, icon
, shortcut icon
, mask-icon
, apple-touch-icon
, apple-touch-icon-precomposed
, apple-touch-startup-image
, manifest
, prefetch
, preload
content
attribute of the meta
tag when the name
attribute is msapplication-tileimage
, msapplication-square70x70logo
, msapplication-square150x150logo
, msapplication-wide310x150logo
, msapplication-square310x310logo
, msapplication-config
, twitter:image
or when the property
attribute is og:image
, og:image:url
, og:image:secure_url
, og:audio
, og:audio:secure_url
, og:video
, og:video:secure_url
, vk:image
or when the itemprop
attribute is image
, logo
, screenshot
, thumbnailurl
, contenturl
, downloadurl
, duringmedia
, embedurl
, installurl
, layoutimage
icon-uri
value component in content
attribute of the meta
tag when the name
attribute is msapplication-task
boolean
The true
value enables the processing of all default elements and attributes, the false
value disables the processing of all attributes.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: "html-loader",
options: {
// Disables attributes processing
sources: false,
},
},
],
},
};
object
Allows you to specify which tags and attributes to process, filter them, filter urls and process sources starting with /
.
For example:
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) => {
// 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;
},
},
},
},
],
},
};
list
Type:
type list = Array<{
tag?: string;
attribute?: string;
type?: string;
filter?: (
tag: string,
attribute: string,
attributes: string,
resourcePath: string,
) => boolean;
}>;
Default: supported tags and attributes.
Allows to setup which tags and attributes to process and how, as well as the ability to filter some of them.
Using ...
syntax allows you to extend default supported tags and attributes.
For example:
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;
},
},
],
},
},
},
],
},
};
If the tag name is not specified it will process all the tags.
You can use your custom filter to specify html elements to be processed.
For example:
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 can also be used to extend the supported elements and attributes.
For example, filter can help process meta tags that reference assets:
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;
},
},
],
},
},
},
],
},
};
[!NOTE]
source with a
tag
option takes precedence over source without.
Filter can be used to disable default sources.
For example:
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: "html-loader",
options: {
sources: {
list: [
"...",
{
tag: "img",
attribute: "src",
type: "src",
filter: () => false,
},
],
},
},
},
],
},
};
urlFilter
Type:
type urlFilter = (
attribute: string,
value: string,
resourcePath: string,
) => boolean;
Default: undefined
Allow to filter urls. All filtered urls will not be resolved (left in the code as they were written).
Non-requestable sources (for example <img src="javascript:void(0)"/>
) are not handled by default.
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;
},
},
},
},
],
},
};
scriptingEnabled
Type:
type scriptingEnabled = boolean;
Default: true
By default, the parser in html-loader
interprets content inside <noscript>
tags as #text
, so processing of content inside this tag will be ignored.
In order to enable processing inside <noscript>
for content recognition by the parser as #AST
, set this parameter to: false
Additional information: scriptingEnabled
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: "html-loader",
options: {
sources: {
// Enables processing inside the <noscript> tag
scriptingEnabled: false,
},
},
},
],
},
};
preprocessor
Type:
type preprocessor = (content: string, loaderContext: LoaderContext) => string;
Default: undefined
Allows pre-processing of content before handling.
[!WARNING]
You should always return valid HTML
file.hbs
<div>
<p>{{firstname}} {{lastname}}</p>
<img src="image.png" alt="alt" />
<div>
function
You can set the preprocessor
option as a function
instance.
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;
},
},
},
],
},
};
You can also set the preprocessor
option as an asynchronous function instance.
For example:
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;
},
},
},
],
},
};
postprocessor
Type:
type postprocessor = (content: string, loaderContext: LoaderContext) => string;
Default: undefined
Allows post-processing of content after replacing all attributes (like src
/srcset
/etc).
file.html
<img src="image.png" />
<img src="<%= 'Hello ' + (1+1) %/>" />
<img src="<%= require('./image.png') %>" />
<img src="<%= new URL('./image.png', import.meta.url) %>" />
<div><%= require('./gallery.html').default %></div>
function
You can set the postprocessor
option as a function
instance.
webpack.config.js
const Handlebars = require("handlebars");
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: "html-loader",
options: {
postprocessor: (content, loaderContext) => {
// When you environment supports template literals (using browserslist or options) we will generate code using them
const isTemplateLiteralSupported = content[0] === "`";
return content
.replace(/<%=/g, isTemplateLiteralSupported ? `\${` : '" +')
.replace(/%>/g, isTemplateLiteralSupported ? "}" : '+ "');
},
},
},
],
},
};
You can also set the postprocessor
option as an asynchronous function instance.
For example:
webpack.config.js
const Handlebars = require("handlebars");
module.exports = {
module: {
rules: [
{
test: /\.hbs$/i,
loader: "html-loader",
options: {
postprocessor: async (content, loaderContext) => {
const value = await getValue();
// When you environment supports template literals (using browserslist or options) we will generate code using them
const isTemplateLiteralSupported = content[0] === "`";
return content
.replace(/<%=/g, isTemplateLiteralSupported ? `\${` : '" +')
.replace(/%>/g, isTemplateLiteralSupported ? "}" : '+ "')
.replace("my-value", value);
},
},
},
],
},
};
minimize
Type:
type minimize =
| boolean
| {
caseSensitive?: boolean;
collapseWhitespace?: boolean;
conservativeCollapse?: boolean;
keepClosingSlash?: boolean;
minifyCSS?: boolean;
minifyJS?: boolean;
removeComments?: boolean;
removeRedundantAttributes?: boolean;
removeScriptTypeAttributes?: boolean;
removeStyleLinkTypeAttributes?: boolean;
};
Default: true
in production mode, otherwise false
Tell html-loader
to minimize HTML.
boolean
The enabled rules for minimizing by default are the following ones:
({
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
See html-minifier-terser's documentation for more information on the available options.
The default rules can be overridden using the following options in your webpack.conf.js
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: "html-loader",
options: {
minimize: {
removeComments: false,
collapseWhitespace: false,
},
},
},
],
},
};
The default rules can be extended:
webpack.config.js
const { defaultMinimizerOptions } = require("html-loader");
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: "html-loader",
options: {
minimize: {
...defaultMinimizerOptions,
removeComments: false,
collapseWhitespace: false,
},
},
},
],
},
};
esModule
Type:
type esModule = boolean;
Default: true
By default, html-loader
generates JS modules that use the ES modules syntax.
There are some cases in which using ES modules is beneficial, such as module concatenation and tree shaking.
You can enable a CommonJS modules syntax using:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: "html-loader",
options: {
esModule: false,
},
},
],
},
};
<!-- webpackIgnore: true -->
commentWith <!-- webpackIgnore: true -->
comment, one can disable sources handling for next tag.
<!-- Disabled url handling for the src attribute -->
<!-- webpackIgnore: true -->
<img src="image.png" />
<!-- Disabled url handling for the src and srcset attributes -->
<!-- webpackIgnore: true -->
<img
srcset="image.png 480w, image.png 768w"
src="image.png"
alt="Elva dressed as a fairy"
/>
<!-- Disabled url handling for the content attribute -->
<!-- webpackIgnore: true -->
<meta itemprop="image" content="./image.png" />
<!-- Disabled url handling for the href attribute -->
<!-- webpackIgnore: true -->
<link rel="icon" type="image/png" sizes="192x192" href="./image.png" />
With resolve.roots
one can specify a list of directories where requests of server-relative URLs (starting with '/') are resolved.
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
and link
tagsscript.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: ["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",
},
],
},
};
You can use any template system. Below is an example for 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;
},
},
},
],
},
};
You can use PostHTML without any additional loaders.
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;
},
},
},
],
},
};
A very common scenario is exporting the HTML into their own .html file, to serve them directly instead of injecting with javascript.
This can be achieved with a combination of html-loader and asset modules
.
The html-loader will parse the URLs, require the images and everything you
expect. The extract loader will parse the javascript back into a proper html
file, ensuring images are required and point to proper path, and the asset modules
will write the .html file for you. Example:
webpack.config.js
module.exports = {
output: {
assetModuleFilename: "[name][ext]",
},
module: {
rules: [
{
test: /\.html$/,
type: "asset/resource",
generator: {
filename: "[name][ext]",
},
},
{
test: /\.html$/i,
use: ["html-loader"],
},
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
The imports loader allows you to use modules that depend on specific global variables.
This is useful for third-party modules that rely on global variables like $
or this
being the window
object.
The imports loader can add the necessary require('whatever')
calls, so those modules work with webpack.
For further hints on compatibility issues, check out Shimming of the official docs.
[!WARNING]
By default loader generate ES module named syntax.
[!WARNING]
Be careful, existing imports (
import
/require
) in the original code and importing new values can cause failure.
To begin, you'll need to install imports-loader
:
npm install imports-loader --save-dev
or
yarn add -D imports-loader
or
pnpm add -D imports-loader
Given you have this file:
example.js
$("img").doSomeAwesomeJqueryPluginStuff();
Then you can inject the jquery
value into the module by configuring the imports-loader
using two approaches.
The |
or %20
(space) allow to separate the syntax
, moduleName
, name
and alias
of import.
The documentation and syntax examples can be read here.
[!WARNING]
%20
is space in a query string, because you can't use spaces in URLs
// Alternative syntax:
//
// import myLib from 'imports-loader?imports=default%20jquery%20$!./example.js';
//
// `%20` is space in a query string, equivalently `default jquery $`
import myLib from "imports-loader?imports=default|jquery|$!./example.js";
// Adds the following code to the beginning of example.js:
//
// import $ from "jquery";
//
// ...
// Code
// ...
import myLib from "imports-loader?imports=default|jquery|$,angular!./example.js";
// `|` is separator in a query string, equivalently `default|jquery|$` and `angular`
// Adds the following code to the beginning of example.js:
//
// import $ from "jquery";
// import angular from "angular";
//
// ...
// Code
// ...
import myLib from "imports-loader?imports=named|library|myMethod,angular!./example.js";
// `|` is separator in a query string, equivalently `named|library|myMethod` and `angular`
// Adds the following code to the beginning of example.js:
//
// import { myMethod } from "library";
// import angular from "angular";
//
// ...
// Code
// ...
const myLib = require(
`imports-loader?type=commonjs&imports=single|jquery|$,angular!./example.js`,
);
// `|` is separator in a query string, equivalently `single|jquery|$` and `angular`
// Adds the following code to the beginning of 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`,
);
// `|` is separator in a query string, equivalently `single|myLib|myMethod` and `angular`
// Adds the following code to the example.js:
//
// const myMethod = require('myLib');
//
// (function () {
// ...
// Code
// ...
// }.call(window));
import myLib from "imports-loader?additionalCode=var%20myVariable%20=%20false;!./example.js";
// Adds the following code to the beginning of example.js:
//
// var myVariable = false;
//
// ...
// Code
// ...
webpack.config.js
module.exports = {
module: {
rules: [
{
// You can use `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",
},
],
},
},
],
},
],
},
};
Generate output:
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";
And run webpack
via your preferred method.
type
Type:
type type = string;
Default: module
Format of generated exports.
Possible values - commonjs
(CommonJS module syntax) and module
(ES module syntax).
commonjs
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve("example.js"),
loader: "imports-loader",
options: {
syntax: "default",
type: "commonjs",
imports: "Foo",
},
},
],
},
};
Generate output:
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",
},
},
],
},
};
Generate output:
import Foo from "Foo";
// ...
// Code
// ...
imports
Type:
type imports =
| string
| {
syntax:
| "default"
| "named"
| "namespace"
| "side-effects"
| "single"
| "multiple"
| "pure";
moduleName: string;
name: string;
alias: string;
}
| Array<
| string
| {
syntax:
| "default"
| "named"
| "namespace"
| "side-effects"
| "single"
| "multiple"
| "pure";
moduleName: string;
name: string;
alias: string;
}
>;
Default: undefined
List of imports.
string
Allows to use a string to describe an export.
Syntax
The |
or %20
(space) allow to separate the syntax
, moduleName
, name
and alias
of import.
String syntax - [[syntax] [moduleName] [name] [alias]]
or [[syntax]|[moduleName]|[name]|[alias]]
, where:
[syntax]
(may be omitted):
type
is module
- can be default
, named
, namespace
or side-effects
, the default value is default
.type
is commonjs
- can be single
, multiple
or pure
, the default value is single
.[moduleName]
- name of an imported module (required)
[name]
- name of an imported value (required)
[alias]
- alias of an imported value (may be omitted)
Examples:
If type module
:
[Foo]
- generates import Foo from "Foo";
.[default Foo]
- generates import Foo from "Foo";
.[default ./my-lib Foo]
- generates import Foo from "./my-lib";
.[named Foo FooA]
- generates import { FooA } from "Foo";
.[named Foo FooA Bar]
- generates import { FooA as Bar } from "Foo";
.[namespace Foo FooA]
- generates import * as FooA from "Foo";
.[side-effects Foo]
- generates import "Foo";
.If type commonjs
:
[Foo]
- generates const Foo = require("Foo");
.[single Foo]
- generates const Foo = require("Foo");
.[single ./my-lib Foo]
- generates const Foo = require("./my-lib");
.[multiple Foo FooA Bar]
- generates const { FooA: Bar } = require("Foo");
.[pure Foo]
- generates require("Foo");
.[!WARNING]
You need to set
type: "commonjs"
to usesingle
,multiple
andpure
syntaxes.
[!WARNING]
Aliases can't be used together with
default
,namespace
,side-effects
,single
andpure
syntaxes.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve("./path/to/example.js"),
loader: "imports-loader",
options: {
imports: "default lib myName",
},
},
],
},
};
Generate output:
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",
},
},
],
},
};
Generate output:
var myName = require("lib");
// ...
// Code
// ...
object
Allows to use an object to describe an import.
Properties:
syntax
:
type
is module
- can be default
, named
, namespace
or side-effects
type
is commonjs
- can be single
, multiple
or pure
moduleName
- name of an imported module (required)
name
- name of an imported value (required)
alias
- alias of an imported value (may be omitted)
[!WARNING]
Alias can't be used together with
default
,namespace
,side-effects
,single
andpure
syntaxes.
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",
},
},
},
],
},
],
},
};
Generate output:
import { lib2_method_2 as lib_2_method_2_alias } from "lib_2";
// ...
// Code
// ...
array
Allow to specify multiple imports.
Each item can be a string
or an 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",
],
},
},
],
},
],
},
};
Generate output:
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
Type:
type wrapper =
| boolean
| string
| {
thisArg: string;
args: Record<string, string> | Array<string>;
};
Default: undefined
Closes the module code in a function with a given thisArg
and args
((function () { ... }).call();
).
[!WARNING]
Do not use this option if source code contains ES module import(s)
boolean
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve("example.js"),
use: [
{
loader: "imports-loader",
options: {
imports: {
moduleName: "jquery",
name: "$",
},
wrapper: true,
},
},
],
},
],
},
};
Generate output:
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",
},
},
],
},
],
},
};
Generate output:
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"],
},
},
},
],
},
],
},
};
Generate output:
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",
},
},
},
},
],
},
],
},
};
Generate output:
import $ from "jquery";
(function (var1, var2) {
// ...
// Code
// ...
}).call(window, myVariable, myOtherVariable);
additionalCode
Type:
type additionalCode = string;
Default: undefined
Adds custom code as a preamble before the module's code.
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;",
},
},
],
},
],
},
};
Generate output:
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 */",
},
},
],
},
],
},
};
Generate output:
import $ from "jquery";
var define = false; /* Disable AMD for misbehaving libraries */
// ...
// Code
// ...
Please take a moment to read our contributing guidelines if you haven't yet done so.
A Less loader for webpack. Compiles Less to CSS.
To begin, you'll need to install less
and less-loader
:
npm install less less-loader --save-dev
or
yarn add -D less less-loader
or
pnpm add -D less less-loader
Then add the loader to your webpack
config. For example:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
// compiles Less to CSS
"style-loader",
"css-loader",
"less-loader",
],
},
],
},
};
And run webpack
via your preferred method.
lessOptions
Type:
type lessOptions = import('less').options | ((loaderContext: LoaderContext) => import('less').options})
Default: { relativeUrls: true }
You can pass any Less specific options to the less-loader
through the lessOptions
property in the loader options. See the Less documentation for all available options in dash-case. Since we're passing these options to Less programmatically, you need to pass them in camelCase here:
object
Use an object to pass options through to 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
Allows setting the options passed through to Less based off of the loader context.
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
lessOptions: (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 {
paths: ["absolute/path/c", "absolute/path/d"],
};
}
return {
paths: ["absolute/path/a", "absolute/path/b"],
};
},
},
},
],
},
],
},
};
additionalData
Type:
type additionalData =
| string
| ((content: string, loaderContext: LoaderContext) => string);
Default: undefined
Prepends/Appends Less
code to the actual entry file.
In this case, the less-loader
will not override the source but just prepend the entry's content.
This is especially useful when some of your Less variables depend on the environment:
Since you're injecting code, this will break the source mappings in your entry file. Often there's a simpler solution than this, like multiple Less entry files.
string
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
additionalData: `@env: ${process.env.NODE_ENV};`,
},
},
],
},
],
},
};
function
Sync
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
additionalData: (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;
},
},
},
],
},
],
},
};
Async
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
Type:
type sourceMap = boolean;
Default: depends on the compiler.devtool
value
By default generation of source maps depends on the devtool
option. All values enable source map generation except eval
and false
value.
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
Type:
type webpackImporter = boolean;
Default: true
Enables/Disables the default webpack
importer.
This can improve performance in some cases. Use it with caution because aliases and @import
from node_modules
will not work.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
webpackImporter: false,
},
},
],
},
],
},
};
implementation
Type:
type implementation = object | string;
less-loader compatible with Less 3 and 4 versions
The special implementation
option determines which implementation of Less to use. Overrides the locally installed peerDependency
version of less
.
This option is only really useful for downstream tooling authors to ease the Less 3-to-4 transition.
object
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
implementation: require("less"),
},
},
],
},
],
},
};
string
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
implementation: require.resolve("less"),
},
},
],
},
],
},
};
lessLogAsWarnOrErr
Type:
type lessLogAsWarnOrErr = boolean;
Default: false
Less
warnings and errors will be webpack warnings and errors, not just logs.
warning.less
div {
&:extend(.body1);
}
If lessLogAsWarnOrErr
is set to false
it will be just a log and webpack will compile successfully, but if you set this option to true
webpack will compile fail with a warning.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
lessLogAsWarnOrErr: true,
},
},
],
},
],
},
};
Chain the less-loader
with the css-loader
and the style-loader
to immediately apply all styles to the DOM.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
{
loader: "style-loader", // creates style nodes from JS strings
},
{
loader: "css-loader", // translates CSS into CommonJS
},
{
loader: "less-loader", // compiles Less to CSS
},
],
},
],
},
};
Unfortunately, Less doesn't map all options 1-by-1 to camelCase. When in doubt, check their executable and search for the dash-case option.
To enable sourcemaps for CSS, you'll need to pass the sourceMap
property in the loader's options. If this is not passed, the loader will respect the setting for webpack source maps, set in devtool
.
webpack.config.js
module.exports = {
devtool: "source-map", // any "source-map"-like devtool is possible
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
{
loader: "css-loader",
options: {
sourceMap: true,
},
},
{
loader: "less-loader",
options: {
sourceMap: true,
},
},
],
},
],
},
};
If you want to edit the original Less files inside Chrome, there's a good blog post. The blog post is about Sass but it also works for Less.
Usually, it's recommended to extract the style sheets into a dedicated file in production using the MiniCssExtractPlugin. This way your styles are not dependent on JavaScript.
First we try to use built-in less
resolve logic, then webpack
resolve logic.
webpack
provides an advanced mechanism to resolve files.
less-loader
applies a Less plugin that passes all queries to the webpack resolver if less
could not resolve @import
.
Thus you can import your Less modules from node_modules
.
@import "bootstrap/less/bootstrap";
Using ~
is deprecated and can be removed from your code (we recommend it), but we still support it for historical reasons.
Why you can removed it? The loader will first try to resolve @import
as relative, if it cannot be resolved, the loader will try to resolve @import
inside node_modules
.
Default resolver options can be modified by resolve.byDependency
:
webpack.config.js
module.exports = {
devtool: "source-map", // any "source-map"-like devtool is possible
module: {
rules: [
{
test: /\.less$/i,
use: ["style-loader", "css-loader", "less-loader"],
},
],
},
resolve: {
byDependency: {
// More options can be found here https://webpack.js.org/configuration/resolve/
less: {
mainFiles: ["custom"],
},
},
},
};
If you specify the paths
option, modules will be searched in the given paths
. This is less
default behavior. paths
should be an array with absolute 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")],
},
},
},
],
},
],
},
};
In order to use plugins, simply set the plugins
option like this:
webpack.config.js
const CleanCSSPlugin = require('less-plugin-clean-css');
module.exports = {
...
{
loader: 'less-loader',
options: {
lessOptions: {
plugins: [
new CleanCSSPlugin({ advanced: true }),
],
},
},
},
...
};
[!NOTE]
Access to the loader context inside the custom plugin can be done using the
pluginManager.webpackLoaderContext
property.
module.exports = {
install: function (less, pluginManager, functions) {
functions.add("pi", function () {
// Loader context is available in `pluginManager.webpackLoaderContext`
return Math.PI;
});
},
};
Bundling CSS with webpack has some nice advantages like referencing images and fonts with hashed urls or hot module replacement in development. In production, on the other hand, it's not a good idea to apply your style sheets depending on JS execution. Rendering may be delayed or even a FOUC might be visible. Thus it's often still better to have them as separate files in your final production build.
There are two possibilities to extract a style sheet from the bundle:
extract-loader
(simpler, but specialized on the css-loader's output)MiniCssExtractPlugin
(more complex, but works in all use-cases)There is a known problem with Less and CSS modules regarding relative file paths in url(...)
statements. See this issue for an explanation.
Please take a moment to read our contributing guidelines if you haven't yet done so.
A Node.js add-ons loader.
Allows to connect native node modules with .node
extension.
⚠
node-loader
only works on thenode
/async-node
/electron-main
/electron-renderer
/electron-preload
targets.
To begin, you'll need to install node-loader
:
npm install node-loader --save-dev
or
yarn add -D node-loader
or
pnpm add -D node-loader
Setup the target
option to node
/async-node
/electron-main
/electron-renderer
/electron-preload
value and do not mock the __dirname
global variable.
webpack.config.js
module.exports = {
resolve: {
extensions: ["...", ".node"],
},
target: "node",
node: {
__dirname: false,
},
module: {
rules: [
{
test: /\.node$/,
loader: "node-loader",
},
],
},
};
index.js
import node from "node-loader!./file.node";
And run webpack
via your preferred method.
index.js
import node from "file.node";
Then add the loader to your webpack
config. For example:
webpack.config.js
module.exports = {
target: "node",
node: {
__dirname: false,
},
module: {
rules: [
{
test: /\.node$/,
loader: "node-loader",
},
],
},
};
And run webpack
via your preferred method.
Name | Type | Default | Description |
---|---|---|---|
flags | {Number} | undefined | Enables/Disables url /image-set functions handling |
name | {String|Function} | '[contenthash].[ext]' | Specifies a custom filename template for the target file(s). |
flags
Type: Number
Default: undefined
The flags
argument is an integer that allows to specify dlopen behavior.
See the process.dlopen
documentation for details.
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
Type: String|Function
Default: '[contenthash].[ext]'
Specifies a custom filename template for the target file(s).
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]";
},
},
},
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
Loader to process CSS with PostCSS
.
You need webpack v5 to use the latest version. For Webpack v4, you have to install postcss-loader v4.
To begin, you'll need to install postcss-loader
and postcss
:
npm install --save-dev postcss-loader postcss
or
yarn add -D postcss-loader postcss
or
pnpm add -D postcss-loader postcss
Then add the plugin to your webpack
config. For example:
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",
{
// Options
},
],
],
},
},
},
],
},
],
},
};
Alternative use with config files:
postcss.config.js
module.exports = {
plugins: [
[
"postcss-preset-env",
{
// Options
},
],
],
};
The loader automatically searches for configuration files.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader", "postcss-loader"],
},
],
},
};
And run webpack
via your preferred method.
execute
Type:
type execute = boolean;
Default: undefined
Enable PostCSS Parser support in CSS-in-JS
.
If you use JS styles the postcss-js
parser, add the execute
option.
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
See the file https://github.com/webpack-contrib/postcss-loader/blob/master/src/config.d.ts
.
Type:
import type { Config as PostCSSConfig } from "postcss-load-config";
import type { LoaderContext } from "webpack";
type PostCSSLoaderContext = LoaderContext<PostCSSConfig>;
interface PostCSSLoaderAPI {
mode: PostCSSLoaderContext["mode"];
file: PostCSSLoaderContext["resourcePath"];
webpackLoaderContext: PostCSSLoaderContext;
env: PostCSSLoaderContext["mode"];
options: PostCSSConfig;
}
export type PostCSSLoaderOptions =
| PostCSSConfig
| ((api: PostCSSLoaderAPI) => PostCSSConfig);
Default: undefined
Allows to set PostCSS options
and plugins.
All PostCSS
options are supported.
There is the special config
option for config files. How it works and how it can be configured is described below.
We recommend do not specify from
, to
and map
options, because this can lead to wrong path in source maps.
If you need source maps please use the sourcemap
option.
For large projects, to optimize performance of the loader, it is better to provide postcssOptions
in loader
config and specify config: false
. This approach removes the need to lookup and load external config files multiple
times during compilation.
object
Setup 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 }),
// Deprecated and will be removed in the next major release
{ "postcss-nested": { preserveEmpty: true } },
],
},
},
},
],
},
};
webpack.config.js (deprecated, will be removed in the next major release)
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: {
"postcss-import": {},
"postcss-short": { prefix: "x" },
},
},
},
},
],
},
};
Setup syntax
:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: "postcss-loader",
options: {
postcssOptions: {
// Can be `string`
syntax: "sugarss",
// Can be `object`
syntax: require("sugarss"),
},
},
},
],
},
};
Setup parser
:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: "postcss-loader",
options: {
postcssOptions: {
// Can be `string`
parser: "sugarss",
// Can be `object`
parser: require("sugarss"),
// Can be `function`
parser: require("sugarss").parse,
},
},
},
],
},
};
Setup stringifier
:
webpack.config.js
const Midas = require("midas");
const midas = new Midas();
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: "postcss-loader",
options: {
postcssOptions: {
// Can be `string`
stringifier: "sugarss",
// Can be `object`
stringifier: require("sugarss"),
// Can be `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
Type:
type config = boolean | string;
Default: true
Allows to set options using config files. Options specified in the config file are combined with options passed to the loader, the loader options overwrite options from config.
The loader will search up the directory tree for configuration in the following places:
postcss
property in package.json
.postcssrc
file in JSON or YAML format.postcssrc.json
, .postcssrc.yaml
, .postcssrc.yml
, .postcssrc.js
, or .postcssrc.cjs
filepostcss.config.js
or postcss.config.cjs
CommonJS module exporting an object (recommended)Using object
notation:
postcss.config.js (recommend)
module.exports = {
// You can specify any options from https://postcss.org/api/#processoptions here
// parser: 'sugarss',
plugins: [
// Plugins for PostCSS
["postcss-short", { prefix: "x" }],
"postcss-preset-env",
],
};
Using function
notation:
postcss.config.js (recommend)
module.exports = (api) => {
// `api.file` - path to the file
// `api.mode` - `mode` value of webpack, please read https://webpack.js.org/configuration/mode/
// `api.webpackLoaderContext` - loader context for complex use cases
// `api.env` - alias `api.mode` for compatibility with `postcss-cli`
// `api.options` - the `postcssOptions` options
if (/\.sss$/.test(api.file)) {
return {
// You can specify any options from https://postcss.org/api/#processoptions here
parser: "sugarss",
plugins: [
// Plugins for PostCSS
["postcss-short", { prefix: "x" }],
"postcss-preset-env",
],
};
}
return {
// You can specify any options from https://postcss.org/api/#processoptions here
plugins: [
// Plugins for PostCSS
["postcss-short", { prefix: "x" }],
"postcss-preset-env",
],
};
};
postcss.config.js (deprecated, will be removed in the next major release)
module.exports = {
// You can specify any options from https://postcss.org/api/#processoptions here
// parser: 'sugarss',
plugins: {
// Plugins for PostCSS
"postcss-short": { prefix: "x" },
"postcss-preset-env": {},
},
};
You can use different postcss.config.js
files in different directories.
Config lookup starts from path.dirname(file)
and walks the file tree upwards until a config file is found.
|– 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
After setting up your postcss.config.js
, add postcss-loader
to your webpack.config.js
.
You can use it standalone or in conjunction with css-loader
(recommended).
Use it before css-loader
and style-loader
, but after other preprocessor loaders like e.g sass|less|stylus-loader
, if you use any (since webpack loaders evaluate right to left/bottom to top).
webpack.config.js (recommended)
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
importLoaders: 1,
},
},
"postcss-loader",
],
},
],
},
};
boolean
Enables/Disables autoloading config.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "postcss-loader",
options: {
postcssOptions: {
config: false,
},
},
},
],
},
};
Allows to specify the path to the config file.
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
Type:
type sourceMap = boolean;
Default: depends on the compiler.devtool
value
By default generation of source maps depends on the devtool
option.
All values enable source map generation except eval
and false
value.
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 } },
],
},
],
},
};
Alternative setup:
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
Type:
type implementation = object;
type of implementation
should be the same as postcss.d.ts
Default: postcss
The special implementation
option determines which implementation of PostCSS to use. Overrides the locally installed peerDependency
version of postcss
.
This option is only really useful for downstream tooling authors to ease the PostCSS 7-to-8 transition.
function
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" },
],
},
],
},
};
You'll need to install sugarss
:
npm install --save-dev sugarss
Using SugarSS
syntax.
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",
},
},
},
],
},
],
},
};
You'll need to install autoprefixer
:
npm install --save-dev autoprefixer
Add vendor prefixes to CSS rules using 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",
{
// Options
},
],
],
},
},
},
],
},
],
},
};
[!WARNING]
postcss-preset-env
includesautoprefixer
, so adding it separately is not necessary if you already use the preset. More information
You'll need to install 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",
{
// Options
},
],
],
},
},
},
],
},
],
},
};
What is CSS Modules
? Please read.
No additional options required on the postcss-loader
side.
To make them work properly, either add the css-loader
’s importLoaders
option.
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
You'll need to install postcss-js
:
npm install --save-dev postcss-js
If you want to process styles written in JavaScript, use the 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",
],
},
],
},
};
As result you will be able to write styles in the following way
import colors from "./styles/colors";
export default {
".menu": {
color: colors.main,
height: 25,
"&_link": {
color: "white",
},
},
};
[!WARNING]
If you are using Babel you need to do the following in order for the setup to work
- Add
babel-plugin-add-module-exports
to your configuration.- You need to have only one default export per style module.
Using mini-css-extract-plugin
.
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",
}),
],
};
To write a asset from PostCSS plugin to the webpack, need to add a message in result.messages
.
The message should contain the following fields:
type
= asset
- Message type (require, should be equal asset
)file
- file name (require)content
- file content (require)sourceMap
- sourceMapinfo
- asset infowebpack.config.js
const postcssCustomPlugin = (opts = {}) => {
return {
postcssPlugin: "postcss-custom-plugin",
Once: (root, { result }) => {
result.messages.push({
type: "asset",
file: "sprite.svg",
content: "<svg>...</svg>",
});
},
};
};
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [postcssCustomPlugin()],
},
},
},
],
},
],
},
};
The dependencies are necessary for webpack to understand when it needs to run recompilation on the changed files.
There are two way to add dependencies:
result.messages
.The message should contain the following fields:
type
= dependency
- Message type (require, should be equal dependency
, context-dependency
, build-dependency
or missing-dependency
)file
- absolute file path (require)webpack.config.js
const path = require("path");
const postcssCustomPlugin = (opts = {}) => {
return {
postcssPlugin: "postcss-custom-plugin",
Once: (root, { result }) => {
result.messages.push({
type: "dependency",
file: path.resolve(__dirname, "path", "to", "file"),
});
},
};
};
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [postcssCustomPlugin()],
},
},
},
],
},
],
},
};
Or you can use ready-made plugin postcss-add-dependencies.
loaderContext
in plugin.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/postcssCustomPlugin.js")({
loaderContext: api.webpackLoaderContext,
}),
],
});
postcssCustomPlugin.js
const path = require("path");
const postcssCustomPlugin = (opts = {}) => {
return {
postcssPlugin: "postcss-custom-plugin",
Once: (root, { result }) => {
opts.loaderContext.addDependency(
path.resolve(__dirname, "path", "to", "file"),
);
},
};
};
postcssCustomPlugin.postcss = true;
module.exports = postcssCustomPlugin;
Please take a moment to read our contributing guidelines if you haven't yet done so.
Load markdown through remark
.
Simply add the loader to your configuration, and pass 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],
},
},
},
],
},
],
},
};
Here's the full list of remark
plugins.
We no longer support any react
specific features.
Please see the wonderful MDX project if you're interested in mixing JSX with Markdown.
Remark options
Type:
type remarkOptions = {
plugins: Array<string | Array>;
settings: Object;
data: Object;
};
Allows to connect remark
plugins
Type:
type plugins = Array<string | Array>;
Default: []
Allows to connect remark
plugins
webpack.config.js
import RemarkFrontmatter from "remark-frontmatter";
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
remarkOptions: {
plugins: [RemarkFrontmatter],
},
},
},
],
},
],
},
};
If need to specify options for the plugin, can pass the plugin using an array, where the second argument will be 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",
},
},
],
],
},
},
},
],
},
],
},
};
Remark settings
Type:
type settings = Object;
Default: undefined
Pass remark-stringify
options and remark-parse
options options to the remark
.
webpack.config.js
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
remarkOptions: {
settings: {
bullet: "+",
listItemIndent: "1",
},
},
},
},
],
},
],
},
};
Information available to all plugins
Type:
type data = Object;
Default: undefined
Configure the remark
with information available to all plugins.
Information is stored in an in-memory key-value store.
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",
},
},
},
},
],
},
],
},
};
Remove removeFrontMatter
Type:
type removeFrontMatter = boolean;
Default: true
By default, the frontMatter is removed.
To override this behavior, set removeFrontMatter
to false
and add remark-frontmatter
to plugins.
webpack.config.js
import RemarkFrontmatter from "remark-frontmatter";
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
removeFrontMatter: false,
remarkOptions: {
plugins: [RemarkFrontmatter],
},
},
},
],
},
],
},
};
This project was inspired the following open source work:
To get html, need to add remark-html
to the remark plugins and add html-loader
to the webpack.config
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",
},
],
},
],
},
};
Please take a moment to read our contributing guidelines if you haven't yet done so.
Loads a Sass/SCSS file and compiles it to CSS.
To begin, you'll need to install sass-loader
:
npm install sass-loader sass webpack --save-dev
or
yarn add -D sass-loader sass webpack
or
pnpm add -D sass-loader sass webpack
[!NOTE]
To enable CSS processing in your project, you need to install style-loader and css-loader via
npm i style-loader css-loader
.
sass-loader
requires you to install either Dart Sass, Node Sass on your own (more documentation can be found below) or Sass Embedded.
This allows you to control the versions of all your dependencies, and to choose which Sass implementation to use.
[!NOTE]
We highly recommend using Sass Embedded or Dart Sass.
[!WARNING]
Node Sass does not work with Yarn PnP and doesn't support @use rule.
Chain the sass-loader
with the css-loader and the style-loader to immediately apply all styles to the DOM or the mini-css-extract-plugin to extract it into a separate file.
Then add the loader to your webpack configuration. For example:
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: [
// Creates `style` nodes from JS strings
"style-loader",
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
],
},
};
Finally run webpack
via your preferred method.
style
(new API, by default since 16 version) and outputStyle
(old API) options in production
modeFor production
mode, the style
(new API, by default since 16 version) and outputStyle
(old API) options default to compressed
unless otherwise specified in sassOptions
.
import
and use
at-rulesWebpack provides an advanced mechanism to resolve files.
The sass-loader
uses Sass's custom importer feature to pass all queries to the webpack resolving engine enabling you to import your Sass modules from node_modules
.
@import "bootstrap";
Using ~
is deprecated and should be removed from your code, but we still support it for historical reasons.
Why can you remove it? The loader will first try to resolve @import
as a relative path. If it cannot be resolved, then the loader will try to resolve @import
inside node_modules
.
Prepending module paths with a ~
tells webpack to search through node_modules
.
@import "~bootstrap";
It's important to prepend the path with only ~
, because ~/
resolves to the home directory.
Webpack needs to distinguish between bootstrap
and ~bootstrap
because CSS and Sass files have no special syntax for importing relative files.
Writing @import "style.scss"
is the same as @import "./style.scss";
url(...)
Since Sass implementations don't provide url rewriting, all linked assets must be relative to the output.
css-loader
, all urls must be relative to the entry-file (e.g. main.scss
).css-loader
, it must be relative to your web root.You might be surprised by this first issue, as it is natural to expect relative references to be resolved against the .sass
/.scss
file in which they are specified (like in regular .css
files).
Thankfully there are two solutions to this problem:
sass-loader
in the loader chain.$icon-font-path
.implementation
Type:
type implementation = object | string;
Default: sass
The special implementation
option determines which implementation of Sass to use.
By default, the loader resolves the implementation based on your dependencies.
Just add the desired implementation to your package.json
(sass
, sass-embedded
, or node-sass
package) and install dependencies.
Example where the sass-loader
loader uses the sass
(dart-sass
) implementation:
package.json
{
"devDependencies": {
"sass-loader": "^7.2.0",
"sass": "^1.22.10"
}
}
Example where the sass-loader
loader uses the node-sass
implementation:
package.json
{
"devDependencies": {
"sass-loader": "^7.2.0",
"node-sass": "^5.0.0"
}
}
Example where the sass-loader
loader uses the sass-embedded
implementation:
package.json
{
"devDependencies": {
"sass-loader": "^7.2.0",
"sass": "^1.22.10"
},
"optionalDependencies": {
"sass-embedded": "^1.70.0"
}
}
[!NOTE]
Using
optionalDependencies
means thatsass-loader
can fallback tosass
when running on an operating system not supported bysass-embedded
Be aware of the order that sass-loader
will resolve the implementation:
sass-embedded
sass
node-sass
You can specify a specific implementation by using the implementation
option, which accepts one of the above values.
object
For example, to always use Dart Sass, you'd pass:
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
"style-loader",
"css-loader",
{
loader: "sass-loader",
options: {
// Prefer `dart-sass`, even if `sass-embedded` is available
implementation: require("sass"),
},
},
],
},
],
},
};
string
For example, to use Dart Sass, you'd pass:
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
"style-loader",
"css-loader",
{
loader: "sass-loader",
options: {
// Prefer `dart-sass`, even if `sass-embedded` is available
implementation: require.resolve("sass"),
},
},
],
},
],
},
};
sassOptions
Type:
type sassOptions =
| import("sass").LegacyOptions<"async">
| ((
content: string | Buffer,
loaderContext: LoaderContext,
meta: any,
) => import("sass").LegacyOptions<"async">);
Default: defaults values for Sass implementation
Options for Dart Sass or Node Sass implementation.
[!NOTE]
The
charset
option istrue
by default fordart-sass
, we strongly discourage setting this tofalse
, because webpack doesn't support files other thanutf-8
.
[!NOTE]
The
syntax
(new API, by default since 16 version)and
indentedSyntax(old API) option is
scssfor the
scssextension,
indentedfor the
sassextension and
cssfor the
css` extension.
[!NOTE]
Options such as
data
andfile
are unavailable and will be ignored.
ℹ We strongly discourage changing the
sourceMap
(new API, by default since 16 version),outFile
(old API),sourceMapContents
(old API),sourceMapEmbed
(old API), andsourceMapRoot
(old API) options becausesass-loader
sets these automatically when thesourceMap
option istrue
.
[!NOTE]
Access to the loader context inside the custom importer can be done using the
this.webpackLoaderContext
property.
There is a slight difference between the options for sass
(dart-sass
) and node-sass
.
Please consult their respective documentation before using them:
sass
options.sass
options.node-sass
options.object
Use an object for the Sass implementation setup.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
"style-loader",
"css-loader",
{
loader: "sass-loader",
options: {
sassOptions: {
style: `compressed`,
loadPaths: ["absolute/path/a", "absolute/path/b"],
},
},
},
],
},
],
},
};
function
Allows configuring the Sass implementation with different options based on the loader context.
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
"style-loader",
"css-loader",
{
loader: "sass-loader",
options: {
sassOptions: (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 {
loadPaths: ["absolute/path/c", "absolute/path/d"],
};
}
return {
loadPaths: ["absolute/path/a", "absolute/path/b"],
};
},
},
},
],
},
],
},
};
sourceMap
Type:
type sourceMap = boolean;
Default: depends on the compiler.devtool
value
Enables/Disables generation of source maps.
By default generation of source maps depends on the devtool
option.
All values enable source map generation except eval
and false
.
ℹ If
true
, thesourceMap
(new API, by default since 16 version),outFile
(old API),sourceMapContents
(old API),sourceMapEmbed
(old API), andsourceMapRoot
(old API) fromsassOptions
will be ignored.
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,
},
},
],
},
],
},
};
ℹ In some rare cases
node-sass
can output invalid source maps (it is anode-sass
bug).In order to avoid this, you can try to update
node-sass
to latest version, or you can try to set withinsassOptions
theoutputStyle
option tocompressed
.
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
Type:
type additionalData =
| string
| ((content: string | Buffer, loaderContext: LoaderContext) => string);
Default: undefined
Prepends Sass
/SCSS
code before the actual entry file.
In this case, the sass-loader
will not override the data
option but just prepend the entry's content.
This is especially useful when some of your Sass variables depend on the environment:
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) => {
// 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;
},
},
},
],
},
],
},
};
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
Type:
type webpackImporter = boolean;
Default: true
Enables/Disables the default webpack importer.
This can improve performance in some cases, though use it with caution because aliases and @import
at-rules starting with ~
will not work.
You can pass your own importer
to solve this (see 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:
type warnRuleAsWarning = boolean;
Default: true
Treats the @warn
rule as a webpack warning.
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);
}
The presented code will throw a webpack warning instead logging.
To ignore unnecessary warnings you can use the ignoreWarnings option.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
"style-loader",
"css-loader",
{
loader: "sass-loader",
options: {
warnRuleAsWarning: true,
},
},
],
},
],
},
};
api
Type:
type api = "legacy" | "modern" | "modern-compiler";
Default: "modern"
for sass
(dart-sass
) and sass-embedded
, or "legacy"
for node-sass
Allows you to switch between the legacy
and modern
APIs. You can find more information here. The modern-compiler
option enables the modern API with support for Shared Resources.
[!NOTE]
Using
modern-compiler
andsass-embedded
together significantly improve performance and decrease built time. We strongly recommend their use. We will enable them by default in a future major release.
[!WARNING]
The sass options are different for the
legacy
andmodern
APIs. Please look at docs how to migrate to the modern options.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
"style-loader",
"css-loader",
{
loader: "sass-loader",
options: {
api: "modern-compiler",
sassOptions: {
// Your sass options
},
},
},
],
},
],
},
};
@debug
outputBy default, the output of @debug
messages are disabled.
Add the following to webpack.config.js to enable them:
module.exports = {
stats: {
loggingDebug: ["sass-loader"],
},
// ...
};
For production builds it's recommended to extract the CSS from your bundle to be able to use parallel loading of CSS/JS resources later on.
There are four recommended ways to extract a stylesheet from a bundle:
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// fallback to style-loader in development
process.env.NODE_ENV !== "production"
? "style-loader"
: MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader",
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].css",
chunkFilename: "[id].css",
}),
],
};
webpack.config.js
module.exports = {
entry: [__dirname + "/src/scss/app.scss"],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [],
},
{
test: /\.scss$/,
exclude: /node_modules/,
type: "asset/resource",
generator: {
filename: "bundle.css",
},
use: ["sass-loader"],
},
],
},
};
webpack.config.js
module.exports = {
entry: [__dirname + "/src/scss/app.scss"],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [],
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{
loader: "file-loader",
options: { outputPath: "css/", name: "[name].min.css" },
},
"sass-loader",
],
},
],
},
};
(source: https://stackoverflow.com/a/60029923/2969615)
Enables/Disables generation of source maps.
To enable CSS source maps, you'll need to pass the sourceMap
option to the sass-loader
and the css-loader
.
webpack.config.js
module.exports = {
devtool: "source-map", // any "source-map"-like devtool is possible
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
"style-loader",
{
loader: "css-loader",
options: {
sourceMap: true,
},
},
{
loader: "sass-loader",
options: {
sourceMap: true,
},
},
],
},
],
},
};
If you want to edit the original Sass files inside Chrome, there's a good blog post. Checkout test/sourceMap for a running example.
Please take a moment to read our contributing guidelines if you haven't yet done so.
Extracts source maps from existing source files (from their sourceMappingURL
).
To begin, you'll need to install source-map-loader
:
npm i -D source-map-loader
or
yarn add -D source-map-loader
or
pnpm add -D source-map-loader
Then add the plugin to your webpack
config. For example:
file.js
import css from "file.css";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
enforce: "pre",
use: ["source-map-loader"],
},
],
},
};
The source-map-loader
extracts existing source maps from all JavaScript entries.
This includes both inline source maps as well as those linked via URL.
All source map data is passed to webpack for processing as per a chosen source map style specified by the devtool
option in webpack.config.js.
This loader is especially useful when using 3rd-party libraries having their own source maps.
If not extracted and processed into the source map of the webpack bundle, browsers may misinterpret source map data. source-map-loader
allows webpack to maintain source map data continuity across libraries so ease of debugging is preserved.
The source-map-loader
will extract from any JavaScript file, including those in the node_modules
directory.
Be mindful in setting include and exclude rule conditions to maximize bundling performance.
And run webpack
via your preferred method.
Name | Type | Default | Description |
---|---|---|---|
filterSourceMappingUrl | {Function} | undefined | Allows to control SourceMappingURL behaviour |
Type: Function
Default: undefined
Allows you to specify the behavior of the loader for SourceMappingURL
comment.
The function must return one of the values:
true
or 'consume'
- consume the source map and remove SourceMappingURL
comment (default behavior)false
or 'remove'
- do not consume the source map and remove SourceMappingURL
commentskip
- do not consume the source map and do not remove SourceMappingURL
commentExample configuration:
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;
},
},
},
],
},
],
},
};
To ignore warnings, you can use the following configuration:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
enforce: "pre",
use: ["source-map-loader"],
},
],
},
ignoreWarnings: [/Failed to parse source map/],
};
More information about the ignoreWarnings
option can be found here
Please take a moment to read our contributing guidelines if you haven't yet done so.
Inject CSS into the DOM.
To begin, you'll need to install style-loader
:
npm install --save-dev style-loader
or
yarn add -D style-loader
or
pnpm add -D style-loader
It's recommended to combine style-loader
with the css-loader
Then add the loader to your webpack
config. For example:
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"],
},
],
},
};
This loader is primarily meant for development. The default settings are not safe for production environments. See the recommended example configuration and the section on nonces for details.
injectType
Type:
type injectType =
| "styleTag"
| "singletonStyleTag"
| "autoStyleTag"
| "lazyStyleTag"
| "lazySingletonStyleTag"
| "lazyAutoStyleTag"
| "linkTag";
Default: styleTag
Allows to setup how styles will be injected into the DOM.
Possible values:
styleTag
Automatically injects styles into the DOM using multiple <style></style>
. It is default behaviour.
component.js
import "./styles.css";
Example with Locals (CSS Modules):
component-with-css-modules.js
import * as styles from "./styles.css";
const divElement = document.createElement("div");
divElement.className = styles["my-class"];
All local variables (class names) are exported as named exports. To achieve this behaviour you also have to setup modules
option for css-loader
. For more information consult with css-loader
documentation
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
// The `injectType` option can be avoided because it is default behaviour
{ loader: "style-loader", options: { injectType: "styleTag" } },
{
loader: "css-loader",
// Uncomment it if you want to use CSS modules
// options: { modules: true }
},
],
},
],
},
};
The loader inject styles like:
<style>
.foo {
color: red;
}
</style>
<style>
.bar {
color: blue;
}
</style>
singletonStyleTag
Automatically injects styles into the DOM using one <style></style>
.
[!WARNING]
Source maps do not work.
component.js
import "./styles.css";
component-with-css-modules.js
import * as styles from "./styles.css";
const divElement = document.createElement("div");
divElement.className = styles["my-class"];
All local variables (class names) are exported as named exports. To achieve this behaviour you also have to setup modules
option for css-loader
. For more information consult with css-loader
documentation
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: { injectType: "singletonStyleTag" },
},
{
loader: "css-loader",
// Uncomment it if you want to use CSS modules
// options: { modules: true }
},
],
},
],
},
};
The loader inject styles like:
<style>
.foo {
color: red;
}
.bar {
color: blue;
}
</style>
autoStyleTag
Works the same as a styleTag
, but if the code is executed in IE6-9, turns on the singletonStyleTag
mode.
lazyStyleTag
Injects styles into the DOM using multiple <style></style>
on demand.
We recommend following .lazy.css
naming convention for lazy styles and the .css
for basic style-loader
usage (similar to other file types, i.e. .lazy.less
and .less
).
When you lazyStyleTag
value the style-loader
injects the styles lazily making them useable on-demand via style.use()
/ style.unuse()
.
⚠️ Behavior is undefined when
unuse
is called more often thanuse
. Don't do that.
component.js
import styles from "./styles.lazy.css";
styles.use();
// For removing styles you can use
// styles.unuse();
component-with-css-modules.js
import styles, { "my-class" as myClass } from "./styles.lazy.css";
styles.use();
const divElement = document.createElement("div");
divElement.className = myClass;
All local variables (class names) are exported as named exports. To achieve this behaviour you also have to setup modules
option for css-loader
. For more information consult with css-loader
documentation
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
exclude: /\.lazy\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.lazy\.css$/i,
use: [
{ loader: "style-loader", options: { injectType: "lazyStyleTag" } },
{
loader: "css-loader",
// Uncomment it if you want to use CSS modules
// options: { modules: true }
},
],
},
],
},
};
The loader inject styles like:
<style>
.foo {
color: red;
}
</style>
<style>
.bar {
color: blue;
}
</style>
lazySingletonStyleTag
Injects styles into the DOM using one <style></style>
on demand.
We recommend following .lazy.css
naming convention for lazy styles and the .css
for basic style-loader
usage (similar to other file types, i.e. .lazy.less
and .less
).
When you lazySingletonStyleTag
value the style-loader
injects the styles lazily making them useable on-demand via style.use()
/ style.unuse()
.
⚠️ Source maps do not work.
⚠️ Behavior is undefined when
unuse
is called more often thanuse
. Don't do that.
component.js
import styles from "./styles.css";
styles.use();
// For removing styles you can use
// styles.unuse();
component-with-css-modules.js
import styles, { "my-class" as myClass } from "./styles.lazy.css";
styles.use();
const divElement = document.createElement("div");
divElement.className = myClass;
All local variables (class names) are exported as named exports. To achieve this behaviour you also have to setup modules
option for css-loader
. For more information consult with css-loader
documentation
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
exclude: /\.lazy\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.lazy\.css$/i,
use: [
{
loader: "style-loader",
options: { injectType: "lazySingletonStyleTag" },
},
{
loader: "css-loader",
// Uncomment it if you want to use CSS modules
// options: { modules: true }
},
],
},
],
},
};
The loader generate this:
<style>
.foo {
color: red;
}
.bar {
color: blue;
}
</style>
lazyAutoStyleTag
Works the same as a lazyStyleTag
, but if the code is executed in IE6-9, turns on the lazySingletonStyleTag
mode.
linkTag
Injects styles into the DOM using multiple <link rel="stylesheet" href="path/to/file.css">
.
ℹ️ The loader will dynamically insert the
<link href="path/to/file.css" rel="stylesheet">
tag at runtime via JavaScript. You should use MiniCssExtractPlugin if you want to include a static<link href="path/to/file.css" rel="stylesheet">
.
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" },
],
},
],
},
};
The loader generate this:
<link rel="stylesheet" href="path/to/style.css" />
<link rel="stylesheet" href="path/to/other-styles.css" />
attributes
Type:
type attributes = HTMLAttributes;
Default: {}
If defined, the style-loader
will attach given attributes with their values on <style>
/ <link>
element.
component.js
import "./file.css";
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: "style-loader", options: { attributes: { id: "id" } } },
{ loader: "css-loader" },
],
},
],
},
};
<style id="id"></style>
insert
Type:
type insert = string;
Default: head
By default, the style-loader
appends <style>
/<link>
elements to the end of the style target, which is the <head>
tag of the page unless specified by insert
.
This will cause CSS created by the loader to take priority over CSS already present in the target.
You can use other values if the standard behavior is not suitable for you, but we do not recommend doing this.
If you target an iframe make sure you have sufficient access rights, the styles will be injected into the content document head.
Selector
Allows to setup custom query selector where styles inject into the DOM.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: "body",
},
},
"css-loader",
],
},
],
},
};
Absolute path to function
Allows to setup absolute path to custom function that allows to override default behavior and insert styles at any position.
[!WARNING]
Do not forget that this code will be used in the browser and not all browsers support latest ECMA features like
let
,const
,arrow function expression
and etc. We recommend usingbabel-loader
for support latest ECMA features.
[!WARNING]
Do not forget that some DOM methods may not be available in older browsers, we recommended use only DOM core level 2 properties, but it is depends what browsers you want to support
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: require.resolve("./path-to-insert-module"),
},
},
"css-loader",
],
},
],
},
};
A new <style>
/<link>
elements will be inserted into at bottom of body
tag.
Examples:
Insert styles at top of head
tag:
insert-function.js
function insertAtTop(element) {
var parent = document.querySelector("head");
// eslint-disable-next-line no-underscore-dangle
var lastInsertedElement = window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, parent.firstChild);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling);
} else {
parent.appendChild(element);
}
// eslint-disable-next-line no-underscore-dangle
window._lastElementInsertedByStyleLoader = element;
}
module.exports = insertAtTop;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: require.resolve("./insert-function"),
},
},
"css-loader",
],
},
],
},
};
You can pass any parameters to style.use(options)
and this value will be passed to insert
and styleTagTransform
functions.
insert-function.js
function insertIntoTarget(element, options) {
var parent = options.target || document.head;
parent.appendChild(element);
}
module.exports = insertIntoTarget;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
injectType: "lazyStyleTag",
// Do not forget that this code will be used in the browser and
// not all browsers support latest ECMA features like `let`, `const`, `arrow function expression` and etc,
// we recommend use only ECMA 5 features,
// but it depends what browsers you want to support
insert: require.resolve("./insert-function.js"),
},
},
"css-loader",
],
},
],
},
};
Insert styles to the provided element or to the head
tag if target isn't provided. Now you can inject styles into Shadow DOM (or any other element).
custom-square.css
div {
width: 50px;
height: 50px;
background-color: red;
}
custom-square.js
import customSquareStyles from "./custom-square.css";
class CustomSquare extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
const divElement = document.createElement("div");
divElement.textContent = "Text content.";
this.shadowRoot.appendChild(divElement);
customSquareStyles.use({ target: this.shadowRoot });
// You can override injected styles
const bgPurple = new CSSStyleSheet();
const width = this.getAttribute("w");
const height = this.getAttribute("h");
bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);
this.shadowRoot.adoptedStyleSheets = [bgPurple];
// `divElement` will have `100px` width, `100px` height and `red` background color
}
}
customElements.define("custom-square", CustomSquare);
export default CustomSquare;
styleTagTransform
Type:
type styleTagTransform = string;
Default: undefined
string
Allows to setup absolute path to custom function that allows to override default behavior styleTagTransform.
[!WARNING]
Do not forget that this code will be used in the browser and not all browsers support latest ECMA features like
let
,const
,arrow function expression
and etc, we recommend use only ECMA 5 features, but it is depends what browsers you want to support
[!WARNING]
Do not forget that some DOM methods may not be available in older browsers, we recommended use only DOM core level 2 properties, but it depends what browsers you want to support
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
injectType: "styleTag",
styleTagTransform: require.resolve("style-tag-transform-code"),
},
},
"css-loader",
],
},
],
},
};
base
type base = number;
This setting is primarily used as a workaround for css clashes when using one or more DllPlugin's. base
allows you to prevent either the app's css (or DllPlugin2's css) from overwriting DllPlugin1's css by specifying a css module id base which is greater than the range used by DllPlugin1 e.g.:
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:
type esModule = boolean;
Default: true
By default, style-loader
generates JS modules that use the ES modules syntax.
There are some cases in which using ES modules is beneficial, like in the case of module concatenation and tree shaking.
You can enable a CommonJS modules syntax using:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "style-loader",
options: {
esModule: false,
},
},
],
},
};
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, because it creates separate css files.
For development
mode (including webpack-dev-server
) you can use style-loader
, because it injects CSS into the DOM using multiple <style></style>
and works faster.
[!WARNING]
Do not use together
style-loader
andmini-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()]),
};
[!WARNING]
It is not allowed to use JavaScript reserved words in css class names.
[!WARNING]
Options
esModule
andmodules.namedExport
incss-loader
should be enabled (by default forcss-loader@7
it is true).
styles.css
.fooBaz {
color: red;
}
.bar {
color: blue;
}
.my-class {
color: green;
}
index.js
import { fooBaz, bar, "my-class" as myClass } from "./styles.css";
console.log(fooBaz, bar, myClass);
Or:
index.js
import * as styles from "./styles.css";
console.log(styles.fooBaz, styles.bar, styles["my-class"]);
You can enable a ES module named export using:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
options: {
modules: {
namedExport: true,
},
},
},
],
},
],
},
};
The loader automatically inject source maps when previous loader emit them.
Therefore, to generate source maps, set the sourceMap
option to true
for the previous loader.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
"style-loader",
{ loader: "css-loader", options: { sourceMap: true } },
],
},
],
},
};
If you are using a Content Security Policy (CSP), the injected code will usually be blocked. A workaround is to use a nonce. Note, however, that using a nonce significantly reduces the protection provided by the CSP. You can read more about the security impact in the specification. The better solution is not to use this loader in production.
There are two ways to work with nonce
:
attributes
option__webpack_nonce__
variable[!WARNING]
the
attributes
option takes precedence over the__webpack_nonce__
variable
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",
],
},
],
},
};
The loader generate:
<style nonce="12345678">
.foo {
color: red;
}
</style>
__webpack_nonce__
create-nonce.js
__webpack_nonce__ = "12345678";
component.js
import "./create-nonce.js";
import "./style.css";
Alternative example for require
:
component.js
__webpack_nonce__ = "12345678";
require("./style.css");
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
The loader generate:
<style nonce="12345678">
.foo {
color: red;
}
</style>
Insert styles at top of head
tag.
insert-function.js
function insertAtTop(element) {
var parent = document.querySelector("head");
var lastInsertedElement = window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, parent.firstChild);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling);
} else {
parent.appendChild(element);
}
window._lastElementInsertedByStyleLoader = element;
}
module.exports = insertAtTop;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: require.resolve("./insert-function.js"),
},
},
"css-loader",
],
},
],
},
};
Inserts styles before #id
element.
insert-function.js
function insertBeforeAt(element) {
const parent = document.querySelector("head");
const target = document.querySelector("#id");
const lastInsertedElement = window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, target);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling);
} else {
parent.appendChild(element);
}
window._lastElementInsertedByStyleLoader = element;
}
module.exports = insertBeforeAt;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
insert: require.resolve("./insert-function.js"),
},
},
"css-loader",
],
},
],
},
};
You can define custom target for your styles for the lazyStyleTag
type.
insert-function.js
function insertIntoTarget(element, options) {
var parent = options.target || document.head;
parent.appendChild(element);
}
module.exports = insertIntoTarget;
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader",
options: {
injectType: "lazyStyleTag",
// Do not forget that this code will be used in the browser and
// not all browsers support latest ECMA features like `let`, `const`, `arrow function expression` and etc,
// we recommend use only ECMA 5 features,
// but it is depends what browsers you want to support
insert: require.resolve("./insert-function.js"),
},
},
"css-loader",
],
},
],
},
};
Insert styles to the provided element or to the head
tag if target isn't provided.
custom-square.css
div {
width: 50px;
height: 50px;
background-color: red;
}
custom-square.js
import customSquareStyles from "./custom-square.css";
class CustomSquare extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
const divElement = document.createElement("div");
divElement.textContent = "Text content.";
this.shadowRoot.appendChild(divElement);
customSquareStyles.use({ target: this.shadowRoot });
// You can override injected styles
const bgPurple = new CSSStyleSheet();
const width = this.getAttribute("w");
const height = this.getAttribute("h");
bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);
this.shadowRoot.adoptedStyleSheets = [bgPurple];
// `divElement` will have `100px` width, `100px` height and `red` background color
}
}
customElements.define("custom-square", CustomSquare);
export default CustomSquare;
Please take a moment to read our contributing guidelines if you haven't yet done so.
A Stylus loader for webpack. Compiles Styl to CSS.
To begin, you'll need to install stylus
and stylus-loader
:
npm install stylus stylus-loader --save-dev
or
yarn add -D stylus stylus-loader
or
pnpm add -D stylus stylus-loader
Then add the loader to your webpack
config. For example:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
loader: "stylus-loader", // compiles Styl to CSS
},
],
},
};
And run webpack
via your preferred method.
stylusOptions
Type:
type stylusOptions =
| {
use: Array<string | Function>;
include: Array<string>;
import: Array<string>;
define: Array;
includeCSS: false;
resolveURL: boolean | Object;
lineNumbers: boolean;
hoistAtrules: boolean;
compress: boolean;
}
| (loaderContext: LoaderContext) => Array<string>;
Default: {}
You can pass any Stylus specific options to the stylus-loader
through the stylusOptions
property in the loader options
See the Stylus documentation.
Options in dash-case should use camelCase.
object
Use an object to pass options through to Stylus.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
},
{
loader: "stylus-loader",
options: {
stylusOptions: {
/**
* Specify Stylus plugins to use. Plugins may be passed as
* strings instead of importing them in your Webpack config.
*
* @type {(string|Function)[]}
* @default []
*/
use: ["nib"],
/**
* Add path(s) to the import lookup paths.
*
* @type {string[]}
* @default []
*/
include: [path.join(__dirname, "src/styl/config")],
/**
* Import the specified Stylus files/paths.
*
* @type {string[]}
* @default []
*/
import: ["nib", path.join(__dirname, "src/styl/mixins")],
/**
* Define Stylus variables or functions.
*
* @type {Array|Object}
* @default {}
*/
// Array is the recommended syntax: [key, value, raw]
define: [
["$development", process.env.NODE_ENV === "development"],
["rawVar", 42, true],
],
// Object is deprecated syntax (there is no possibility to specify "raw')
// define: {
// $development: process.env.NODE_ENV === 'development',
// rawVar: 42,
// },
/**
* Include regular CSS on @import.
*
* @type {boolean}
* @default false
*/
includeCSS: false,
/**
* Resolve relative url()'s inside imported files.
*
* @see https://stylus-lang.com/docs/js.html#stylusresolveroptions
*
* @type {boolean|Object}
* @default { nocheck: true }
*/
resolveURL: true,
// resolveURL: { nocheck: true },
/**
* Emits comments in the generated CSS indicating the corresponding Stylus line.
*
* @see https://stylus-lang.com/docs/executable.html
*
* @type {boolean}
* @default false
*/
lineNumbers: true,
/**
* Move @import and @charset to the top.
*
* @see https://stylus-lang.com/docs/executable.html
*
* @type {boolean}
* @default false
*/
hoistAtrules: true,
/**
* Compress CSS output.
* In the "production" mode is `true` by default
*
* @see https://stylus-lang.com/docs/executable.html
*
* @type {boolean}
* @default false
*/
compress: true,
},
},
},
],
},
],
},
};
function
Allows setting the options passed through to Stylus based off of the loader context.
module.exports = {
module: {
rules: [
{
test: /\.styl/,
use: [
"style-loader",
"css-loader",
{
loader: "stylus-loader",
options: {
stylusOptions: (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.styl") {
return {
paths: ["absolute/path/c", "absolute/path/d"],
};
}
return {
paths: ["absolute/path/a", "absolute/path/b"],
};
},
},
},
],
},
],
},
};
sourceMap
Type:
type 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
Type:
type webpackImporter = boolean;
Default: true
Enables/Disables the default Webpack importer.
This can improve performance in some cases.
Use it with caution because aliases and @import
at-rules starting with ~
will not work.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl/i,
use: [
"style-loader",
"css-loader",
{
loader: "stylus-loader",
options: {
webpackImporter: false,
},
},
],
},
],
},
};
additionalData
Type:
type additionalData =
| string
| (
content: string | Buffer,
loaderContext: LoaderContext,
meta: any
) => string;
Default: undefined
Prepends Stylus
code before the actual entry file.
In this case, the stylus-loader
will not override the source but just prepend the entry's content.
This is especially useful when some of your Stylus variables depend on the environment:
[!NOTE]
Since you're injecting code, this will break the source mappings in your entry file. Often there's a simpler solution than this, like multiple Stylus entry files.
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) => {
// 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.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) => {
// 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.styl") {
return "value = 100px" + content;
}
return "value 200px" + content;
},
},
},
],
},
],
},
};
implementation
Type:
type implementation = Function | string;
The special implementation
option determines which implementation of Stylus to use. Overrides the locally installed peerDependency
version of stylus
.
function
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl/i,
use: [
"style-loader",
"css-loader",
{
loader: "stylus-loader",
options: {
implementation: require("stylus"),
},
},
],
},
],
},
};
string
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl/i,
use: [
"style-loader",
"css-loader",
{
loader: "stylus-loader",
options: {
implementation: require.resolve("stylus"),
},
},
],
},
],
},
};
Chain the stylus-loader
with the css-loader
and the style-loader
to immediately apply all styles to the DOM.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
{
loader: "style-loader", // creates style nodes from JS strings
},
{
loader: "css-loader", // translates CSS into CommonJS
},
{
loader: "stylus-loader", // compiles Stylus to CSS
},
],
},
],
},
};
To enable sourcemaps for CSS, you'll need to pass the sourceMap
property in the loader's options. If this is not passed, the loader will respect the setting for webpack source maps, set in devtool
.
webpack.config.js
module.exports = {
devtool: "source-map", // any "source-map"-like devtool is possible
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", // creates style nodes from JS strings
},
{
loader: "css-loader", // translates CSS into CommonJS
},
{
loader: "stylus-loader", // compiles Stylus to CSS
options: {
stylusOptions: {
use: [require("nib")()],
import: ["nib"],
},
},
},
],
},
],
},
};
Stylus does not provide resolving capabilities in the json
function.
Therefore webpack resolver does not work for .json
files.
Use stylus resolver
.
index.styl
// Suppose the file is located here `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: {
// Specify the path. where to find files
paths: ["node_modules/vars"],
},
},
},
],
},
],
},
};
Usually, it's recommended to extract the style sheets into a dedicated file in production using the MiniCssExtractPlugin. This way your styles are not dependent on JavaScript.
Webpack provides an advanced mechanism to resolve files.
The stylus-loader
applies the webpack resolver when processing queries.
Thus you can import your Stylus modules from node_modules
.
@import 'bootstrap-styl/bootstrap/index.styl';
Using ~
is deprecated and can be removed from your code (we recommend it), but we still support it for historical reasons.
Why you can removed it? The loader will first try to resolve @import
/@require
as relative, if it cannot be resolved, the loader will try to resolve @import
/@require
inside node_modules
.
Just prepend them with a ~
which tells webpack to look up the modules
.
@import "~bootstrap-styl/bootstrap/index.styl";
It's important to only prepend it with ~
, because ~/
resolves to the home-directory.
Webpack needs to distinguish between bootstrap
and ~bootstrap
, because CSS and Styl files have no special syntax for importing relative files.
Writing @import "file"
is the same as @import "./file";
If you specify the paths
option, modules will be searched in the given paths
.
This is Stylus default behavior.
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")],
},
},
},
],
},
],
},
};
Bundling CSS with webpack has some nice advantages like referencing images and fonts with hashed urls or hot module replacement in development. In production, on the other hand, it's not a good idea to apply your style sheets depending on JS execution. Rendering may be delayed or even a FOUC might be visible. Thus it's often still better to have them as separate files in your final production build.
There are two possibilities to extract a style sheet from the bundle:
extract-loader
(simpler, but specialized on the css-loader's output)Please take a moment to read our contributing guidelines if you haven't yet done so.
Runs the following loaders in a worker pool.
npm install --save-dev thread-loader
or
yarn add -D thread-loader
or
pnpm add -D thread-loader
Put this loader in front of other loaders. The following loaders run in a worker pool.
Loaders running in a worker pool are limited. Examples:
Each worker is a separate node.js process, which has an overhead of ~600ms. There is also an overhead of inter-process communication.
Use this loader only for expensive operations!
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
include: path.resolve('src'),
use: [
'thread-loader',
// your expensive loader (e.g babel-loader)
],
},
],
},
};
with options
use: [
{
loader: 'thread-loader',
// loaders with equal options will share worker pools
options: {
// the number of spawned workers, defaults to (number of cpus - 1) or
// fallback to 1 when require('os').cpus() is undefined
workers: 2,
// number of jobs a worker processes in parallel
// defaults to 20
workerParallelJobs: 50,
// additional node.js arguments
workerNodeArgs: ['--max-old-space-size=1024'],
// Allow to respawn a dead worker pool
// respawning slows down the entire compilation
// and should be set to false for development
poolRespawn: false,
// timeout for killing the worker processes when idle
// defaults to 500 (ms)
// can be set to Infinity for watching builds to keep workers alive
poolTimeout: 2000,
// number of jobs the poll distributes to the workers
// defaults to 200
// decrease of less efficient but more fair distribution
poolParallelJobs: 50,
// name of the pool
// can be used to create different pools with elsewise identical options
name: 'my-pool',
},
},
// your expensive loader (e.g babel-loader)
];
prewarming
To prevent the high delay when booting workers it possible to warmup the worker pool.
This boots the max number of workers in the pool and loads specified modules into the node.js module cache.
const threadLoader = require('thread-loader');
threadLoader.warmup(
{
// pool options, like passed to loader options
// must match loader options to boot the correct pool
},
[
// modules to load
// can be any module, i. e.
'babel-loader',
'babel-preset-es2015',
'sass-loader',
],
);
Please take a moment to read our contributing guidelines if you haven't yet done so.
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
yarn add -D val-loader
pnpm add -D val-loader
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.
executableFile
Type:
type executableFile = 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:
type code = string | Buffer;
Default: undefined
Required
Code passed along to webpack or the next loader that will replace the module.
sourceMap
Type:
type sourceMap = object;
Default: undefined
A source map passed along to webpack or the next loader.
ast
Type:
type ast = 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:
type dependencies = 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:
type contextDependencies = 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:
type buildDependencies = 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:
type cacheable = 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.
Webpack enables use of loaders to preprocess files. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js.
Loaders are activated by using loadername!
prefixes in require()
statements, or are automatically applied via regex from your webpack configuration – see configuration.
val-loader
Executes code as module and consider exports as JS coderef-loader
Create dependencies between any files manuallycson-loader
Loads and transpiles a CSON filebabel-loader
Loads ES2015+ code and transpiles to ES5 using Babelesbuild-loader
Loads ES2015+ code and transpiles to ES6+ using esbuildbuble-loader
Loads ES2015+ code and transpiles to ES5 using Bublétraceur-loader
Loads ES2015+ code and transpiles to ES5 using Traceurts-loader
Loads TypeScript 2.0+ like JavaScriptcoffee-loader
Loads CoffeeScript like JavaScriptfengari-loader
Loads Lua code using fengarielm-webpack-loader
Loads Elm like JavaScripthtml-loader
Exports HTML as string, require references to static resourcespug-loader
Loads Pug and Jade templates and returns a functionmarkdown-loader
Compiles Markdown to HTMLreact-markdown-loader
Compiles Markdown to a React Component using the markdown-parse parserposthtml-loader
Loads and transforms a HTML file using PostHTMLhandlebars-loader
Compiles Handlebars to HTMLmarkup-inline-loader
Inline SVG/MathML files to HTML. It’s useful when applying icon font or applying CSS animation to SVG.twig-loader
Compiles Twig templates and returns a functionremark-loader
Load markdown through remark
with built-in image resolutionstyle-loader
Add exports of a module as style to DOMcss-loader
Loads CSS file with resolved imports and returns CSS codeless-loader
Loads and compiles a LESS filesass-loader
Loads and compiles a SASS/SCSS filepostcss-loader
Loads and transforms a CSS/SSS file using PostCSSstylus-loader
Loads and compiles a Stylus filevue-loader
Loads and compiles Vue Componentsangular2-template-loader
Loads and compiles Angular ComponentsFor more third-party loaders, see the list from awesome-webpack.