Printable
babel-loader
This README is for babel-loader v8/v9/v10 with Babel v7 If you are using legacy Babel v6, see the 7.x branch docs
This package allows transpiling JavaScript files using Babel together with webpack or Rspack.
Note: Issues with the output should be reported on the Babel Issues tracker.
Install
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 10.x ^5.61.0 ^7.12.0 || ^8.0.0-alpha ^18.20.0 || ^20.10.0 || >=22.0.0`
npm install -D babel-loader @babel/core @babel/preset-env webpackUsage
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']
]
}
}
}
]
}Options
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: Defaultfalse. 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 totruein options ({cacheDirectory: true}), the loader will use the default cache directory innode_modules/.cache/babel-loaderor fallback to the default OS temporary file directory if nonode_modulesfolder could be found in any root directory. -
cacheIdentifier: Default is a string composed by the@babel/core's version and thebabel-loader's version. The final cache id will be determined by the input file path, the merged Babel config viaBabel.loadPartialConfigAsyncand thecacheIdentifier. The merged Babel config will be determined by thebabel.config.jsor.babelrcfile if they exist, or the value of the environment variableBABEL_ENVandNODE_ENV.cacheIdentifiercan be set to a custom value to force cache busting if the identifier changes. -
cacheCompression: Defaulttrue. When set, each Babel transform output will be compressed with Gzip. If you want to opt-out of cache compression, set it tofalse-- your project may benefit from this if it transpiles thousands of files. -
customize: Defaultnull. The path of a module that exports acustomcallback 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.customto create a wrapper loader. Only use this if you must continue usingbabel-loaderdirectly, 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 tocontext.myMetadataPluginwithin your webpack plugin's hooks & that function will be called withmetadata. Seehttps://github.com/babel/babel-loader/main/test/metadata.test.jsfor an example.
Troubleshooting
Enable debug mode logging
Specify the webpack option stats.loggingDebug to output verbose debug logs.
// webpack.config.js
module.exports = {
// ...
stats: {
loggingDebug: ["babel-loader"]
}
}babel-loader is slow!
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.
Some files in my node_modules are not transpiled for IE 11
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 is injecting helpers into each file and bloating my code!
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']
}
}
}
]NOTE: transform-runtime & custom polyfills (e.g. Promise library)
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');The Node.js API for 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',
}Exclude libraries that should not be transpiled
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"
]
}
}Top level function (IIFE) is still arrow (on Webpack 5)
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
},
},
};Customize config based on webpack target
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" }
}
]
]
}
}Customized Loader
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.
Example
// 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.
License
coffee-loader
Compile CoffeeScript to JavaScript.
Getting Started
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 loader to your webpack.config.js. 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";Finally, run webpack using the method you normally use (e.g., via CLI or an npm script).
Options
Type: Object
Default: { bare: true }
You can find all available CoffeeScript options here.
For documentation on the transpile option, see this section.
[!NOTE]
The
sourceMapoption takes a value from thecompiler.devtoolvalue by default.
[!NOTE]
The
filenameoption takes a value from webpack loader API, but it's value will be ignored.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.coffee$/,
loader: "coffee-loader",
options: {
bare: false,
transpile: {
presets: ["@babel/env"],
},
},
},
],
},
};Examples
CoffeeScript and Babel
From CoffeeScript 2 documentation:
[!NOTE]
CoffeeScript 2 generates JavaScript using 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, modern JavaScript needs to be converted into an older JavaScript that will run in older versions of Node or older browsers; for example:
{ a } = objintoa = obj.a. This conversion is done using 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"],
},
},
},
],
},
};Literate CoffeeScript
To use Literate CoffeeScript you should setup:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.coffee$/,
loader: "coffee-loader",
options: {
literate: true,
},
},
],
},
};Contributing
Please take a moment to read our contributing guidelines if you haven't yet done so.
License
css-loader
The css-loader interprets @import and url() like import/require() and resolves them.
Getting Started
[!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 loader to your webpack configuration. 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"],
},
],
},
};Finally, run webpack using the method you normally use (e.g., via CLI or an npm script).
If you need to extract CSS into a separate file (i.e. do not store CSS in a JS module), consider using the recommend example.
Options
url
Type:
type url =
| boolean
| {
filter: (url: string, resourcePath: string) => boolean;
};Default: true
Enables or disables handling the CSS functions url and image-set.
- If set to
false,css-loaderwill not parse any paths specified inurlorimage-set. - You can also pass a function to control this behavior dynamically based on the asset path.
As of version 4.0.0, absolute paths are resolved 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 (including resolve.modules) or an 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
Allows filtering of url() values.
Any 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(url)) {
return false;
}
return true;
},
},
},
},
],
},
};import
Type:
type importFn =
| boolean
| {
filter: (
url: string,
media: string,
resourcePath: string,
supports?: string,
layer?: string,
) => boolean;
};Default: true
Allows you to enable or disable handling of @import at-rules.
Controls how @import statements are resolved.
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) or an 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
Allows filtering of @import.
Any 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 you to enable or disable CSS Modules or ICSS and configure them:
undefined: Enables CSS modules for all files matching/\.module\.\w+$/i.test(filename)or/\.icss\.\w+$/i.test(filename)regexp.true: Enables CSS modules for all files.false: Disables CSS Modules for all files.string: Disables CSS Modules for all files and set themodeoption (see mode for details).object: Enables CSS modules for all files unless themodules.autooption is provided. otherwise themodules.autooption will determine whether if it is CSS Modules or not (see auto for more details).
The modules option enables/disables the CSS Modules specification and configures its behavior.
Setting modules: false can improve performance because we avoid parsing CSS Modules features, this is useful for developers using use vanilla CSS or other technologies.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: true,
},
},
],
},
};Features
Scope
- Using
localvalue requires you to specify:globalclasses. - Using
globalvalue requires you to specify:localclasses. - Using
purevalue requires selectors must contain at least one local class or ID.
You can find more information on scoping module here.
With CSS Modules, styles are scoped locally, preventing conflicts with global styles.
Use :local(.className) to declare a className in the local scope. The local identifiers are exported by the module.
- With
:local(without parentheses) local mode can be switchedonfor this selector. - The
:global(.className)notation can be used to declare an explicit global selector. - With
:global(without parentheses) global mode can be switchedonfor this selector.
The loader replaces local selectors with unique, scoped 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;
}Output (example):
._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 naming is recommended for local selectors, as it simplifies usage in imported JS modules.
Although you can use :local(#someId), but this is not recommended. Prefer classes instead of IDs for modular styling.
Composing
When declaring a local class name, you can compose it from one or more other local class names.
:local(.className) {
background: red;
color: yellow;
}
:local(.subClass) {
composes: className;
background: blue;
}This does not alter the final CSS output, but the generated subClass will include both class names in its export.
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 class names from another module.
[!NOTE]
It is highly recommended to include file extensions 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 following a naming convention:
v-prefix for valuess-prefix for selectorsm-prefix 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 configure its behavior through options.
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 or ICSS based on the file name, query or fragment when modules option is an object.
Possible values:
undefined: Enables CSS modules for all files.true: Enables CSS modules for files matching/\.module\.\w+$/i.test(filename)and/\.icss\.\w+$/i.test(filename)regexp.false: Disables CSS Modules for all files.RegExp: Enables CSS modules for all files matching/RegExp/i.test(filename)regexp.function: Enables CSS Modules for files based on the file name satisfying your filter function check.
boolean
Possible values:
true: Enables CSS modules or Interoperable CSS (ICSS) format, sets themodules.modeoption tolocalvalue for all files which satisfy/\.module(s)?\.\w+$/i.test(filename)condition or sets themodules.modeoption toicssvalue for all files which satisfy/\.icss\.\w+$/i.test(filename)condition.false: Disables CSS modules or ICSS format based on filename for all files.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
auto: true,
},
},
},
],
},
};RegExp
Enables 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
Enables 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, andpurehandlesclassandidscoping and@valuevalues. - The
icsswill only compile the low levelInteroperable CSS (ICSS)format for declaring:importand:exportdependencies 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 setting 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:
- webpack template strings,
- output.hashDigest,
- output.hashDigestLength,
- output.hashFunction,
- output.hashSalt.
Supported template strings:
[name]the basename of the resource[folder]the folder the resource relative to thecompiler.contextoption ormodules.localIdentContextoption.[path]the path of the resource relative to thecompiler.contextoption ormodules.localIdentContextoption.[file]- filename and path.[ext]- extension with leading..[hash]- the hash of the string, generated based onlocalIdentHashSalt,localIdentHashFunction,localIdentHashDigest,localIdentHashDigestLength,localIdentContext,resourcePathandexportName[<hashFunction>:hash:<hashDigest>:<hashDigestLength>]- hash with hash settings.[local]- original class.
Recommendations:
- Use
'[path][name]__[local]'for development - Use
'[hash:base64]'for production
The [local] placeholder contains original class.
Note: all reserved characters (<>:"/\|?*) 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 redefining the 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 your custom function returns null or undefined, the built-in generator is used as a fallback.
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, namedExport defaults to true ; otherwise, it defaults to false.
Enables or disables ES modules named export for locals.
[!WARNING]
The
defaultclass name cannot be used directly whennamedExportistruebecausedefaultis a reserved keyword in ECMAScript modules. It is automatically renamed to_default.
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 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.
See 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(class names converted to camelCase, original name removed).
[!WARNING]
Names of locals are converted to camelCase when the named export is
false, i.e. theexportLocalsConventionoption hascamelCaseOnlyvalue 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 camelCased, but the original class name will not to be removed from the locals. |
'camel-case-only' | string | Class names will be camelCased, and original class name will be removed from the locals. |
'dashes' | string | Only dashes in class names will be camelCased |
'dashes-only' | string | Dashes in class names will be camelCased, 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; it 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 linkingimportsandexports, 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 file 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 sets up the 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 @imported 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 values.
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 CommonJS module 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).
The default value is 'array', i.e. loader exports an array of modules with a 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-loaderormini-css-extract-pluginwith this value.The
esModuleoption should be enabled if you want to use it withCSS modules. By default for locals named export will be used.
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]
@importrules not yet allowed, more information
[!WARNING]
You don't need
style-loaderanymore, please remove it.
[!WARNING]
The
esModuleoption should be enabled if you want to use it withCSS modules. By default for locals named export will be used.
[!WARNING]
Source maps are not currently supported in
Chromedue to a 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
},
},
],
},
],
},
],
},
};Examples
Recommend
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-loaderandmini-css-extract-plugintogether.
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()]),
};Disable URL resolving using the /* webpackIgnore: true */ comment
With 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
);
}Assets
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",
},
],
},
};Extract
For production builds it's recommended to extract the CSS from your bundle to enable 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.
Pure CSS, CSS Modules and PostCSS
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",
},
],
},
};Resolve unresolved URLs using an alias
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",
),
},
},
};Named export with custom export names
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: {
namedExport: true,
exportLocalsConvention: function (name) {
return name.replace(/-/g, "_");
},
},
},
},
],
},
};Separating Interoperable CSS-only and CSS Module features
The following setup is an example of allowing Interoperable CSS features only (such as :import and :export) without using further CSS Module functionality by setting the mode option for all files that do not match the *.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}`;
Contributing
We welcome all contributions!
If you are new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
License
exports-loader
Allows you to set up exports using module.exports or export for source files.
Useful when a source file does not contain exports or when something is not exported.
For more information on compatibility issues, refer to the Shimming guide in the official documentation.
[!WARNING]
By default, the loader generates exports using ES module syntax.
[!WARNING]
Be careful: modifying existing exports (
export,module.exports, orexports) or adding new exports can lead to errors.
Getting Started
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
Inline
The | or %20 (space) allow to separate the syntax, name and alias of export.
The documentation and syntax examples can be read here.
[!WARNING]
%20represents a space in a query string because spaces are not allowed 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 {
myFunction,
myVariable,
} 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");Descriptions of string values can be found in the documentation below.
Using Configuration
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",
},
},
],
},
};Finally, run webpack using the method you normally use (e.g., via CLI or an npm script).
Options
| 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) -- if
typeismodule- can bedefaultandnamed, - if
typeiscommonjs- can besingleandmultiple
- if
-
[name]- name of an exported value (required) -
[alias]- alias of an exported value (may be omitted)
Examples:
[Foo]- generatesexport { Foo };.[default Foo]- generatesexport default Foo;.[named Foo]- generatesexport { Foo };.[named Foo FooA]- generatesexport { Foo as FooA };.[single Foo]- generatesmodule.exports = Foo;.[multiple Foo]- generatesmodule.exports = { Foo };.[multiple Foo FooA]- generatesmodule.exports = { 'FooA': Foo };.[named [name] [name]Alias]- generates ES module named exports and exports a value equal to the filename under other name., forsingle.jsit will besingleandsingleAlias, generatesexport { single as singleAlias };.
[!WARNING]
You need to set
type: "commonjs"to usesingleormultiplesyntaxes.
[!WARNING]
Aliases can't be used together with
defaultorsinglesyntaxes.
Examples
ES Module Default Export
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;ES Module Named Exports
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 };CommonJS Single Export
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;CommonJS Multiple Exports
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 bedefaultornamedfor themoduletype (ES modulesmodule format), andsingleormultiplefor thecommonjstype (CommonJSmodule format) (may be omitted)name- name of an exported value (required)alias- alias of an exported value (may be omitted)
Examples
ES Module Default Export
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;ES Module Named Exports
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 };CommonJS Single Export
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;CommonJS Multiple Exports
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 both
singleandmultiplesyntaxes together due to CommonJS format limitations.
[!WARNING]
Not possible to use multiple
defaultvalues due to ES module format limitations.
[!WARNING]
Not possible to use multiple
singlevalues due to CommonJS format limitations.
Examples
CommonJS Multiple Exports
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 = { Bar, BazA: Bar, Foo };ES Module Default Export And Named Exports Together
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 };Named Exports
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 };Contributing
We welcome all contributions!
If you're new here, please take a moment to review our contributing guidelines.
License
expose-loader
The expose-loader loader allows to expose a module (either in whole or in part) to global object (self, window and global).
For compatibility tips and examples, check out Shimming guide in the official documentation.
Getting Started
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.
Inline
The | or %20 (space) allow to separate the globalName, moduleLocalName and override of expose.
The documentation and syntax examples can be read here.
[!WARNING]
%20represents aspacein a query string because spaces are not allowed 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`Using Configuration
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 that returns the absolute path of 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.
Finally, run webpack using the method you normally use (e.g., via CLI or an npm script).
Options
| 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 | string[];
moduleLocalName?: string;
override?: boolean;
}
| (
| string
| {
globalName: string | 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 on the global object, for examplewindow.$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 | 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 browsers, 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",
},
},
],
},
};Examples
Expose a local module
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`
},
},
],
},
};Contributing
We welcome all contributions!
If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
License
html-loader
Exports HTML as string. HTML is minimized when the compiler demands.
Getting Started
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 loader to your webpack configuration. For example:
file.js
import html from "./file.html";webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: "html-loader",
},
],
},
};Options
sources
Type:
type sources =
| boolean
| {
list?: {
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:
- The
srcattribute of theaudiotag - The
srcattribute of theembedtag - The
srcattribute of theimgtag - The
srcsetattribute of theimgtag - The
srcattribute of theinputtag - The
dataattribute of theobjecttag - The
srcattribute of thescripttag - The
hrefattribute of thescripttag - The
xlink:hrefattribute of thescripttag - The
srcattribute of thesourcetag - The
srcsetattribute of thesourcetag - The
srcattribute of thetracktag - The
posterattribute of thevideotag - The
srcattribute of thevideotag - The
xlink:hrefattribute of theimagetag - The
hrefattribute of theimagetag - The
xlink:hrefattribute of theusetag - The
hrefattribute of theusetag - The
hrefattribute of thelinktag when therelattribute containsstylesheet,icon,shortcut icon,mask-icon,apple-touch-icon,apple-touch-icon-precomposed,apple-touch-startup-image,manifest,prefetch,preloador when theitempropattribute isimage,logo,screenshot,thumbnailurl,contenturl,downloadurl,duringmedia,embedurl,installurl,layoutimage - The
imagesrcsetattribute of thelinktag when therelattribute containsstylesheet,icon,shortcut icon,mask-icon,apple-touch-icon,apple-touch-icon-precomposed,apple-touch-startup-image,manifest,prefetch,preload - The
contentattribute of themetatag when thenameattribute ismsapplication-tileimage,msapplication-square70x70logo,msapplication-square150x150logo,msapplication-wide310x150logo,msapplication-square310x310logo,msapplication-config,twitter:imageor when thepropertyattribute isog:image,og:image:url,og:image:secure_url,og:audio,og:audio:secure_url,og:video,og:video:secure_url,vk:imageor when theitempropattribute isimage,logo,screenshot,thumbnailurl,contenturl,downloadurl,duringmedia,embedurl,installurl,layoutimage - The
icon-urivalue component incontentattribute of themetatag when thenameattribute ismsapplication-task
boolean
- true: Enables processing of all default tags and attributes
- false: Disables processing entirely
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 = {
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
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
tagoption 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 plain #text, so processing of content inside these tags will is ignored during processing.
In order to enable processing inside <noscript> for content recognition by the parser as #AST, set this option 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 by the loader.
[!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
.replaceAll("<%=", isTemplateLiteralSupported ? "${" : '" +')
.replaceAll("%>", 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
.replaceAll("<%=", isTemplateLiteralSupported ? "${" : '" +')
.replaceAll("%>", 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
Use this option to enable or customize HTML minimization with html-loader.
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.config.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.
If you want to generate CommonJS modules instead (e.g., module.exports =), set:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: "html-loader",
options: {
esModule: false,
},
},
],
},
};Examples
Disable URL resolving using the <!-- webpackIgnore: true --> comment
Use the <!-- webpackIgnore: true --> comment to prevent html-loader from processing URLs for the next HTML tag. This is useful when you don’t want Webpack to handle asset imports automatically.
<!-- 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" />roots
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 resolvedCDN
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,..." />'Process script and link tags
script.file.js
console.log(document);style.file.css
a {
color: red;
}file.html
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Title of the document</title>
<link rel="stylesheet" type="text/css" href="./style.file.css" />
</head>
<body>
Content of the document......
<script src="./script.file.js"></script>
</body>
</html>webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/,
type: "asset/resource",
generator: {
filename: "[name][ext]",
},
},
{
test: /\.html$/i,
use: ["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",
},
],
},
};Templating
You can use any templating engine by leveraging the preprocessor option in html-loader. The preprocessor function receives the file content and the loader context, allowing you to transform the HTML before it’s processed by webpack.
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;
},
},
},
],
},
};This setup will transform the file.hbs template using Handlebars before passing the result to html-loader.
PostHTML
You can use PostHTML to transform HTML before it's processed, without needing additional loaders. This is useful for tasks like converting image formats, adding attributes, or restructuring markup.
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;
},
},
},
],
},
};Export into HTML files
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"],
},
],
},
};Contributing
We welcome all contributions! If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
License
imports-loader
The imports loader allows you to use modules that depend on specific global variables.
This is especially useful for third-party modules that rely on global variables like $ or where this is expected to be 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, see the official webpack documentation on Shimming.
[!WARNING]
By default, this loader generates ES module named syntax.
[!WARNING]
Be careful, existing imports (
import/require) in the original code and importing new values can cause failure.
Getting Started
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.
Inline
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]
%20represents aspacein 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
// ...Using Configuration
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 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_short } from "lib_3";
import * as my_namespace from "lib_4";
import "lib_5";Finally, run webpack using the method you normally use (e.g., via CLI or an npm script).
Options
type
Type:
type type = string;Default: module
Defines the format of generated exports.
Possible values:
commonjs(CommonJS module syntax)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:
const 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;
}
| (
| 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):- if
typeismodule- can bedefault,named,namespaceorside-effects, the default value isdefault. - if
typeiscommonjs- can besingle,multipleorpure, the default value issingle.
- if
-
[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]- generatesimport Foo from "Foo";.[default Foo]- generatesimport Foo from "Foo";.[default ./my-lib Foo]- generatesimport Foo from "./my-lib";.[named Foo FooA]- generatesimport { FooA } from "Foo";.[named Foo FooA Bar]- generatesimport { FooA as Bar } from "Foo";.[namespace Foo FooA]- generatesimport * as FooA from "Foo";.[side-effects Foo]- generatesimport "Foo";.
If type commonjs:
[Foo]- generatesconst Foo = require("Foo");.[single Foo]- generatesconst Foo = require("Foo");.[single ./my-lib Foo]- generatesconst Foo = require("./my-lib");.[multiple Foo FooA Bar]- generatesconst { FooA: Bar } = require("Foo");.[pure Foo]- generatesrequire("Foo");.
[!WARNING]
You need to set
type: "commonjs"to usesingle,multipleandpuresyntaxes.
[!WARNING]
Aliases can't be used together with
default,namespace,side-effects,singleandpuresyntaxes.
Examples
ES Module Default Import
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
// ...CommonJS Single Import
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:
const myName = require("lib");
// ...
// Code
// ...object
Allows to use an object to describe an import.
Properties:
-
syntax:- if
typeismodule- can bedefault,named,namespaceorside-effects - if
typeiscommonjs- can besingle,multipleorpure
- if
-
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,singleandpuresyntaxes.
Examples
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 either a string or an object.
Examples
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> | 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). It is intended for legacy or non-ESM compatible code.
boolean
Wraps the code in an IIFE (Immediately Invoked Function Expression) with default context.
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
Passes a custom thisArg to the .call() context.
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(globalThis);object
Allows advanced control: specify the this context and custom arguments passed into the IIFE
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(globalThis, myVariable, myOtherVariable);object with different parameter names
Allows remapping argument names in the function signature using a key-value 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: "var1",
myOtherVariable: "var2",
},
},
},
},
],
},
],
},
};Generate output:
import $ from "jquery";
(function (var1, var2) {
// ...
// Code
// ...
}).call(globalThis, myVariable, myOtherVariable);additionalCode
Type:
type additionalCode = string;Default: undefined
Adds custom code as a preamble before the module's code.
Examples
Define custom variable
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";
const myVariable = false;
// ...
// Code
// ...Disable AMD Import Syntax
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";
const define = false; /* Disable AMD for misbehaving libraries */
// ...
// Code
// ...Contributing
We welcome contributions! If you’re interested in helping improve this loader, please take a moment to read our contributing guidelines.
License
less-loader
A Less loader for webpack that compiles Less files into CSS.
Getting Started
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 configuration. For example:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
// compiles Less to CSS
"style-loader",
"css-loader",
"less-loader",
],
},
],
},
};Finally, run webpack using the method you normally use (e.g., via CLI or an npm script).
Options
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 directly 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 Less options dynamically based on 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 or 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 | "only";Default: true
Enables or 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 both 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
Example using a Less instance:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
implementation: require("less"),
},
},
],
},
],
},
};string
Example using a resolved Less module path:
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 treated as webpack warnings and errors, instead of being logged silently.
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(or error), and can break the build if configured accordingly.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
lessLogAsWarnOrErr: true,
},
},
],
},
],
},
};Examples
Normal usage
Chain the less-loader with css-loader and 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.
Source maps
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.
In production
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, improving performance and cacheability.
Imports
First we try to use built-in less resolve logic, then webpack resolve logic.
Webpack Resolver
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 ~ prefix (e.g., @import "~bootstrap/less/bootstrap";) 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"],
},
},
},
};Less Resolver
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")],
},
},
},
],
},
],
},
};Plugins
In order to use Less 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 a custom plugin can be done using the
pluginManager.webpackLoaderContextproperty.
module.exports = {
install(less, pluginManager, functions) {
functions.add(
"pi",
() =>
// Loader context is available in `pluginManager.webpackLoaderContext`
Math.PI,
);
},
};Extracting style sheets
Bundling CSS with webpack has some nice advantages like referencing images and fonts with hashed urls or Hot Module Replacement(HMR) 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)
CSS modules gotcha
There is a known problem when using Less with CSS modules regarding relative file paths in url(...) statements.
See this issue for an explanation.
Contributing
We welcome all contributions! If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
License
postcss-loader
A loader to process CSS using PostCSS.
Getting Started
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 loader to your webpack configuration. For example:
In the following configuration the plugin
postcss-preset-envis 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"],
},
],
},
};Finally, run webpack using the method you normally use (e.g., via CLI or an npm script).
Options
execute
Type:
type execute = boolean;Default: undefined
Enable PostCSS parser support for 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/postcss-loader/main/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 you 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 instead.
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 you 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.
Config Files
The loader will search up the directory tree for configuration in the following places:
- A
postcssproperty inpackage.json - A
.postcssrcfile in JSON or YAML format - A
.postcssrc.json,.postcssrc.yaml,.postcssrc.yml,.postcssrc.js, or.postcssrc.cjsfile - A
postcss.config.jsorpostcss.config.cjsCommonJS module exporting an object (recommended)
Examples of Config Files
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": {},
},
};Config Cascade
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 postcss-loader 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 } },
},
],
},
};String
Allows to specify the path to the config file.
webpack.config.js
const path = require("node: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" },
],
},
],
},
};String
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" },
],
},
],
},
};Examples
SugarSS
SugarSS is a whitespace-based syntax for PostCSS.
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" } },
},
],
},
],
},
};Autoprefixer
You'll need to install autoprefixer:
npm install --save-dev autoprefixer
Automatically 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",
{
// Autoprefixer options (optional)
},
],
],
},
},
},
],
},
],
},
};[!WARNING]
postcss-preset-envincludesautoprefixer, so adding it separately is not necessary if you already use the preset. More information
PostCSS Preset Env
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
},
],
],
},
},
},
],
},
],
},
};CSS Modules
What are
CSS Modules? Please read here.
No additional options required on the postcss-loader side to support CSS Modules.
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",
],
},
],
},
};CSS-in-JS and postcss-js
To process styles written in JavaScript, you can use postcss-js as the parser.
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-exportsto your configuration.- You need to have only one default export per style module.
Extract CSS
To extract CSS into separate files, use 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",
}),
],
};💡 Use this setup to extract and cache CSS in production while keeping fast style injection during development.
Emit assets
To emit an 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 equalasset)file- file name (require)content- file content (require)sourceMap- sourceMapinfo- asset info
webpack.config.js
const postcssCustomPlugin = (opts = {}) => ({
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()] } },
},
],
},
],
},
};ℹ️ This allows your plugin to generate additional files as part of the build process, and Webpack will handle them like any other emitted asset.
Add dependencies, contextDependencies, buildDependencies, missingDependencies
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:
- (Recommended). The plugin may emit messages in
result.messages.
The message should contain the following fields:
type=dependency- Message type (require, should be equaldependency,context-dependency,build-dependencyormissing-dependency)file- absolute file path (require)
webpack.config.js
const path = require("node:path");
const postcssCustomPlugin = (opts = {}) => ({
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()] } },
},
],
},
],
},
};💡 You can use ready-made plugin postcss-add-dependencies to simplify this process.
- Pass
loaderContextin plugin (for advanced setups).
webpack.config.js
const path = require("node: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"),
},
},
},
],
},
],
},
};⚠️ Use this approach only when managing dependencies via custom PostCSS configurations with dynamic imports or external files.
postcss.config.js
Pass the webpackLoaderContext through the PostCSS api object:
module.exports = (api) => ({
plugins: [
require("path/to/postcssCustomPlugin.js")({
loaderContext: api.webpackLoaderContext,
}),
],
});postcssCustomPlugin.js
Register a file dependency using loaderContext.addDependency:
const path = require("node:path");
const postcssCustomPlugin = (opts = {}) => ({
postcssPlugin: "postcss-custom-plugin",
Once: (root, { result }) => {
opts.loaderContext.addDependency(
path.resolve(__dirname, "path", "to", "file"),
);
},
});
postcssCustomPlugin.postcss = true;
module.exports = postcssCustomPlugin;✅ This method is ideal when you want to dynamically declare dependencies without relying on result.messages, especially in more complex setups or shared plugin configurations.
Contributing
We welcome all contributions! If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
License
remark-loader
Remark Loader
Load markdown through remark.
Usage
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.
Options
remarkOptions
Remark options
Type:
interface remarkOptions {
plugins: (string | any[])[];
settings: object;
data: object;
}plugins
Allows to connect remark plugins
Type:
type plugins = (string | any[])[];Default: []
Allows to connect remark plugins
string
webpack.config.js
import RemarkFrontmatter from "remark-frontmatter";
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
remarkOptions: {
plugins: [RemarkFrontmatter],
},
},
},
],
},
],
},
};array
If need to specify options for the plugin, you can pass the plugin using an array, where the second argument will be the options.
webpack.config.js
import RemarkBookmarks from "remark-bookmarks";
import RemarkFrontmatter from "remark-frontmatter";
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
remarkOptions: {
plugins: [
RemarkFrontmatter,
[
RemarkBookmarks,
{
bookmarks: {
npm: "https://npmjs.com/package/remark-bookmarks",
},
},
],
],
},
},
},
],
},
],
},
};settings
Remark settings
Type:
type settings = object;Default: undefined
Pass remark-stringify options and remark-parse options to remark.
webpack.config.js
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
options: {
remarkOptions: {
settings: {
bullet: "+",
listItemIndent: "1",
},
},
},
},
],
},
],
},
};data
Information available to all plugins
Type:
type data = object;Default: undefined
Configure remark with information available to all plugins.
This 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",
},
},
},
},
],
},
],
},
};removeFrontMatter
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],
},
},
},
],
},
],
},
};Inspiration
This project was inspired the following open source work:
Examples
Markdown to HTML
To get HTML, you need to add remark-html to the remark plugins and add html-loader to your webpack.config.js
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],
},
},
},
],
},
],
},
};Markdown to Markdown
index.js
import md from "markdown-file.md";
console.log(md);webpack.config.js
module.exports = {
// ...
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: "remark-loader",
},
],
},
],
},
};Contributing
We welcome all contributions! If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
License
sass-loader
Loads a Sass/SCSS file and compiles it to CSS.
Getting Started
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 with 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 (e.g., via CLI or an npm script).
The style (new API, by default since 16 version) and outputStyle (old API) options in production mode
For production mode, the style (new API, by default since 16 version) and outputStyle (old API) options default to compressed unless otherwise specified in sassOptions.
Resolving import and use at-rules
Webpack 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";
Problems with url(...)
Since Sass implementations don't provide url rewriting, all linked assets must be relative to the output.
- If you pass the generated CSS on to the
css-loader, all URLs must be relative to the entry-file (e.g.main.scss). - If you're just generating CSS without passing it to the
css-loader, URLs 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:
-
Add the missing URL rewriting using the resolve-url-loader. Place it before
sass-loaderin the loader chain. -
Library authors usually provide a variable to modify the asset path. bootstrap-sass for example, has an
$icon-font-path.
Options
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 uses the sass (dart-sass) implementation:
package.json
{
"devDependencies": {
"sass-loader": "^7.2.0",
"sass": "^1.22.10"
}
}Example where the sass-loader uses the node-sass implementation:
package.json
{
"devDependencies": {
"sass-loader": "^7.2.0",
"node-sass": "^5.0.0"
}
}Example where the sass-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
optionalDependenciesmeans thatsass-loadercan fallback tosasswhen running on an operating system not supported bysass-embedded
Be aware of the order that sass-loader will resolve the implementation:
sass-embeddedsassnode-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
charsetoption istrueby default fordart-sass. We strongly discourage setting this tofalsebecause webpack doesn't support files other thanutf-8.
[!NOTE]
The
syntax(new API, by default since 16 version) andindentedSyntax(old API) option isscssfor thescssextension,indentedfor thesassextension, andcssfor thecssextension.
[!NOTE]
Options such as
dataandfileare 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-loadersets these automatically when thesourceMapoption istrue.
[!NOTE]
Access to the loader context inside the custom importer can be done using the
this.webpackLoaderContextproperty.
There is a slight difference between the options for sass (dart-sass) and node-sass.
Please consult their respective documentation before using them:
- Dart Sass documentation for all available
sassoptions. - Sass Embedded documentation for all available
sassoptions. - Node Sass documentation for all available
node-sassoptions.
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) fromsassOptionswill 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-sasscan output invalid source maps (this is anode-sassbug).In order to avoid this, you can try to update
node-sassto the latest version, or you can try to set withinsassOptionstheoutputStyleoption 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
Sync
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}`;
},
},
},
],
},
],
},
};Async
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 of 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-compilerandsass-embeddedtogether significantly improves performance and decreases build 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
legacyandmodernAPIs. Please look at docs to learn 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
},
},
},
],
},
],
},
};How to enable @debug output
By default, the output of @debug messages is disabled.
Add the following to webpack.config.js to enable them:
module.exports = {
stats: {
loggingDebug: ["sass-loader"],
},
// ...
};Examples
Extracts CSS into separate files
For production builds, it's recommended to extract the CSS from your bundle to enable parallel loading of CSS/JS resources.
There are four recommended ways to extract a stylesheet from a bundle:
1. mini-css-extract-plugin
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",
}),
],
};2. Asset Modules
webpack.config.js
const path = require("node:path");
module.exports = {
entry: [path.resolve(__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"],
},
],
},
};3. extract-loader (simpler, but specialized on the css-loader's output)
4. file-loader (deprecated--should only be used in webpack v4)
webpack.config.js
const path = require("node:path");
module.exports = {
entry: [path.resolve(__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)
Source maps
Enables/disables generation of source maps.
To enable CSS source maps, you'll need to pass the sourceMap option to both 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 working example.
Contributing
We welcome all contributions! If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
License
style-loader
Inject CSS into the DOM.
Getting Started
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 configuration. 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"],
},
],
},
};Security Warning
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.
Options
injectType
Type:
type injectType =
| "styleTag"
| "singletonStyleTag"
| "autoStyleTag"
| "lazyStyleTag"
| "lazySingletonStyleTag"
| "lazyAutoStyleTag"
| "linkTag";Default: styleTag
Allows you 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 the 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 set up the modules option for css-loader. For more information, consult the 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 a single <style></style> tag.
[!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 set up the modules option for css-loader. For more information, consult the 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> tags on demand.
We recommend following the .lazy.css naming convention for lazy styles and .css for basic style-loader usage (similar to other file types, i.e. .lazy.less and .less).
When you use the lazyStyleTag value, style-loader injects the styles lazily, making them useable on-demand via style.use() / style.unuse().
⚠️ Behavior is undefined when
unuseis 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 set up the modules option for css-loader. For more information, consult the 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 a single <style></style> tag 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 use the lazySingletonStyleTag value, 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
unuseis 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 set up the modules option for css-loader. For more information, consult the 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 the 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 you to setup custom query selector where styles are injected 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 you to setup an absolute path to custom function that allows to override the 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, etc. We recommend usingbabel-loaderto support the latest ECMA features.
[!WARNING]
Do not forget that some DOM methods may not be available in older browsers. We recommended using only DOM core level 2 properties, but it depends on which 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",
],
},
],
},
};New <style>/<link> elements will be inserted at the bottom of the body tag.
Examples:
Insert styles at top of head tag:
insert-function.js
function insertAtTop(element) {
const parent = document.querySelector("head");
const 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"),
},
},
"css-loader",
],
},
],
},
};You can pass any parameters to style.use(options) and this value will be passed to the insert and styleTagTransform functions.
insert-function.js
function insertIntoTarget(element, options) {
const 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 you to setup an absolute path to a custom function that allows to override default styleTagTransform behavior.
[!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, etc. We recommend use only ECMA 5 features, but it depends on which browsers you want to support.
[!WARNING]
Do not forget that some DOM methods may not be available in older browsers. We recommended using only DOM core level 2 properties, but it depends on which 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 DllPlugins.
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 that 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, such as in the case of module concatenation and tree shaking.
You can enable a CommonJS module syntax using:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: "style-loader",
options: {
esModule: false,
},
},
],
},
};Examples
Recommended
For production builds, it's recommended to extract the CSS from your bundle to enable 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> tags and works faster.
[!WARNING]
Do not use
style-loaderandmini-css-extract-plugintogether.
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: [devMode ? [] : [new MiniCssExtractPlugin()]].flat(),
};Named export for CSS Modules
[!WARNING]
It is not allowed to use JavaScript reserved words in CSS class names.
[!WARNING]
Options
esModuleandmodules.namedExportincss-loadershould be enabled (by default forcss-loader@7it is true).
styles.css
.fooBaz {
color: red;
}
.bar {
color: blue;
}
.my-class {
color: green;
}index.js
import { bar, fooBaz, "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 an 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,
},
},
},
],
},
],
},
};Source maps
The loader automatically injects source maps when the previous loader emits 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 } },
],
},
],
},
};Nonce
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:
- Using the
attributesoption - Using the
__webpack_nonce__variable
[!WARNING]
the
attributesoption 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
Insert styles at top of head tag.
insert-function.js
function insertAtTop(element) {
const parent = document.querySelector("head");
const 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",
],
},
],
},
};Insert styles before target element
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",
],
},
],
},
};Custom Elements (Shadow DOM)
You can define custom target for your styles when using the lazyStyleTag type.
insert-function.js
function insertIntoTarget(element, options) {
const 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 into the head tag if the 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;Contributing
We welcome all contributions! If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
License
stylus-loader
A Stylus loader for webpack. Compiles Stylus files into CSS.
Getting Started
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 configuration. For example:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
loader: "stylus-loader", // compiles Styl to CSS
},
],
},
};Finally, run webpack using the method you normally use (e.g., via CLI or an npm script).
Options
stylusOptions
Type:
type stylusOptions =
| {
use: (string | ((stylusOptions: StylusOptions) => void))[];
include: string[];
import: string[];
define: any[];
includeCSS: false;
resolveURL: boolean | object;
lineNumbers: boolean;
hoistAtrules: boolean;
compress: boolean;
}
| ((loaderContext: LoaderContext) => 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 be written in 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 will simply 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, such as using 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
Sync
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}`;
},
},
},
],
},
],
},
};Async
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 = (() => typeof import("stylus")) | string;The implementation option allows you to specify which Stylus implementation to use.
It 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"),
},
},
],
},
],
},
};Examples
Normal Usage
Chain stylus-loader with the css-loader and 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
},
],
},
],
},
};Source maps
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,
},
},
],
},
],
},
};Using nib with stylus
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"],
},
},
},
],
},
],
},
};Import JSON files
Stylus does not provide resolving capabilities in the json() function.
Therefore webpack resolver does not work for .json files.
To handle this, use a 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"],
},
},
},
],
},
],
},
};In production
Usually, it's recommended to extract the style sheets into a dedicated CSS file in production using the MiniCssExtractPlugin. This way your styles are not dependent on JavaScript.
webpack resolver
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 directly from node_modules.
@import 'bootstrap-styl/bootstrap/index.styl';
Using ~ prefix is deprecated and can be removed from your code (we recommended), 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, which is different.
Webpack needs to distinguish between bootstrap and ~bootstrap, because CSS and Stylus files have no special syntax for importing relative files.
Writing @import "file" is the same as @import "./file";
Stylus resolver
If you specify the paths option, modules will be searched in the given paths.
This is the default Stylus 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")],
},
},
},
],
},
],
},
};Extracting style sheets
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)
Contributing
We welcome all contributions! If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
License
thread-loader
Runs the specified loaders in a worker pool.
Getting Started
npm install --save-dev thread-loaderor
yarn add -D thread-loaderor
pnpm add -D thread-loaderPut this loader in front of other loaders. The following loaders run in a worker pool.
Loaders running in a worker pool have limitations. Examples:
- Loaders cannot emit files.
- Loaders cannot use custom loader APIs (i.e. by plugins).
- Loaders cannot access webpack options.
Each worker is a separate Node.js process, which has an overhead of ~600ms. There is also additional overhead from inter-process communication.
Use this loader only for expensive operations!
Examples
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 pool distributes to the workers
// defaults to 200
// decrease for less efficient but more fair distribution
poolParallelJobs: 50,
// name of the pool
// can be used to create different pools with otherwise identical options
name: 'my-pool',
},
},
// your expensive loader (e.g babel-loader)
];prewarming
To prevent the high delays when booting workers, it is possible to warm up the worker pool.
This boots the max number of workers in the pool and loads the 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-env',
'sass-loader',
],
);Contributing
We welcome all contributions! If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
License
Loaders
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.
Files
ref-loaderCreate dependencies between any files manually
JSON
cson-loaderLoads and transpiles a CSON file
Transpiling
babel-loaderLoads ES2015+ code and transpiles to ES5 using Babelesbuild-loaderLoads ES2015+ code and transpiles to ES6+ using esbuildbuble-loaderLoads ES2015+ code and transpiles to ES5 using Bublétraceur-loaderLoads ES2015+ code and transpiles to ES5 using Traceurts-loaderLoads TypeScript 2.0+ like JavaScriptcoffee-loaderLoads CoffeeScript like JavaScriptfengari-loaderLoads Lua code using fengarielm-webpack-loaderLoads Elm like JavaScript
Templating
html-loaderExports HTML as string, require references to static resourcespug-loaderLoads Pug and Jade templates and returns a functionmarkdown-loaderCompiles Markdown to HTMLreact-markdown-loaderCompiles Markdown to a React Component using the markdown-parse parserposthtml-loaderLoads and transforms a HTML file using PostHTMLhandlebars-loaderCompiles Handlebars to HTMLmarkup-inline-loaderInline SVG/MathML files to HTML. It’s useful when applying icon font or applying CSS animation to SVG.twig-loaderCompiles Twig templates and returns a functionremark-loaderLoad markdown throughremarkwith built-in image resolution
Styling
style-loaderAdd exports of a module as style to DOMcss-loaderLoads CSS file with resolved imports and returns CSS codeless-loaderLoads and compiles a LESS filesass-loaderLoads and compiles a SASS/SCSS filepostcss-loaderLoads and transforms a CSS/SSS file using PostCSSstylus-loaderLoads and compiles a Stylus file
Frameworks
vue-loaderLoads and compiles Vue Componentsangular2-template-loaderLoads and compiles Angular Components
Awesome
For more third-party loaders, see the list from awesome-webpack.

