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/blob/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
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,
// Uses the built-in CSS support of webpack, i.e. `.module.less` files
// are treated as CSS modules, other files are treated as plain CSS
type: "css/auto",
// Compiles Less to CSS
use: ["less-loader"],
},
],
},
experiments: {
// Enables the built-in CSS support of webpack
css: true,
},
};[!NOTE]
The built-in CSS support of webpack requires
experiments.cssto be enabled. Alternatively you can still chain the loader withcss-loaderandstyle-loader(or themini-css-extract-plugin), see Usingcss-loaderandstyle-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,
type: "css/auto",
use: [
{
loader: "less-loader",
options: {
lessOptions: {
strictMath: true,
},
},
},
],
},
],
},
experiments: {
css: true,
},
};function
Allows setting the Less options dynamically based on the loader context.
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
type: "css/auto",
use: [
{
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"],
};
},
},
},
],
},
],
},
experiments: {
css: true,
},
};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,
type: "css/auto",
use: [
{
loader: "less-loader",
options: {
additionalData: `@env: ${process.env.NODE_ENV};`,
},
},
],
},
],
},
experiments: {
css: true,
},
};function
Sync
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
type: "css/auto",
use: [
{
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}`;
},
},
},
],
},
],
},
experiments: {
css: true,
},
};Async
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
type: "css/auto",
use: [
{
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}`;
},
},
},
],
},
],
},
experiments: {
css: true,
},
};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,
type: "css/auto",
use: [
{
loader: "less-loader",
options: {
sourceMap: true,
},
},
],
},
],
},
experiments: {
css: 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,
type: "css/auto",
use: [
{
loader: "less-loader",
options: {
webpackImporter: false,
},
},
],
},
],
},
experiments: {
css: true,
},
};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,
type: "css/auto",
use: [
{
loader: "less-loader",
options: {
implementation: require("less"),
},
},
],
},
],
},
experiments: {
css: true,
},
};string
Example using a resolved Less module path:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
type: "css/auto",
use: [
{
loader: "less-loader",
options: {
implementation: require.resolve("less"),
},
},
],
},
],
},
experiments: {
css: true,
},
};lessLogAsWarnOrErr
Type:
type lessLogAsWarnOrErr = boolean;Default: true
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 leave the default value (or 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,
type: "css/auto",
use: [
{
loader: "less-loader",
options: {
lessLogAsWarnOrErr: true,
},
},
],
},
],
},
experiments: {
css: true,
},
};Examples
Normal usage
Set the module type to css/auto and enable experiments.css to let webpack handle the generated CSS with its built-in CSS support, without any extra loaders or plugins.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
type: "css/auto", // Handles the generated CSS using the built-in CSS support of webpack
use: ["less-loader"], // Compiles Less to CSS
},
],
},
experiments: {
css: true,
},
};The css/auto module type treats *.module.less files as CSS modules and any other file as plain CSS.
Use type: "css" to always treat the file as plain CSS, or type: "css/module" to always treat it as a CSS module.
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.
Using css-loader and style-loader
The built-in CSS support of webpack is not mandatory, you can still 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
},
],
},
],
},
};Note that in this case the type and experiments.css options should not be set for this rule, and options like sourceMap have to be enabled for the css-loader too.
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,
type: "css/auto",
use: [
{
loader: "less-loader",
options: {
sourceMap: true,
},
},
],
},
],
},
experiments: {
css: 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
The built-in CSS support of webpack always extracts style sheets into dedicated files, so your styles are not dependent on JavaScript, which improves performance and cacheability.
The name of the generated files can be configured using the output.cssFilename and output.cssChunkFilename options.
When you chain the loader with css-loader and style-loader instead, it's recommended to extract the style sheets into a dedicated file in production using the MiniCssExtractPlugin.
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,
type: "css/auto",
use: ["less-loader"],
},
],
},
experiments: {
css: true,
},
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,
type: "css/auto",
use: [
{
loader: "less-loader",
options: {
lessOptions: {
paths: [path.resolve(__dirname, "node_modules")],
},
},
},
],
},
],
},
experiments: {
css: true,
},
};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.
The built-in CSS support of webpack does this out of the box: every entry point and chunk gets its own style sheet, no extra plugin required.
When you chain the loader with the css-loader instead, use the MiniCssExtractPlugin to extract a style sheet from the bundle.
CSS modules
With the built-in CSS support of webpack, *.module.less files are treated as CSS modules when the module type is css/auto, and all files are treated as CSS modules when the module type is css/module:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
type: "css/auto",
use: ["less-loader"],
},
],
},
experiments: {
css: true,
},
};index.js
import * as styles from "./style.module.less";
document.body.className = styles.box;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.
The examples below use the built-in CSS support of webpack (available in webpack
>= 5.87.0), so nocss-loaderandstyle-loaderare required. If you prefer to handle CSS usingcss-loaderandstyle-loader, keep them in the list of loaders and usepostcss-loaderbefore them.
file.js
import css from "file.css";webpack.config.js
module.exports = {
experiments: {
// Enable the built-in CSS support of webpack
css: true,
},
module: {
rules: [
{
test: /\.css$/i,
// `css/auto` treats `*.module.css` files as CSS modules and all other files as regular CSS
type: "css/auto",
use: [
{
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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.css$/i,
type: "css/auto",
use: ["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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.style.js$/,
type: "css/auto",
use: [
{
loader: "postcss-loader",
options: {
postcssOptions: { parser: "postcss-js" },
execute: true,
},
},
],
},
],
},
};postcssOptions
See the file https://github.com/webpack/postcss-loader/blob/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 the built-in CSS support of webpack (recommended).
Use postcss-loader 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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.css$/,
type: "css/auto",
use: ["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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{ loader: "postcss-loader", options: { sourceMap: true } },
{ loader: "sass-loader", options: { sourceMap: true } },
],
},
],
},
};Alternative setup:
webpack.config.js
module.exports = {
devtool: "source-map",
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [{ 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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
loader: "postcss-loader",
options: { implementation: require("postcss") },
},
{ loader: "sass-loader" },
],
},
],
},
};String
webpack.config.js
module.exports = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.sss$/i,
type: "css/auto",
use: [
{
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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.css$/i,
type: "css/auto",
use: [
{
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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.css$/i,
type: "css/auto",
use: [
{
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.
With the built-in CSS support of webpack use the css/auto module type - all *.module.css files are treated as CSS modules, other files are treated as regular CSS.
webpack.config.js
module.exports = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.css$/i,
type: "css/auto",
use: ["postcss-loader"],
},
],
},
};Use the css/module module type to treat all matched files as CSS modules, regardless of their name.
webpack.config.js
module.exports = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.css$/i,
type: "css/module",
use: ["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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.style.js$/,
type: "css/auto",
use: [
{
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
The built-in CSS support of webpack extracts CSS into separate files out of the box, no plugin is required.
Use output.cssFilename and output.cssChunkFilename to control the names of the generated files.
webpack.config.js
const isProductionMode = process.env.NODE_ENV === "production";
module.exports = {
mode: isProductionMode ? "production" : "development",
experiments: {
css: true,
},
output: {
cssFilename: isProductionMode ? "[name].[contenthash].css" : "[name].css",
},
module: {
rules: [
{
test: /\.css$/,
type: "css/auto",
use: ["postcss-loader"],
},
],
},
};💡 Use this setup to extract and cache CSS in production while keeping fast rebuilds 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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.css$/i,
type: "css/auto",
use: [
{
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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.css$/i,
type: "css/auto",
use: [
{
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 = {
experiments: {
css: true,
},
module: {
rules: [
{
test: /\.css$/i,
type: "css/auto",
use: [
{
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
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]
Webpack has built-in CSS support, so no extra loaders are required to process the CSS generated by
sass-loader- just enableexperiments.cssand set the moduletypetocss/auto.If you prefer the loader-based setup, install style-loader and css-loader via
npm i style-loader css-loaderand chain them withsass-loaderinstead.
sass-loader requires you to install either Dart Sass or Sass Embedded on your own (more documentation can be found below).
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.
Use the sass-loader with the built-in CSS support of webpack (the css/auto module type) to let webpack handle the generated CSS - it extracts styles into a separate file and injects them into the document.
Alternatively, you can 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,
// Lets webpack handle the generated CSS using its built-in CSS support,
// `css/auto` also enables CSS modules for `*.module.scss` files
type: "css/auto",
use: [
// Compiles Sass to CSS
"sass-loader",
],
},
],
},
experiments: {
// Enables the built-in CSS support of webpack
css: true,
},
};Finally run webpack via your preferred method (e.g., via CLI or an npm script).
[!NOTE]
All examples below use the built-in CSS support of webpack. If you use css-loader and style-loader (or mini-css-extract-plugin) instead, remove the
typeandexperimentsoptions and put them before thesass-loaderin theusearray:module.exports = { module: { rules: [ { test: /\.s[ac]ss$/i, use: ["style-loader", "css-loader", "sass-loader"], }, ], }, };
The style option in production mode
For production mode, the style option defaults to compressed unless otherwise specified in sassOptions.
Resolving import, use and forward at-rules
Webpack provides an advanced mechanism to resolve files.
The sass-loader uses Sass's custom importer feature to pass every @use, @import and @forward request to the webpack resolving engine, so your webpack resolve configuration applies to stylesheets, and you can load Sass modules from node_modules:
@use "bootstrap";How a request is resolved
For @use "theme" inside src/app.scss, the loader asks webpack for the following and takes the first hit:
- the partial
src/_theme.sass,src/_theme.scss,src/_theme.css src/theme.sass,src/theme.scss,src/theme.cssthemeas written, so aliases and package requests resolve
Directories resolve through their _index/index file. For @import only, the import-only files _theme.import.scss and theme.import.scss are tried before everything else.
Relative requests win over module ones, so @use "theme" behaves like @use "./theme" when both could match. Keeping both _theme.scss and theme.scss in one directory is ambiguous and Sass reports an error for it, so the order within a directory rarely matters.
What your resolve configuration controls
alias- applied to every request, and tried beforenode_modulesmodules- extra directories to look in, e.g.srcbyDependency.sass- requests are resolved withdependencyType: "sass", so this targets stylesheets onlyplugins,symlinks,rootsand the rest of the resolver options
webpack.config.js
module.exports = {
resolve: {
alias: { "@styles": path.resolve(__dirname, "src/styles") },
modules: [path.resolve(__dirname, "src"), "node_modules"],
},
};style.scss
@use "@styles/theme" as *; // resolved by `resolve.alias`
@use "abstracts" as *; // resolved by `resolve.modules` to `src/abstracts/_index.scss`Some options are fixed to match Sass's own algorithm and can't be changed through resolve: the extensions are .sass, .scss and .css (so resolve.extensions doesn't apply here), mainFiles prefer _index/index, mainFields prefer sass and style over main, and conditionNames prefer the sass and style export conditions. Your own mainFields and conditionNames are kept after those.
Packages
A package request resolves through the sass and style conditions of its exports field, falling back to the sass, style and main fields. The pkg: URL scheme is supported as well:
@use "pkg:bootstrap";When webpack can't resolve a request
The importer hands the request back to Sass, which then applies its own resolution - sassOptions.loadPaths, the SASS_PATH environment variable and any custom importer you configured.
Plain CSS files
Sass compiles @import "theme.css" to a plain CSS @import, so the loader leaves it in the output untouched - whatever handles the CSS afterwards (the built-in CSS support of webpack, css-loader, or the browser) decides what happens with it. @use "theme.css" includes the file's content instead, and is resolved like any other request:
@import "theme.css"; // stays `@import "theme.css";` in the output
@use "theme.css"; // inlines the content of the fileThe ~ prefix
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 @use as a relative path. If it cannot be resolved, then the loader will try to resolve it inside node_modules.
Prepending module paths with a ~ tells webpack to search through node_modules.
@use "~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 @use "style.scss" is the same as @use "./style.scss";
Problems with url(...)
Since Sass implementations don't provide url rewriting, all linked assets must be relative to the output.
- If webpack handles the generated CSS (i.e. the built-in CSS support or the
css-loader), all URLs must be relative to the entry-file (e.g.main.scss). - If you're just generating CSS without letting webpack handle it, 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 or sass-embedded 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 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-embeddedsass
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,
type: "css/auto",
use: [
{
loader: "sass-loader",
options: {
// Prefer `dart-sass`, even if `sass-embedded` is available
implementation: require("sass"),
},
},
],
},
],
},
experiments: {
css: true,
},
};string
For example, to use Dart Sass, you'd pass:
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
loader: "sass-loader",
options: {
// Prefer `dart-sass`, even if `sass-embedded` is available
implementation: require.resolve("sass"),
},
},
],
},
],
},
experiments: {
css: true,
},
};sassOptions
Type:
type sassOptions =
| import("sass").StringOptionsWithImporter<"async">
| ((
content: string | Buffer,
loaderContext: LoaderContext,
meta: any,
) => import("sass").StringOptionsWithImporter<"async">);Default: defaults values for Sass implementation
Options for Dart Sass or Sass Embedded implementation.
[!NOTE]
The
charsetoption istrueby default fordart-sass. We strongly discourage setting this tofalsebecause webpack doesn't support files other thanutf-8.
[!NOTE]
The
syntaxoption isscssfor thescssextension,indentedfor thesassextension, andcssfor thecssextension.
[!NOTE]
Options such as
dataandurlare unavailable and will be ignored.
ℹ We strongly discourage changing the
sourceMapoption becausesass-loadersets it automatically when thesourceMapoption istrue.
Please consult their respective documentation before using them:
- Dart Sass documentation for all available
sassoptions. - Sass Embedded documentation for all available
sass-embeddedoptions.
object
Use an object for the Sass implementation setup.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
loader: "sass-loader",
options: {
sassOptions: {
style: "compressed",
loadPaths: ["absolute/path/a", "absolute/path/b"],
},
},
},
],
},
],
},
experiments: {
css: true,
},
};function
Allows configuring the Sass implementation with different options based on the loader context.
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
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"],
};
},
},
},
],
},
],
},
experiments: {
css: true,
},
};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, thesourceMapoption fromsassOptionswill be ignored.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
loader: "sass-loader",
options: {
sourceMap: true,
},
},
],
},
],
},
experiments: {
css: true,
},
};webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
loader: "sass-loader",
options: {
sourceMap: true,
sassOptions: {
style: "compressed",
},
},
},
],
},
],
},
experiments: {
css: true,
},
};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,
type: "css/auto",
use: [
{
loader: "sass-loader",
options: {
additionalData: `$env: ${process.env.NODE_ENV};`,
},
},
],
},
],
},
experiments: {
css: true,
},
};function
Sync
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
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}`;
},
},
},
],
},
],
},
experiments: {
css: true,
},
};Async
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
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}`;
},
},
},
],
},
],
},
experiments: {
css: true,
},
};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 Sass importer documentation).
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
loader: "sass-loader",
options: {
webpackImporter: false,
},
},
],
},
],
},
experiments: {
css: true,
},
};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,
type: "css/auto",
use: [
{
loader: "sass-loader",
options: {
warnRuleAsWarning: true,
},
},
],
},
],
},
experiments: {
css: true,
},
};api
Type:
type api = "auto" | "modern" | "modern-compiler";Default: "auto" for sass (dart-sass) and sass-embedded
Allows you to switch between the modern and modern-compiler APIs. You can find more information here. The modern-compiler option enables the modern API with support for Shared Resources.
When "auto" is used, the loader picks "modern-compiler" whenever the implementation exposes initAsyncCompiler (i.e. recent versions of sass and sass-embedded) and falls back to "modern" otherwise. Combined with sass-embedded, this yields the best build performance out of the box.
[!NOTE]
Using
modern-compilerandsass-embeddedtogether significantly improves performance and decreases build time. They are now selected automatically by the default"auto"API.
[!NOTE]
The legacy Sass JS API is no longer supported. If you were using
api: "legacy", please migrate to the modern API. See the Sass JS API docs to learn how to migrate.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
loader: "sass-loader",
options: {
api: "modern-compiler",
sassOptions: {
// Your sass options
},
},
},
],
},
],
},
experiments: {
css: true,
},
};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 five recommended ways to extract a stylesheet from a bundle:
1. Built-in CSS support
Webpack emits CSS into separate files on its own, so nothing but experiments.css is required.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: ["sass-loader"],
},
],
},
output: {
// Both options are optional
cssFilename: "[name].css",
cssChunkFilename: "[id].css",
},
experiments: {
css: true,
},
};2. 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",
}),
],
};3. 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"],
},
],
},
};4. extract-loader (simpler, but specialized on the css-loader's output)
5. 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 the sass-loader (and to the css-loader too, when you use it).
webpack.config.js
module.exports = {
devtool: "source-map", // any "source-map"-like devtool is possible
module: {
rules: [
{
test: /\.s[ac]ss$/i,
type: "css/auto",
use: [
{
loader: "sass-loader",
options: {
sourceMap: true,
},
},
],
},
],
},
experiments: {
css: 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
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$/i,
// Uses the built-in CSS support of webpack, i.e. `.module.styl` files
// are treated as CSS modules, other files are treated as plain CSS
type: "css/auto",
// Compiles Stylus to CSS
use: ["stylus-loader"],
},
],
},
experiments: {
// Enables the built-in CSS support of webpack
css: true,
},
};[!NOTE]
The built-in CSS support of webpack requires
experiments.cssto be enabled. Alternatively you can still chain the loader withcss-loaderandstyle-loader(or themini-css-extract-plugin), see Usingcss-loaderandstyle-loader.
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$/i,
type: "css/auto",
use: [
{
loader: "stylus-loader",
options: {
stylusOptions: {
// eslint-disable-next-line jsdoc/no-restricted-syntax
/**
* Specify Stylus plugins to use. Plugins may be passed as
* strings instead of importing them in your Webpack config.
* @type {(string | (renderer: object) => void)[]}
* @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 {[string, string | number | boolean, boolean?] | Record<string, string | number | boolean>}
* @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 | { nocheck?: boolean, paths?: string[] }}
* @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,
},
},
},
],
},
],
},
experiments: {
css: true,
},
};function
Allows setting the options passed through to Stylus based off of the loader context.
module.exports = {
module: {
rules: [
{
test: /\.styl$/i,
type: "css/auto",
use: [
{
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"],
};
},
},
},
],
},
],
},
experiments: {
css: true,
},
};sourceMap
Type:
type sourceMap = boolean;webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/i,
type: "css/auto",
use: [
{
loader: "stylus-loader",
options: {
sourceMap: true,
},
},
],
},
],
},
experiments: {
css: 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,
type: "css/auto",
use: [
{
loader: "stylus-loader",
options: {
webpackImporter: false,
},
},
],
},
],
},
experiments: {
css: true,
},
};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$/i,
type: "css/auto",
use: [
{
loader: "stylus-loader",
options: {
additionalData: `@env: ${process.env.NODE_ENV};`,
},
},
],
},
],
},
experiments: {
css: true,
},
};function
Sync
module.exports = {
module: {
rules: [
{
test: /\.styl$/i,
type: "css/auto",
use: [
{
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}`;
},
},
},
],
},
],
},
experiments: {
css: true,
},
};Async
module.exports = {
module: {
rules: [
{
test: /\.styl$/i,
type: "css/auto",
use: [
{
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}`;
},
},
},
],
},
],
},
experiments: {
css: true,
},
};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,
type: "css/auto",
use: [
{
loader: "stylus-loader",
options: {
implementation: require("stylus"),
},
},
],
},
],
},
experiments: {
css: true,
},
};string
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/i,
type: "css/auto",
use: [
{
loader: "stylus-loader",
options: {
implementation: require.resolve("stylus"),
},
},
],
},
],
},
experiments: {
css: true,
},
};Examples
Normal Usage
Set the module type to css/auto and enable experiments.css to let webpack handle the generated CSS with its built-in CSS support, without any extra loaders or plugins.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/i,
type: "css/auto", // Handles the generated CSS using the built-in CSS support of webpack
use: ["stylus-loader"], // Compiles Stylus to CSS
},
],
},
experiments: {
css: true,
},
};The css/auto module type treats *.module.styl files as CSS modules and any other file as plain CSS.
Use type: "css" to always treat the file as plain CSS, or type: "css/module" to always treat it as a CSS module.
Using css-loader and style-loader
The built-in CSS support of webpack is not mandatory, you can still chain the stylus-loader with css-loader and style-loader to immediately apply all styles to the DOM.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/i,
use: [
{
loader: "style-loader", // Creates style nodes from JS strings
},
{
loader: "css-loader", // Translates CSS into CommonJS
},
{
loader: "stylus-loader", // Compiles Stylus to CSS
},
],
},
],
},
};Note that in this case the type and experiments.css options should not be set for this rule, and options like sourceMap have to be enabled for the css-loader too.
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$/i,
type: "css/auto",
use: [
{
loader: "stylus-loader",
options: {
sourceMap: true,
},
},
],
},
],
},
experiments: {
css: true,
},
};Using nib with stylus
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/i,
type: "css/auto",
use: [
{
loader: "stylus-loader",
options: {
stylusOptions: {
use: [require("nib")()],
import: ["nib"],
},
},
},
],
},
],
},
experiments: {
css: true,
},
};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$/i,
type: "css/auto",
use: [
{
loader: "stylus-loader",
options: {
stylusOptions: {
// Specify the path. where to find files
paths: ["node_modules/vars"],
},
},
},
],
},
],
},
experiments: {
css: true,
},
};In production
The built-in CSS support of webpack always extracts style sheets into dedicated files, so your styles are not dependent on JavaScript, which improves performance and cacheability.
The name of the generated files can be configured using the output.cssFilename and output.cssChunkFilename options.
When you chain the loader with css-loader and style-loader instead, 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$/i,
type: "css/auto",
use: [
{
loader: "stylus-loader",
options: {
stylusOptions: {
paths: [path.resolve(__dirname, "node_modules")],
},
},
},
],
},
],
},
experiments: {
css: true,
},
};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.
The built-in CSS support of webpack does this out of the box: every entry point and chunk gets its own style sheet, no extra plugin required.
When you chain the loader with the css-loader instead, use the MiniCssExtractPlugin to extract a style sheet from the bundle.
CSS modules
With the built-in CSS support of webpack, *.module.styl files are treated as CSS modules when the module type is css/auto, and all files are treated as CSS modules when the module type is css/module:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/i,
type: "css/auto",
use: ["stylus-loader"],
},
],
},
experiments: {
css: true,
},
};index.js
import * as styles from "./style.module.styl";
document.body.className = styles.box;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
What needs no loader
Webpack handles these itself — install a loader only for what is not on this list:
- JavaScript, ESM and CommonJS
- JSON
- Images, fonts, media and text files — Asset Modules, which replace
file-loader,url-loaderandraw-loader - WebAssembly —
experiments.asyncWebAssembly - CSS —
experiments.css, experimental; see what it covers - HTML —
experiments.html, experimental; see what it covers - TypeScript —
experiments.typescript, experimental; erases types on Node.js 22.6+, but does not type-check or handle JSX
Webpack enables use of loaders to preprocess everything else. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js.
Loaders are separate packages that extend webpack's capabilities and are maintained within the broader ecosystem.
Loaders are activated by using loadername! prefixes in import .. from "mod";/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
pug-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 function
Styling
css-utility-loader- Automatically parses and translates legacy CSS properties into modern utility classes (Tailwind) at build-time.less-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.



