A variety of interfaces are available to customize the compilation process. Some features overlap between interfaces, e.g. a configuration option may be available via a CLI flag, while others exist only through a single interface. The following high-level information should get you started.
The Command Line Interface (CLI) to configure and interact with your build. It
is especially useful in the case of early prototyping and profiling. For the
most part, the CLI is used to kick off the process using a configuration
file and a few flags (e.g. --env
).
When processing modules with webpack, it is important to understand the different module syntaxes – specifically the methods and variables – that are supported.
While most users can get away with using the CLI along with a configuration file, more fine-grained control of the compilation can be achieved via the Node interface. This includes passing multiple configurations, programmatically running or watching, and collecting stats.
Learn more about the Node API!
Loaders are transformations that are applied to the source code of a module. They are written as functions that accept source code as a parameter and return a new version of that code with transformations applied.
The plugin interface allows users to tap directly into the compilation process. Plugins can register handlers on lifecycle hooks that run at different points throughout a compilation. When each hook is executed, the plugin will have full access to the current state of the compilation.
For proper usage and easier distribution of this configuration, webpack can be configured with webpack.config.js
. Any parameters sent to the CLI will map to a corresponding parameter in the configuration file.
Read the installation guide if you don't already have webpack and CLI installed.
webpack-cli offers a variety of commands to make working with webpack easier. By default webpack ships with
Command | Usage | Description |
---|---|---|
build | build|bundle|b [entries...] [options] | Run webpack (default command, can be omitted). |
configtest | configtest|t [config-path] | Validate a webpack configuration. |
help | help|h [command] [option] | Display help for commands and options. |
info | info|i [options] | Outputs information about your system. |
init | init|create|c|new|n [generation-path] [options] | Initialize a new webpack project. |
loader | loader|l [output-path] [options] | Scaffold a loader. |
plugin | plugin|p [output-path] [options] | Scaffold a plugin. |
serve | serve|server|s [options] | Run the webpack-dev-server . |
version | version|v [commands...] | Output the version number of webpack , webpack-cli and webpack-dev-server . |
watch | watch|w [entries...] [options] | Run webpack and watch for files changes. |
Run webpack (default command, can be omitted).
npx webpack build [options]
example
npx webpack build --config ./webpack.config.js --stats verbose
Used to initialize a new webpack project.
npx webpack init [generation-path] [options]
example
npx webpack init ./my-app --force --template=default
Location of where to generate the configuration. Defaults to process.cwd()
.
-t
, --template
string = 'default'
Name of template to generate.
-f
, --force
boolean
To generate a project without questions. When enabled, the default answer for each question will be used.
Scaffold a loader.
npx webpack loader [output-path] [options]
example
npx webpack loader ./my-loader --template=default
Path to the output directory, e.g. ./loader-name
.
-t
, --template
string = 'default'
Type of template.
Scaffold a plugin.
npx webpack plugin [output-path] [options]
example
npx webpack plugin ./my-plugin --template=default
Path to the output directory, e.g. ./plugin-name
.
-t
, --template
string = 'default'
Type of template.
Outputs information about your system.
npx webpack info [options]
example
npx webpack info --output json --addition-package postcss
-a
, --additional-package
string
Adds additional packages to the output.
example
npx webpack info --additional-package postcss
-o
, --output
string : 'json' | 'markdown'
To get the output in a specified format.
example
npx webpack info --output markdown
Validate a webpack configuration.
npx webpack configtest [config-path]
example
npx webpack configtest ./webpack.config.js
Path to your webpack configuration file. Defaults to ./webpack.config.js
.
Run the webpack dev server.
npx webpack serve [options]
example
npx webpack serve --static --open
Run webpack and watch for files changes.
npx webpack watch [options]
example
npx webpack watch --mode development
By default webpack ships with the following flags:
Flag / Alias | Type | Description |
---|---|---|
--entry | string[] | The entry point(s) of your application e.g. ./src/main.js |
--config, -c | string[] | Provide path to a webpack configuration file e.g. ./webpack.config.js |
--config-name | string[] | Name of the configuration to use |
--name | string | Name of the configuration. Used when loading multiple configurations |
--color | boolean | Enable colors on console |
--merge, -m | boolean | Merge two or more configurations using webpack-merge |
--env | string[] | Environment passed to the configuration when it is a function |
--define-process-env-node-env | string | Set process.env.NODE_ENV to the specified value |
--progress | boolean, string | Print compilation progress during build |
--help | boolean | Outputs list of supported flags and commands |
--output-path, -o | string | Output location of the file generated by webpack e.g. ./dist |
--target, -t | string[] | Sets the build target |
--watch, -w | boolean | Watch for file changes |
--watch-options-stdin | boolean | Stop watching when stdin stream has ended |
--devtool, -d | string | Controls if and how source maps are generated. |
--json, -j | boolean, string | Prints result as JSON or store it in a file |
--mode | string | Defines the mode to pass to webpack |
--version, -v | boolean | Get current version |
--stats | boolean, string | It instructs webpack on how to treat the stats |
--disable-interpret | boolean | Disable interpret for loading the config file. |
--fail-on-warnings | boolean | Stop webpack-cli process with non-zero exit code on warnings from webpack |
--analyze | boolean | It invokes webpack-bundle-analyzer plugin to get bundle information |
--extends, -e | string[] | Extend an existing configuration |
Flag | Description |
---|---|
--no-color | Disables any color on the console |
--no-hot | Disables hot reloading if you have it enabled via your config |
--no-stats | Disables any compilation stats emitted by webpack |
--no-watch | Do not watch for file changes |
--no-devtool | Do not generate source maps |
--no-watch-options-stdin | Do not stop watching when stdin stream has ended |
Starting CLI v4 and webpack v5, CLI imports the entire configuration schema from webpack core to allow tuning almost every configuration option from the command line.
Here's the list of all the core flags supported by webpack v5 with CLI v4 - link
For example if you want to enable performance hints in your project you'd use this option in configuration, with core flags you can do -
npx webpack --performance-hints warning
npx webpack [--config webpack.config.js]
See configuration for the options in the configuration file.
npx webpack --entry <entry> --output-path <output-path>
example
npx webpack --entry ./first.js --entry ./second.js --output-path /build
A filename or a set of named filenames which act as the entry point to build your project. You can pass multiple entries (every entry is loaded on startup). Following are the multiple ways of specifying entry file(s) via CLI -
npx webpack --entry-reset ./first-entry.js
npx webpack --entry-reset --entry ./first-entry.js
npx webpack --entry-reset ./first-entry.js ./other-entry.js
npx webpack --entry-reset --entry ./first-entry.js ./other-entry.js
A path for the bundled file to be saved in. It will be mapped to the configuration options output.path
.
Example
If your project structure is as follows -
.
├── dist
├── index.html
└── src
├── index.js
├── index2.js
└── others.js
npx webpack ./src/index.js --output-path dist
This will bundle your source code with entry as index.js
, and the output bundle file will have a path of dist
.
asset main.js 142 bytes [compared for emit] [minimized] (name: main)
./src/index.js 30 bytes [built] [code generated]
./src/others.js 1 bytes [built] [code generated]
webpack 5.1.0 compiled successfully in 187 ms
npx webpack ./src/index.js ./src/others2.js --output-path dist/
This will form the bundle with both the files as separate entry points.
asset main.js 142 bytes [compared for emit] [minimized] (name: main)
./src/index.js 30 bytes [built] [code generated]
./src/others2.js 1 bytes [built] [code generated]
./src/others.js 1 bytes [built] [code generated]
webpack 5.1.0 compiled successfully in 198 ms
CLI will look for some default configurations in the path of your project, here are the config files picked up by CLI.
This is the lookup priority in increasing order
example - config file lookup will be in order of .webpack/webpackfile > .webpack/webpack.config.js > webpack.config.js
'webpack.config',
'.webpack/webpack.config',
'.webpack/webpackfile',
List basic commands and flags available on the cli
Both webpack help [command] [option]
and webpack [command] --help
are valid to get help:
npx webpack --help
# or
npx webpack help
List all supported commands and flags by cli
npx webpack --help=verbose
See help for a specific command or option
npx webpack help --mode
Show version of installed packages and sub-packages
To inspect the version of webpack
and webpack-cli
you are using, run the command:
npx webpack --version
# or
npx webpack version
This will output the following result:
webpack 5.31.2
webpack-cli 4.6.0
It will output the version of webpack-dev-server
as well if you have it installed:
webpack 5.31.2
webpack-cli 4.6.0
webpack-dev-server 3.11.2
To inspect the version of any webpack-cli
sub-package (like @webpack-cli/info
), run command similar to the following:
npx webpack info --version
This will output the following result:
@webpack-cli/info 1.2.3
webpack 5.31.2
webpack-cli 4.6.0
webpack-dev-server 3.11.2
Build source using a configuration file
Specify a different configuration file other than webpack.config.js
, which is one of the defaults.
npx webpack --config example.config.js
In case your configuration file exports multiple configurations, you can use --config-name
to specify which configuration to run.
Consider the following webpack.config.js
:
module.exports = [
{
output: {
filename: './dist-first.js',
},
name: 'first',
entry: './src/first.js',
mode: 'development',
},
{
output: {
filename: './dist-second.js',
},
name: 'second',
entry: './src/second.js',
mode: 'development',
},
{
output: {
filename: './dist-third.js',
},
name: 'third',
entry: './src/third.js',
mode: 'none',
stats: 'verbose',
},
];
To run only the second
configuration:
npx webpack --config-name second
You can also pass multiple values:
npx webpack --config-name first --config-name second
You can merge two or more different webpack configurations with the help of --merge
:
npx webpack --config ./first.js --config ./second.js --merge
You can extend existing webpack configurations with the help of --extends
:
npx webpack --extends ./base.webpack.config.js
Read more about it in extending configurations.
Print result of webpack as JSON
npx webpack --json
If you want to store stats as json instead of printing it, you can use -
npx webpack --json stats.json
In every other case, webpack prints out a set of stats showing bundle, chunk and timing details. Using this option, the output can be a JSON object. This response is accepted by webpack's analyse tool, or chrisbateman's webpack-visualizer, or th0r's webpack-bundle-analyzer. The analyse tool will take in the JSON and provide all the details of the build in graphical form.
When the webpack configuration exports a function, an "environment" may be passed to it.
npx webpack --env production # env.production = true
The --env
argument accepts multiple values:
Invocation | Resulting environment |
---|---|
npx webpack --env prod | { prod: true } |
npx webpack --env prod --env min | { prod: true, min: true } |
npx webpack --env platform=app --env production | { platform: "app", production: true } |
npx webpack --env foo=bar=app | { foo: "bar=app"} |
npx webpack --env app.platform="staging" --env app.name="test" | { app: { platform: "staging", name: "test" } |
In addition to the customized env
showed above, there are some built-in ones under env
to be used inside your webpack configuration:
Environment Variable | Description |
---|---|
WEBPACK_SERVE | true if serve|server|s is being used. |
WEBPACK_BUILD | true if build|bundle|b is being used. |
WEBPACK_WATCH | true if --watch|watch|w is being used. |
Note that you can not access those built-in environment variables inside the bundled code.
module.exports = (env, argv) => {
return {
mode: env.WEBPACK_SERVE ? 'development' : 'production',
};
};
You can use --node-env
option to set process.env.NODE_ENV
, which is available to both user code and webpack configuration:
npx webpack --node-env production # process.env.NODE_ENV = 'production'
For webpack-cli v5+
.
An alias for --node-env
to set process.env.NODE_ENV
:
npx webpack --define-process-env-node-env production # process.env.NODE_ENV = 'production'
When the mode
option is not specified in the configuration, you can use the --define-process-env-node-env
option to set the mode
. For example, using --define-process-env-node-env production
will set both process.env.NODE_ENV
and mode
to 'production'
.
If your configuration exports a function, the value of --define-process-env-node-env
is assigned to mode after the function returns. This means that mode
will not be available in the function arguments (env
and argv
). However, the value of --define-process-env-node-env
is accessible as argv.nodeEnv
within the function and can be used accordingly.
module.exports = (env, argv) => {
console.log(argv.defineProcessEnvNodeEnv); // 'production' if --define-process-env-node-env production is used
return {
// your configuration
};
};
Parameter | Explanation | Input type | Default |
---|---|---|---|
--config | Path to the configuration file | string[] | Default Configs |
--config-name | Name of the configuration to use | string[] | - |
--env | Environment passed to the configuration, when it is a function | string[] | - |
You can also use webpack-bundle-analyzer
to analyze your output bundles emitted by webpack. You can use --analyze
flag to invoke it via CLI.
npx webpack --analyze
To check the progress of any webpack compilation you can use the --progress
flag.
npx webpack --progress
To collect profile data for progress steps you can pass profile
as value to --progress
flag.
npx webpack --progress=profile
To pass arguments directly to Node.js process, you can use the NODE_OPTIONS
option.
For example, to increase the memory limit of Node.js process to 4 GB
NODE_OPTIONS="--max-old-space-size=4096" webpack
Also, you can pass multiple options to Node.js process
NODE_OPTIONS="--max-old-space-size=4096 -r /path/to/preload/file.js" webpack
Exit Code | Description |
---|---|
0 | Success |
1 | Errors from webpack |
2 | Configuration/options problem or an internal error |
Environment Variable | Description |
---|---|
WEBPACK_CLI_SKIP_IMPORT_LOCAL | when true it will skip using the local instance of webpack-cli . |
WEBPACK_CLI_FORCE_LOAD_ESM_CONFIG | when true it will force load the ESM config. |
WEBPACK_PACKAGE | Use a custom webpack version in CLI. |
WEBPACK_DEV_SERVER_PACKAGE | Use a custom webpack-dev-server version in CLI. |
WEBPACK_CLI_HELP_WIDTH | Use a custom width for help output. |
WEBPACK_CLI_FORCE_LOAD_ESM_CONFIG=true npx webpack --config ./webpack.config.esm
Use a custom webpack version in CLI. Considering the following content in your package.json
:
{
"webpack": "^4.0.0",
"webpack-5": "npm:webpack@^5.32.0",
"webpack-cli": "^4.5.0"
}
To use webpack v4.0.0
:
npx webpack
To use webpack v5.32.0
:
WEBPACK_PACKAGE=webpack-5 npx webpack
You might encounter this error in the case of using native ESM in TypeScript (i.e. type: "module"
in package.json
).
webpack-cli
supports configuration in both CommonJS
and ESM
format, at first it tries to load a configuration using require()
, once it fails with an error code of 'ERR_REQUIRE_ESM'
(a special code for this case) it would try to load the configuration using import()
.
However, the import()
method won't work with ts-node
without loader hooks enabled (described at TypeStrong/ts-node#1007
).
To fix the error above use the following command:
NODE_OPTIONS="--loader ts-node/esm" npx webpack --entry ./src/index.js --mode production
For more information, see our documentation on writing a webpack configuration in TypeScript
.
Webpack provides a Node.js API which can be used directly in Node.js runtime.
The Node.js API is useful in scenarios in which you need to customize the build or development process since all the reporting and error handling must be done manually and webpack only does the compiling part. For this reason the stats
configuration options will not have any effect in the webpack()
call.
To start using the webpack Node.js API, first install webpack if you haven’t yet:
npm install --save-dev webpack
Then require the webpack module in your Node.js script:
const webpack = require('webpack');
Or if you prefer ES2015:
import webpack from 'webpack';
The imported webpack
function is fed a webpack Configuration Object and runs the webpack compiler if a callback function is provided:
const webpack = require('webpack');
webpack({}, (err, stats) => {
if (err || stats.hasErrors()) {
// ...
}
// Done processing
});
If you don’t pass the webpack
runner function a callback, it will return a
webpack Compiler
instance. This instance can be used to manually trigger the
webpack runner or have it build and watch for changes, much like the
CLI. The Compiler
instance provides the following methods:
.run(callback)
.watch(watchOptions, handler)
Typically, only one master Compiler
instance is created, although child
compilers can be created in order to delegate specific tasks. The Compiler
is
ultimately a function which performs bare minimum functionality to keep a
lifecycle running. It delegates all the loading, bundling, and writing work to
registered plugins.
The hooks
property on a Compiler
instance is used to register a plugin to
any hook event in the Compiler
's lifecycle. The
WebpackOptionsDefaulter
and WebpackOptionsApply
utilities are used by webpack to configure its Compiler
instance with all the
built-in plugins.
The run
method is then used to kickstart all compilation work. Upon
completion, the given callback
function is executed. The final logging of
stats and errors should be done in this callback
function.
Calling the run
method on the Compiler
instance is much like the quick run
method mentioned above:
const webpack = require('webpack');
const compiler = webpack({
// ...
});
compiler.run((err, stats) => {
// ...
compiler.close((closeErr) => {
// ...
});
});
Calling the watch
method triggers the webpack runner, but then watches for
changes (much like CLI: webpack --watch
), as soon as webpack detects a
change, runs again. Returns an instance of Watching
.
watch(watchOptions, callback);
const webpack = require('webpack');
const compiler = webpack({
// ...
});
const watching = compiler.watch(
{
// Example
aggregateTimeout: 300,
poll: undefined,
},
(err, stats) => {
// Print watch/build result here...
console.log(stats);
}
);
Watching
options are covered in detail
here.
Watching
The watch
method returns a Watching
instance that exposes
.close(callback)
method. Calling this method will end watching:
watching.close((closeErr) => {
console.log('Watching Ended.');
});
Watching
Using watching.invalidate
, you can manually invalidate the current compiling
round, without stopping the watch process:
watching.invalidate();
The stats
object that is passed as a second argument of the
webpack()
callback, is a good source of information about the
code compilation process. It includes:
The webpack CLI uses this information to display nicely formatted output in your console.
This stats
object exposes the following methods:
Can be used to check if there were errors while compiling. Returns true
or
false
.
Can be used to check if there were warnings while compiling. Returns true
or
false
.
Returns compilation information as a JSON object. options
can be either a
string (a preset) or an object for more granular control:
stats.toJson('minimal');
stats.toJson({
assets: false,
hash: true,
});
All available options and presets are described in the stats documentation.
Here’s an example of this function’s output.
Returns a formatted string of the compilation information (similar to CLI output).
Options are the same as stats.toJson(options)
with one addition:
stats.toString({
// Add console colors
colors: true,
});
Here’s an example of stats.toString()
usage:
const webpack = require('webpack');
webpack(
{
// ...
},
(err, stats) => {
if (err) {
console.error(err);
return;
}
console.log(
stats.toString({
chunks: false, // Makes the build much quieter
colors: true, // Shows colors in the console
})
);
}
);
The MultiCompiler
module allows webpack to run multiple configurations in
separate compilers. If the options
parameter in the webpack's NodeJS api is
an array of options, webpack applies separate compilers and calls the
callback
after all compilers have been executed.
var webpack = require('webpack');
webpack(
[
{ entry: './index1.js', output: { filename: 'bundle1.js' } },
{ entry: './index2.js', output: { filename: 'bundle2.js' } },
],
(err, stats) => {
process.stdout.write(stats.toString() + '\n');
}
);
For good error handling, you need to account for these three types of errors:
Here’s an example that does all that:
const webpack = require('webpack');
webpack(
{
// ...
},
(err, stats) => {
if (err) {
console.error(err.stack || err);
if (err.details) {
console.error(err.details);
}
return;
}
const info = stats.toJson();
if (stats.hasErrors()) {
console.error(info.errors);
}
if (stats.hasWarnings()) {
console.warn(info.warnings);
}
// Log result...
}
);
By default, webpack reads files and writes files to disk using a normal file
system. However, it is possible to change the input or output behavior using a
different kind of file system (memory, webDAV, etc). To accomplish this, one
can change the inputFileSystem
or outputFileSystem
. For example, you can
replace the default outputFileSystem
with
memfs
to write files to memory
instead of to disk:
const { createFsFromVolume, Volume } = require('memfs');
const webpack = require('webpack');
const fs = createFsFromVolume(new Volume());
const compiler = webpack({
/* options */
});
compiler.outputFileSystem = fs;
compiler.run((err, stats) => {
// Read the output later:
const content = fs.readFileSync('...');
compiler.close((closeErr) => {
// ...
});
});
Note that this is what webpack-dev-middleware, used by webpack-dev-server and many other packages, uses to mysteriously hide your files but continue serving them up to the browser!
When compiling source code with webpack, users can generate a JSON file containing statistics about modules. These statistics can be used to analyze an application's dependency graph as well as to optimize compilation speed. The file is typically generated with the following CLI command:
npx webpack --profile --json=compilation-stats.json
The --json=compilation-stats.json
flag indicates to webpack that it should emit the compilation-stats.json
containing the dependency graph and various other build information. Typically, the --profile
flag is also added so that a profile
section is added to each modules
object containing module-specific compilation stats.
The top-level structure of the output JSON file is fairly straightforward but there are a few nested data structures as well. Each nested structure has a dedicated section below to make this document more consumable. Note that you can click links within the top-level structure below to jump to relevant sections and documentation:
{
"version": "5.9.0", // Version of webpack used for the compilation
"hash": "11593e3b3ac85436984a", // Compilation specific hash
"time": 2469, // Compilation time in milliseconds
"publicPath": "auto",
"outputPath": "/", // path to webpack output directory
"assetsByChunkName": {
// Chunk name to emitted asset(s) mapping
"main": ["web.js?h=11593e3b3ac85436984a"],
"named-chunk": ["named-chunk.web.js"],
"other-chunk": ["other-chunk.js", "other-chunk.css"]
},
"assets": [
// A list of asset objects
],
"chunks": [
// A list of chunk objects
],
"modules": [
// A list of module objects
],
"entryPoints": {
// A list of entry objects
},
"errors": [
// A list of error objects
],
"errorsCount": 0, // number of errors
"warnings": [
// A list of warning objects
],
"warningsCount": 0 // nummber of warnings
}
Each assets
object represents an output
file emitted from the compilation. They all follow a similar structure:
{
"chunkNames": [], // The chunks this asset contains
"chunks": [10, 6], // The chunk IDs this asset contains
"comparedForEmit": false, // Indicates whether or not the asset was compared with the same file on the output file system
"emitted": true, // Indicates whether or not the asset made it to the `output` directory
"name": "10.web.js", // The `output` filename
"size": 1058, // The size of the file in bytes
"info": {
"immutable": true, // A flag telling whether the asset can be long term cached (contains a hash)
"size": 1058, // The size in bytes, only becomes available after asset has been emitted
"development": true, // A flag telling whether the asset is only used for development and doesn't count towards user-facing assets
"hotModuleReplacement": true, // A flag telling whether the asset ships data for updating an existing application (HMR)
"sourceFilename": "originalfile.js", // sourceFilename when asset was created from a source file (potentially transformed)
"javascriptModule": true // true, when asset is javascript and an ESM
}
}
Each chunks
object represents a group of modules known as a chunk. Each object follows the following structure:
{
"entry": true, // Indicates whether or not the chunk contains the webpack runtime
"files": [
// An array of filename strings that contain this chunk
],
"filteredModules": 0, // See the description in the [top-level structure](#structure) above
"id": 0, // The ID of this chunk
"initial": true, // Indicates whether this chunk is loaded on initial page load or [on demand](/guides/lazy-loading)
"modules": [
// A list of [module objects](#module-objects)
"web.js?h=11593e3b3ac85436984a"
],
"names": [
// An list of chunk names contained within this chunk
],
"origins": [
// See the description below...
],
"parents": [], // Parent chunk IDs
"rendered": true, // Indicates whether or not the chunk went through Code Generation
"size": 188057 // Chunk size in bytes
}
The chunks
object will also contain a list of origins
describing how the given chunk originated. Each origins
object follows the following schema:
{
"loc": "", // Lines of code that generated this chunk
"module": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module
"moduleId": 0, // The ID of the module
"moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module
"moduleName": "./lib/index.web.js", // Relative path to the module
"name": "main", // The name of the chunk
"reasons": [
// A list of the same `reasons` found in [module objects](#module-objects)
]
}
What good would these statistics be without some description of the compiled application's actual modules? Each module in the dependency graph is represented by the following structure:
{
"assets": [
// A list of [asset objects](#asset-objects)
],
"built": true, // Indicates that the module went through [Loaders](/concepts/loaders), Parsing, and Code Generation
"cacheable": true, // Whether or not this module is cacheable
"chunks": [
// IDs of chunks that contain this module
],
"errors": 0, // Number of errors when resolving or processing the module
"failed": false, // Whether or not compilation failed on this module
"id": 0, // The ID of the module (analogous to [`module.id`](/api/module-variables/#moduleid-commonjs))
"identifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // A unique ID used internally
"name": "./lib/index.web.js", // Path to the actual file
"optional": false, // All requests to this module are with `try... catch` blocks (irrelevant with ESM)
"prefetched": false, // Indicates whether or not the module was [prefetched](/plugins/prefetch-plugin)
"profile": {
// Module specific compilation stats corresponding to the [`--profile` flag](/api/cli/#profiling) (in milliseconds)
"building": 73, // Loading and parsing
"dependencies": 242, // Building dependencies
"factory": 11 // Resolving dependencies
},
"reasons": [
// See the description below...
],
"size": 3593, // Estimated size of the module in bytes
"source": "// Should not break it...\r\nif(typeof...", // The stringified raw source
"warnings": 0 // Number of warnings when resolving or processing the module
}
Every module also contains a list of reasons
objects describing why that module was included in the dependency graph. Each "reason" is similar to the origins
seen above in the chunk objects section:
{
"loc": "33:24-93", // Lines of code that caused the module to be included
"module": "./lib/index.web.js", // Relative path to the module based on [context](/configuration/entry-context/#context)
"moduleId": 0, // The ID of the module
"moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module
"moduleName": "./lib/index.web.js", // A more readable name for the module (used for "pretty-printing")
"type": "require.context", // The [type of request](/api/module-methods) used
"userRequest": "../../cases" // Raw string used for the `import` or `require` request
}
"main": {
"name": "main",
"chunks": [
179
],
"assets": [
{
"name": "main.js",
"size": 22
}
],
"filteredAssets": 0,
"assetsSize": 22,
"auxiliaryAssets": [],
"filteredAuxiliaryAssets": 0,
"auxiliaryAssetsSize": 0,
"children": {},
"childAssets": {},
"isOverSizeLimit": false
}
The errors
and warnings
properties each contain a list of objects. Each object contains a message, a stack trace and various other properties:
{
"moduleIdentifier": "C:\\Repos\\webpack\\test\\cases\\context\\issue-5750\\index.js",
"moduleName": "(webpack)/test/cases/context/issue-5750/index.js",
"loc": "3:8-47",
"message": "Critical dependency: Contexts can't use RegExps with the 'g' or 'y' flags.",
"moduleId": 29595,
"moduleTrace": [
{
"originIdentifier": "C:\\Repos\\webpack\\test\\cases|sync|/^\\.\\/[^/]+\\/[^/]+\\/index\\.js$/",
"originName": "(webpack)/test/cases sync ^\\.\\/[^/]+\\/[^/]+\\/index\\.js$",
"moduleIdentifier": "C:\\Repos\\webpack\\test\\cases\\context\\issue-5750\\index.js",
"moduleName": "(webpack)/test/cases/context/issue-5750/index.js",
"dependencies": [
{
"loc": "./context/issue-5750/index.js"
}
],
"originId": 32582,
"moduleId": 29595
},
{
"originIdentifier": "C:\\Repos\\webpack\\testCases.js",
"originName": "(webpack)/testCases.js",
"moduleIdentifier": "C:\\Repos\\webpack\\test\\cases|sync|/^\\.\\/[^/]+\\/[^/]+\\/index\\.js$/",
"moduleName": "(webpack)/test/cases sync ^\\.\\/[^/]+\\/[^/]+\\/index\\.js$",
"dependencies": [
{
"loc": "1:0-70"
}
],
"originId": 8198,
"moduleId": 32582
}
],
"details": "at RequireContextDependency.getWarnings (C:\\Repos\\webpack\\lib\\dependencies\\ContextDependency.js:79:5)\n at Compilation.reportDependencyErrorsAndWarnings (C:\\Repos\\webpack\\lib\\Compilation.js:1727:24)\n at C:\\Repos\\webpack\\lib\\Compilation.js:1467:10\n at _next2 (<anonymous>:16:1)\n at eval (<anonymous>:42:1)\n at C:\\Repos\\webpack\\node_modules\\neo-async\\async.js:2830:7\n at Object.each (C:\\Repos\\webpack\\node_modules\\neo-async\\async.js:2850:39)\n at C:\\Repos\\webpack\\lib\\FlagDependencyExportsPlugin.js:219:18\n at C:\\Repos\\webpack\\node_modules\\neo-async\\async.js:2830:7\n at Object.each (C:\\Repos\\webpack\\node_modules\\neo-async\\async.js:2850:39)\n at C:\\Repos\\webpack\\lib\\FlagDependencyExportsPlugin.js:40:16\n at Hook.eval [as callAsync] (<anonymous>:38:1)\n at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (C:\\Repos\\tapable\\lib\\Hook.js:18:14)\n at Compilation.finish (C:\\Repos\\webpack\\lib\\Compilation.js:1462:28)\n at C:\\Repos\\webpack\\lib\\Compiler.js:909:18\n at processTicksAndRejections (internal/process/task_queues.js:75:11)\n",
"stack": "ModuleDependencyWarning: Critical dependency: Contexts can't use RegExps with the 'g' or 'y' flags.\n at Compilation.reportDependencyErrorsAndWarnings (C:\\Repos\\webpack\\lib\\Compilation.js:1732:23)\n at C:\\Repos\\webpack\\lib\\Compilation.js:1467:10\n at _next2 (<anonymous>:16:1)\n at eval (<anonymous>:42:1)\n at C:\\Repos\\webpack\\node_modules\\neo-async\\async.js:2830:7\n at Object.each (C:\\Repos\\webpack\\node_modules\\neo-async\\async.js:2850:39)\n at C:\\Repos\\webpack\\lib\\FlagDependencyExportsPlugin.js:219:18\n at C:\\Repos\\webpack\\node_modules\\neo-async\\async.js:2830:7\n at Object.each (C:\\Repos\\webpack\\node_modules\\neo-async\\async.js:2850:39)\n at C:\\Repos\\webpack\\lib\\FlagDependencyExportsPlugin.js:40:16\n at Hook.eval [as callAsync] (<anonymous>:38:1)\n at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (C:\\Repos\\tapable\\lib\\Hook.js:18:14)\n at Compilation.finish (C:\\Repos\\webpack\\lib\\Compilation.js:1462:28)\n at C:\\Repos\\webpack\\lib\\Compiler.js:909:18\n at processTicksAndRejections (internal/process/task_queues.js:75:11)\n"
}
webpack-dev-server
provides a Node.js API which can be used directly in Node.js runtime.
To start using the webpack-dev-server
Node.js API, first install webpack
and webpack-dev-server
if you haven’t yet:
npm install --save-dev webpack webpack-dev-server
Then require the modules in your Node.js script:
const Webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
It instructs webpack-dev-server
instance to start the server.
server.js
const Webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const webpackConfig = require('./webpack.config.js');
const compiler = Webpack(webpackConfig);
const devServerOptions = { ...webpackConfig.devServer, open: true };
const server = new WebpackDevServer(devServerOptions, compiler);
const runServer = async () => {
console.log('Starting server...');
await server.start();
};
runServer();
And then run the server with the following command:
node server.js
It instructs webpack-dev-server
instance to start the server and then run the callback function.
server.js
const Webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const webpackConfig = require('./webpack.config.js');
const compiler = Webpack(webpackConfig);
const devServerOptions = { ...webpackConfig.devServer, open: true };
const server = new WebpackDevServer(devServerOptions, compiler);
server.startCallback(() => {
console.log('Successfully started server on http://localhost:8080');
});
And then run the server with the following command:
node server.js
It instructs webpack-dev-server
instance to stop the server.
server.js
const Webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const webpackConfig = require('./webpack.config.js');
const compiler = Webpack(webpackConfig);
const devServerOptions = { ...webpackConfig.devServer, open: true };
const server = new WebpackDevServer(devServerOptions, compiler);
const runServer = async () => {
console.log('Starting server...');
await server.start();
};
const stopServer = async () => {
console.log('Stopping server...');
await server.stop();
};
runServer();
setTimeout(stopServer, 5000);
And then run the server with the following command:
node server.js
It instructs webpack-dev-server
instance to stop the server and then run the callback function.
server.js
const Webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const webpackConfig = require('./webpack.config.js');
const compiler = Webpack(webpackConfig);
const devServerOptions = { ...webpackConfig.devServer, open: true };
const server = new WebpackDevServer(devServerOptions, compiler);
server.startCallback(() => {
console.log('Successfully started server on http://localhost:8080');
});
const stopServer = () =>
server.stopCallback(() => {
console.log('Server stopped.');
});
setTimeout(stopServer, 5000);
And then run the server with the following command:
node server.js
Returns the internal IPv4
/IPv6
address asynchronously.
server.js
const WebpackDevServer = require('webpack-dev-server');
const logInternalIPs = async () => {
const localIPv4 = await WebpackDevServer.internalIP('v4');
const localIPv6 = await WebpackDevServer.internalIP('v6');
console.log('Local IPv4 address:', localIPv4);
console.log('Local IPv6 address:', localIPv6);
};
logInternalIPs();
Returns the internal IPv4
/IPv6
address synchronously.
server.js
const WebpackDevServer = require('webpack-dev-server');
const localIPv4 = WebpackDevServer.internalIPSync('v4');
const localIPv6 = WebpackDevServer.internalIPSync('v6');
console.log('Local IPv4 address:', localIPv4);
console.log('Local IPv6 address:', localIPv6);
If Hot Module Replacement has been enabled via the HotModuleReplacementPlugin
, its interface will be exposed under the module.hot
property as well as import.meta.webpackHot
property. Note that only import.meta.webpackHot
can be used in strict ESM.
Typically, users will check to see if the interface is accessible, then begin working with it. As an example, here's how you might accept
an updated module:
if (module.hot) {
module.hot.accept('./library.js', function () {
// Do something with the updated library module...
});
}
// or
if (import.meta.webpackHot) {
import.meta.webpackHot.accept('./library.js', function () {
// Do something with the updated library module…
});
}
The following methods are supported...
Accept updates for the given dependencies
and fire a callback
to react to those updates, in addition, you can attach an optional error handler:
module.hot.accept(
dependencies, // Either a string or an array of strings
callback, // Function to fire when the dependencies are updated
errorHandler // (err, {moduleId, dependencyId}) => {}
);
// or
import.meta.webpackHot.accept(
dependencies, // Either a string or an array of strings
callback, // Function to fire when the dependencies are updated
errorHandler // (err, {moduleId, dependencyId}) => {}
);
When using ESM import
all imported symbols from dependencies
are automatically updated. Note: The dependency string must match exactly with the from
string in the import
. In some cases callback
can even be omitted. Using require()
in the callback
doesn't make sense here.
When using CommonJS you need to update dependencies manually by using require()
in the callback
. Omitting the callback
doesn't make sense here.
(err, {moduleId, dependencyId}) => {}
err
: the error thrown by the callback in second argument or during dependency execution when using ESM dependencies.moduleId
: the current module id.dependencyId
: the module id of the (first) changed dependency.Accept updates for itself.
module.hot.accept(
errorHandler // Function to handle errors when evaluating the new version
);
// or
import.meta.webpackHot.accept(
errorHandler // Function to handle errors when evaluating the new version
);
When this module or dependencies are updated, this module can be disposed and re-evaluated without informing parents. This makes sense if this module has no exports (or exports are updated in another way).
The errorHandler
is fired when the evaluation of this module (or dependencies) has thrown an exception.
(err, {moduleId, module}) => {}
err
: the error when evaluating the new version.moduleId
: the current module id.module
: the current module instance.
module.hot
: allow to use the HMR API of the errored module instance. A common scenario is to self accept it again. It also makes sense to add a dispose handler to pass data along. Note that the errored module might be already partially executed, so make sure to not get into a inconsistent state. You can use module.hot.data
to store partial state.module.exports
: can be overridden, but be careful since property names might be mangled in production mode.Reject updates for the given dependencies
forcing the update to fail with a 'decline'
code.
module.hot.decline(
dependencies // Either a string or an array of strings
);
// or
import.meta.webpackHot.decline(
dependencies // Either a string or an array of strings
);
Flag a dependency as not-update-able. This makes sense when changing exports of this dependency can't be handled or handling is not implemented yet. Depending on your HMR management code, an update to these dependencies (or unaccepted dependencies of it) usually causes a full-reload of the page.
Reject updates for itself.
module.hot.decline();
// or
import.meta.webpackHot.decline();
Flag this module as not-update-able. This makes sense when this module has irreversible side-effects, or HMR handling is not implemented for this module yet. Depending on your HMR management code, an update to this module (or unaccepted dependencies) usually causes a full-reload of the page.
Add a handler which is executed when the current module code is replaced. This should be used to remove any persistent resource you have claimed or created. If you want to transfer state to the updated module, add it to the given data
parameter. This object will be available at module.hot.data
after the update.
module.hot.dispose((data) => {
// Clean up and pass data to the updated module...
});
// or
import.meta.webpackHot.dispose((data) => {
// Clean up and pass data to the updated module...
});
Calling this method will invalidate the current module, which disposes and recreates it when the HMR update is applied. This bubbles like a normal update of this module. invalidate
can't be self-accepted by this module.
When called during the idle
state, a new HMR update will be created containing this module. HMR will enter the ready
state.
When called during the ready
or prepare
state, this module will be added to the current HMR update.
When called during the check
state, this module will be added to the update when an update is available. If no update is available it will create a new update. HMR will enter the ready
state.
When called during the dispose
or apply
state, HMR will pick it up after getting out of those states.
Conditional Accepting
A module can accept a dependency, but can call invalidate
when the change of the dependency is not handleable:
import { x, y } from './dep';
import { processX, processY } from 'anotherDep';
const oldY = y;
processX(x);
export default processY(y);
module.hot.accept('./dep', () => {
if (y !== oldY) {
// This can't be handled, bubble to parent
module.hot.invalidate();
return;
}
// This can be handled
processX(x);
});
Conditional self accept
A module can self-accept itself, but can invalidate itself when the change is not handleable:
const VALUE = 'constant';
export default VALUE;
if (
module.hot.data &&
module.hot.data.value &&
module.hot.data.value !== VALUE
) {
module.hot.invalidate();
} else {
module.hot.dispose((data) => {
data.value = VALUE;
});
module.hot.accept();
}
Triggering custom HMR updates
const moduleId = chooseAModule();
const code = __webpack_modules__[moduleId].toString();
__webpack_modules__[moduleId] = eval(`(${makeChanges(code)})`);
if (require.cache[moduleId]) {
require.cache[moduleId].hot.invalidate();
module.hot.apply();
}
Remove the handler added via dispose
or addDisposeHandler
.
module.hot.removeDisposeHandler(callback);
// or
import.meta.webpackHot.removeDisposeHandler(callback);
Retrieve the current status of the hot module replacement process.
module.hot.status(); // Will return one of the following strings...
// or
import.meta.webpackHot.status();
Status | Description |
---|---|
idle | The process is waiting for a call to check |
check | The process is checking for updates |
prepare | The process is getting ready for the update (e.g. downloading the updated module) |
ready | The update is prepared and available |
dispose | The process is calling the dispose handlers on the modules that will be replaced |
apply | The process is calling the accept handlers and re-executing self-accepted modules |
abort | An update was aborted, but the system is still in its previous state |
fail | An update has thrown an exception and the system's state has been compromised |
Test all loaded modules for updates and, if updates exist, apply
them.
module.hot
.check(autoApply)
.then((outdatedModules) => {
// outdated modules...
})
.catch((error) => {
// catch errors
});
// or
import.meta.webpackHot
.check(autoApply)
.then((outdatedModules) => {
// outdated modules...
})
.catch((error) => {
// catch errors
});
The autoApply
parameter can either be a boolean or options
to pass to the apply
method when called.
Continue the update process (as long as module.hot.status() === 'ready'
).
module.hot
.apply(options)
.then((outdatedModules) => {
// outdated modules...
})
.catch((error) => {
// catch errors
});
// or
import.meta.webpackHot
.apply(options)
.then((outdatedModules) => {
// outdated modules...
})
.catch((error) => {
// catch errors
});
The optional options
object can include the following properties:
ignoreUnaccepted
(boolean): Ignore changes made to unaccepted modules.ignoreDeclined
(boolean): Ignore changes made to declined modules.ignoreErrored
(boolean): Ignore errors thrown in accept handlers, error handlers and while reevaluating module.onDeclined
(function(info)): Notifier for declined modulesonUnaccepted
(function(info)): Notifier for unaccepted modulesonAccepted
(function(info)): Notifier for accepted modulesonDisposed
(function(info)): Notifier for disposed modulesonErrored
(function(info)): Notifier for errorsThe info
parameter will be an object containing some of the following values:
{
type: 'self-declined' | 'declined' |
'unaccepted' | 'accepted' |
'disposed' | 'accept-errored' |
'self-accept-errored' | 'self-accept-error-handler-errored',
moduleId: 4, // The module in question.
dependencyId: 3, // For errors: the module id owning the accept handler.
chain: [1, 2, 3, 4], // For declined/accepted/unaccepted: the chain from where the update was propagated.
parentId: 5, // For declined: the module id of the declining parent
outdatedModules: [1, 2, 3, 4], // For accepted: the modules that are outdated and will be disposed
outdatedDependencies: { // For accepted: The location of accept handlers that will handle the update
5: [4]
},
error: new Error(...), // For errors: the thrown error
originalError: new Error(...) // For self-accept-error-handler-errored:
// the error thrown by the module before the error handler tried to handle it.
}
Register a function to listen for changes in status
.
module.hot.addStatusHandler((status) => {
// React to the current status...
});
// or
import.meta.webpackHot.addStatusHandler((status) => {
// React to the current status...
});
Bear in mind that when the status handler returns a Promise
, the HMR system will wait for the Promise
to resolve before continuing.
Remove a registered status handler.
module.hot.removeStatusHandler(callback);
// or
import.meta.webpackHot.removeStatusHandler(callback);
A loader is a JavaScript module that exports a function. The loader runner calls this function and passes the result of the previous loader or the resource file into it. The this
context of the function is filled-in by webpack and the loader runner with some useful methods that allow the loader (among other things) to change its invocation style to async, or get query parameters.
The first loader is passed one argument: the content of the resource file. The compiler expects a result from the last loader. The result should be a String
or a Buffer
(which is converted to a string), representing the JavaScript source code of the module. An optional SourceMap result (as a JSON object) may also be passed.
A single result can be returned in sync mode. For multiple results the this.callback()
must be called. In async mode this.async()
must be called to indicate that the loader runner should wait for an asynchronous result. It returns this.callback()
. Then the loader must return undefined
and call that callback.
/**
*
* @param {string|Buffer} content Content of the resource file
* @param {object} [map] SourceMap data consumable by https://github.com/mozilla/source-map
* @param {any} [meta] Meta data, could be anything
*/
function webpackLoader(content, map, meta) {
// code of your webpack loader
}
The following sections provide some basic examples of the different types of loaders. Note that the map
and meta
parameters are optional, see this.callback
below.
Either return
or this.callback
can be used to return the transformed content
synchronously:
sync-loader.js
module.exports = function (content, map, meta) {
return someSyncOperation(content);
};
The this.callback
method is more flexible as you pass multiple arguments instead of using content
only.
sync-loader-with-multiple-results.js
module.exports = function (content, map, meta) {
this.callback(null, someSyncOperation(content), map, meta);
return; // always return undefined when calling callback()
};
For asynchronous loaders, this.async
is used to retrieve the callback
function:
async-loader.js
module.exports = function (content, map, meta) {
var callback = this.async();
someAsyncOperation(content, function (err, result) {
if (err) return callback(err);
callback(null, result, map, meta);
});
};
async-loader-with-multiple-results.js
module.exports = function (content, map, meta) {
var callback = this.async();
someAsyncOperation(content, function (err, result, sourceMaps, meta) {
if (err) return callback(err);
callback(null, result, sourceMaps, meta);
});
};
By default, the resource file is converted to a UTF-8 string and passed to the loader. By setting the raw
flag to true
, the loader will receive the raw Buffer
. Every loader is allowed to deliver its result as a String
or as a Buffer
. The compiler converts them between loaders.
raw-loader.js
module.exports = function (content) {
assert(content instanceof Buffer);
return someSyncOperation(content);
// return value can be a `Buffer` too
// This is also allowed if loader is not "raw"
};
module.exports.raw = true;
Loaders are always called from right to left. There are some instances where the loader only cares about the metadata behind a request and can ignore the results of the previous loader. The pitch
method on loaders is called from left to right before the loaders are actually executed (from right to left).
For the following configuration of use
:
module.exports = {
//...
module: {
rules: [
{
//...
use: ['a-loader', 'b-loader', 'c-loader'],
},
],
},
};
These steps would occur:
|- a-loader `pitch`
|- b-loader `pitch`
|- c-loader `pitch`
|- requested module is picked up as a dependency
|- c-loader normal execution
|- b-loader normal execution
|- a-loader normal execution
So why might a loader take advantage of the "pitching" phase?
First, the data
passed to the pitch
method is exposed in the execution phase as well under this.data
and could be useful for capturing and sharing information from earlier in the cycle.
module.exports = function (content) {
return someSyncOperation(content, this.data.value);
};
module.exports.pitch = function (remainingRequest, precedingRequest, data) {
data.value = 42;
};
Second, if a loader delivers a result in the pitch
method, the process turns around and skips the remaining loaders. In our example above, if the b-loader
s pitch
method returned something:
module.exports = function (content) {
return someSyncOperation(content);
};
module.exports.pitch = function (remainingRequest, precedingRequest, data) {
if (someCondition()) {
return (
'module.exports = require(' +
JSON.stringify('-!' + remainingRequest) +
');'
);
}
};
The steps above would be shortened to:
|- a-loader `pitch`
|- b-loader `pitch` returns a module
|- a-loader normal execution
The loader context represents the properties that are available inside of a loader assigned to the this
property.
Given the following example, this require call is used:
In /abc/file.js
:
require('./loader1?xyz!loader2!./resource?rrr');
addContextDependency(directory: string)
Add a directory as dependency of the loader result.
addDependency(file: string)
dependency(file: string) // shortcut
Add an existing file as a dependency of the loader result in order to make them watchable. For example, sass-loader
, less-loader
uses this to recompile whenever any imported css
file changes.
addMissingDependency(file: string)
Add a non-existing file as a dependency of the loader result in order to make them watchable. Similar to addDependency
, but handles the creation of files during compilation before watchers are attached correctly.
Tells the loader-runner that the loader intends to call back asynchronously. Returns this.callback
.
A function that sets the cacheable flag:
cacheable(flag = true: boolean)
By default, loader results are flagged as cacheable. Call this method passing false
to make the loader's result not cacheable.
A cacheable loader must have a deterministic result when inputs and dependencies haven't changed. This means the loader shouldn't have dependencies other than those specified with this.addDependency
.
A function that can be called synchronously or asynchronously in order to return multiple results. The expected arguments are:
this.callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?: any
);
Error
or null
string
or a Buffer
.In case this function is called, you should return undefined to avoid ambiguous loader results.
clearDependencies();
Remove all dependencies of the loader result, even initial dependencies and those of other loaders. Consider using pitch
.
The directory of the module. Can be used as a context for resolving other stuff.
In the example: /abc
because resource.js
is in this directory
A data object shared between the pitch and the normal phase.
emitError(error: Error)
Emit an error that also can be displayed in the output.
ERROR in ./src/lib.js (./src/loader.js!./src/lib.js)
Module Error (from ./src/loader.js):
Here is an Error!
@ ./src/index.js 1:0-25
emitFile(name: string, content: Buffer|string, sourceMap: {...})
Emit a file. This is webpack-specific.
emitWarning(warning: Error)
Emit a warning that will be displayed in the output like the following:
WARNING in ./src/lib.js (./src/loader.js!./src/lib.js)
Module Warning (from ./src/loader.js):
Here is a Warning!
@ ./src/index.js 1:0-25
Check what kind of ES-features may be used in the generated runtime-code.
E.g.,
{
// The environment supports arrow functions ('() => { ... }').
"arrowFunction": true,
// The environment supports BigInt as literal (123n).
"bigIntLiteral": false,
// The environment supports const and let for variable declarations.
"const": true,
// The environment supports destructuring ('{ a, b } = obj').
"destructuring": true,
// The environment supports an async import() function to import EcmaScript modules.
"dynamicImport": false,
// The environment supports an async import() when creating a worker, only for web targets at the moment.
"dynamicImportInWorker": false,
// The environment supports 'for of' iteration ('for (const x of array) { ... }').
"forOf": true,
// The environment supports 'globalThis'.
"globalThis": true,
// The environment supports ECMAScript Module syntax to import ECMAScript modules (import ... from '...').
"module": false,
// The environment supports optional chaining ('obj?.a' or 'obj?.()').
"optionalChaining": true,
// The environment supports template literals.
"templateLiteral": true
}
Access to the compilation
's inputFileSystem
property.
Extracts given loader options. Optionally, accepts JSON schema as an argument.
getResolve(options: ResolveOptions): resolve
resolve(context: string, request: string, callback: function(err, result: string))
resolve(context: string, request: string): Promise<string>
Creates a resolve function similar to this.resolve
.
Any options under webpack resolve
options are possible. They are merged with the configured resolve
options. Note that "..."
can be used in arrays to extend the value from resolve
options, e.g. { extensions: [".sass", "..."] }
.
options.dependencyType
is an additional option. It allows us to specify the type of dependency, which is used to resolve byDependency
from the resolve
options.
All dependencies of the resolving operation are automatically added as dependencies to the current module.
Information about HMR for loaders.
module.exports = function (source) {
console.log(this.hot); // true if HMR is enabled via --hot flag or webpack configuration
return source;
};
string
The encoding to use when generating the hash. See output.hashDigest.
number
The prefix length of the hash digest to use. See output.hashDigestLength.
string
function
The hashing algorithm to use. See output.hashFunction.
string
An optional salt to update the hash via Node.JS' hash.update
. See output.hashSalt.
this.importModule(request, options, [callback]): Promise
An alternative lightweight solution for the child compiler to compile and execute a request at build time.
request
: the request string to load the module fromoptions
:
layer
: specify a layer in which this module is placed/compiledpublicPath
: the public path used for the built modulescallback
: an optional Node.js style callback returning the exports of the module or a namespace object for ESM. importModule
will return a Promise if no callback is provided.webpack.config.js
module.exports = {
module: {
rules: [
{
test: /stylesheet\.js$/i,
use: ['./a-pitching-loader.js'],
type: 'asset/source', // we set type to 'asset/source' as the loader will return a string
},
],
},
};
a-pitching-loader.js
exports.pitch = async function (remaining) {
const result = await this.importModule(
this.resourcePath + '.webpack[javascript/auto]' + '!=!' + remaining
);
return result.default || result;
};
src/stylesheet.js
import { green, red } from './colors.js';
export default `body { background: ${red}; color: ${green}; }`;
src/colors.js
export const red = '#f00';
export const green = '#0f0';
src/index.js
import stylesheet from './stylesheet.js';
// stylesheet will be a string `body { background: #f00; color: #0f0; }` at build time
You might notice something in the above example:
!=!
syntax in that pitching loader to set matchResource for the request, i.e., we'll use this.resourcePath + '.webpack[javascript/auto]'
to match with the module.rules
instead of the original resource,.webpack[javascript/auto]
is a pseudo extension of the .webpack[type]
pattern, we use it to specify a default module type when no other module type is specified. It's typically used in conjunction with !=!
syntax.Note that the above example is a simplified one, you can check the full example on webpack repository.
The index in the loaders array of the current loader.
In the example: in loader1: 0
, in loader2: 1
loadModule(request: string, callback: function(err, source, sourceMap, module))
Resolves the given request to a module, applies all configured loaders and calls back with the generated source, the sourceMap and the module instance (usually an instance of NormalModule
). Use this function if you need to know the source code of another module to generate the result.
this.loadModule
in a loader context uses CommonJS resolve rules by default. Use this.getResolve
with an appropriate dependencyType
, e.g. 'esm'
, 'commonjs'
or a custom one before using a different semantic.
An array of all the loaders. It is writable in the pitch phase.
loaders = [{request: string, path: string, query: string, module: function}]
In the example:
[
{
request: '/abc/loader1.js?xyz',
path: '/abc/loader1.js',
query: '?xyz',
module: [Function],
},
{
request: '/abc/node_modules/loader2/index.js',
path: '/abc/node_modules/loader2/index.js',
query: '',
module: [Function],
},
];
Read in which mode
webpack is running.
Possible values: 'production'
, 'development'
, 'none'
options
object, this will point to that object.options
, but was invoked with a query string, this will be a string starting with ?
.The resolved request string.
In the example: '/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr'
resolve(context: string, request: string, callback: function(err, result: string))
Resolve a request like a require expression.
context
must be an absolute path to a directory. This directory is used as the starting location for the resolving.request
is the request to be resolved. Usually either relative requests like ./relative
or module requests like module/path
are used, but absolute paths like /some/path
are also possible as requests.callback
is a normal Node.js-style callback function giving the resolved path.All dependencies of the resolving operation are automatically added as dependencies to the current module.
The resource part of the request, including query.
In the example: '/abc/resource.js?rrr'
The resource file.
In the example: '/abc/resource.js'
The query of the resource.
In the example: '?rrr'
Since webpack 4, the formerly this.options.context
is provided as this.rootContext
.
Tells if source map should be generated. Since generating source maps can be an expensive task, you should check if source maps are actually requested.
Target of compilation. Passed from configuration options.
Example values: 'web'
, 'node'
Access to the following utilities.
absolutify
: Return a new request string using absolute paths when possible.contextify
: Return a new request string avoiding absolute paths when possible.createHash
: Return a new Hash object from provided hash function.my-sync-loader.js
module.exports = function (content) {
this.utils.contextify(
this.context,
this.utils.absolutify(this.context, './index.js')
);
this.utils.absolutify(this.context, this.resourcePath);
const mainHash = this.utils.createHash(
this._compilation.outputOptions.hashFunction
);
mainHash.update(content);
mainHash.digest('hex');
// …
return content;
};
Loader API version. Currently 2
. This is useful for providing backwards compatibility. Using the version you can specify custom logic or fallbacks for breaking changes.
This boolean is set to true when this is compiled by webpack.
The loader interface provides all module relate information. However in rare cases you might need access to the compiler api itself.
Therefore you should only use them as a last resort. Using them will reduce the portability of your loader.
Access to the current Compilation object of webpack.
Access to the current Compiler object of webpack.
A boolean flag. It is set when in debug mode.
Passed from the last loader. If you would execute the input argument as a module, consider reading this variable for a shortcut (for performance).
Tells if result should be minimized.
Pass values to the next loader. If you know what your result exports if executed as a module, set this value here (as an only element array).
Hacky access to the Module object being loaded.
You can report errors from inside a loader by:
throw
(or other uncaught exception). Throwing an error while a loader is running will cause current module compilation failure.callback
(in async mode). Pass an error to the callback will also cause module compilation failure.For example:
./src/index.js
require('./loader!./lib');
Throwing an error from loader:
./src/loader.js
module.exports = function (source) {
throw new Error('This is a Fatal Error!');
};
Or pass an error to the callback in async mode:
./src/loader.js
module.exports = function (source) {
const callback = this.async();
//...
callback(new Error('This is a Fatal Error!'), source);
};
The module will get bundled like this:
/***/ "./src/loader.js!./src/lib.js":
/*!************************************!*\
!*** ./src/loader.js!./src/lib.js ***!
\************************************/
/*! no static exports found */
/***/ (function(module, exports) {
throw new Error("Module build failed (from ./src/loader.js):\nError: This is a Fatal Error!\n at Object.module.exports (/workspace/src/loader.js:3:9)");
/***/ })
Then the build output will also display the error (Similar to this.emitError
):
ERROR in ./src/lib.js (./src/loader.js!./src/lib.js)
Module build failed (from ./src/loader.js):
Error: This is a Fatal Error!
at Object.module.exports (/workspace/src/loader.js:2:9)
@ ./src/index.js 1:0-25
As you can see below, not only error message, but also details about which loader and module are involved:
ERROR in ./src/lib.js
(./src/loader.js!./src/lib.js)
(from ./src/loader.js)
@ ./src/index.js 1:0-25
A new inline request syntax was introduced in webpack v4. Prefixing <match-resource>!=!
to a request will set the matchResource
for this request.
When a matchResource
is set, it will be used to match with the module.rules
instead of the original resource. This can be useful if further loaders should be applied to the resource, or if the module type needs to be changed. It's also displayed in the stats and used for matching Rule.issuer
and test
in splitChunks
.
Example:
file.js
/* STYLE: body { background: red; } */
console.log('yep');
A loader could transform the file into the following file and use the matchResource
to apply the user-specified CSS processing rules:
file.js (transformed by loader)
import './file.js.css!=!extract-style-loader/getStyles!./file.js';
console.log('yep');
This will add a dependency to extract-style-loader/getStyles!./file.js
and treat the result as file.js.css
. Because module.rules
has a rule matching /\.css$/
and it will apply to this dependency.
The loader could look like this:
extract-style-loader/index.js
const getStylesLoader = require.resolve('./getStyles');
module.exports = function (source) {
if (STYLES_REGEXP.test(source)) {
source = source.replace(STYLES_REGEXP, '');
return `import ${JSON.stringify(
this.utils.contextify(
this.context || this.rootContext,
`${this.resource}.css!=!${getStylesLoader}!${this.remainingRequest}`
)
)};${source}`;
}
return source;
};
extract-style-loader/getStyles.js
module.exports = function (source) {
const match = source.match(STYLES_REGEXP);
return match[0];
};
Logging API is available since the release of webpack 4.37. When logging
is enabled in stats configuration
and/or when infrastructure logging
is enabled, loaders may log messages which will be printed out in the respective logger format (stats, infrastructure).
this.getLogger()
for logging which is a shortcut to compilation.getLogger()
with loader path and processed file. This kind of logging is stored to the Stats and formatted accordingly. It can be filtered and exported by the webpack user.this.getLogger('name')
to get an independent logger with a child name. Loader path and processed file is still added.this.getLogger ? this.getLogger() : console
to provide a fallback when an older webpack version is used which does not support getLogger
method.Logging output is an additional way to display messages to the end users.
Webpack logger is available to loaders and plugins. Emitting as part of the Stats and configured by the user in webpack configuration.
Benefits of custom logging API in webpack:
stats.json
By introducing webpack logging API we hope to unify the way webpack plugins and loaders emit logs and allow better ways to inspect build problems. Integrated logging solution supports plugins and loaders developers by improving their development experience. Paves the way for non-CLI webpack solutions like dashboards or other UIs.
my-webpack-plugin.js
const PLUGIN_NAME = 'my-webpack-plugin';
export class MyWebpackPlugin {
apply(compiler) {
// you can access Logger from compiler
const logger = compiler.getInfrastructureLogger(PLUGIN_NAME);
logger.log('log from compiler');
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
// you can also access Logger from compilation
const logger = compilation.getLogger(PLUGIN_NAME);
logger.info('log from compilation');
});
}
}
my-webpack-loader.js
module.exports = function (source) {
// you can get Logger with `this.getLogger` in your webpack loaders
const logger = this.getLogger('my-webpack-loader');
logger.info('hello Logger');
return source;
};
As you can see from the above my-webpack-plugin.js
example, there're two types of logging methods,
compilation.getLogger
compiler.getInfrastructureLogger
It's advised to use compilation.getLogger
when plugin/logging is related to the compilation, and they will be stored within the stats. For logging that happens outside the compilation cycle, use compiler.getInfrastructureLogger
instead.
logger.error(...)
: for error messageslogger.warn(...)
: for warningslogger.info(...)
: for important information messages. These messages are displayed by default. Only use this for messages that the user really needs to seelogger.log(...)
: for unimportant information messages. These messages are displayed only when user had opted-in to see themlogger.debug(...)
: for debugging information. These messages are displayed only when user had opted-in to see debug logging for specific moduleslogger.trace()
: to display a stack trace. Displayed like logger.debug
logger.group(...)
: to group messages. Displayed collapsed like logger.log
logger.groupEnd()
: to end a logging grouplogger.groupCollapsed(...)
: to group messages together. Displayed collapsed like logger.log
. Displayed expanded when logging level is set to 'verbose'
or 'debug'
.logger.status
: writes a temporary message, setting a new status, overrides the previous onelogger.clear()
: to print a horizontal line. Displayed like logger.log
logger.profile(...)
, logger.profileEnd(...)
: to capture a profile. Delegated to console.profile
when supportedRuntime logger API is only intended to be used as a development tool, it is not intended to be included in production mode.
const logging = require('webpack/lib/logging/runtime')
: to use the logger in runtime, require it directly from webpacklogging.getLogger('name')
: to get individual logger by namelogging.configureDefaultLogger(...)
: to override the default logger.const logging = require('webpack/lib/logging/runtime');
logging.configureDefaultLogger({
level: 'log',
debug: /something/,
});
logging.hooks.log
: to apply Plugins to the runtime loggerThis section covers all methods available in code compiled with webpack. When using webpack to bundle your application, you can pick from a variety of module syntax styles including ES6, CommonJS, and AMD.
While webpack supports multiple module syntaxes, we recommend following a single syntax for consistency and to avoid odd behaviors/bugs. Actually webpack would enforce the recommendation for .mjs
files, .cjs
files or .js
files when their nearest parent package.json
file contains a "type"
field with a value of either "module"
or "commonjs"
. Please pay attention to these enforcements before you read on:
.mjs
or .js
with "type": "module"
in package.json
require
, module.exports
or exports
import './src/App.mjs'
instead of import './src/App'
(you can disable this enforcement with Rule.resolve.fullySpecified
).cjs
or .js
with "type": "commonjs"
in package.json
import
nor export
is available.wasm
with "type": "module"
in package.json
Version 2 of webpack supports ES6 module syntax natively, meaning you can use import
and export
without a tool like babel to handle this for you. Keep in mind that you will still probably need babel for other ES6+ features. The following methods are supported by webpack:
Statically import
the export
s of another module.
import MyModule from './my-module.js';
import { NamedExport } from './other-module.js';
You can also import
Data URI:
import 'data:text/javascript;charset=utf-8;base64,Y29uc29sZS5sb2coJ2lubGluZSAxJyk7';
import {
number,
fn,
} from 'data:text/javascript;charset=utf-8;base64,ZXhwb3J0IGNvbnN0IG51bWJlciA9IDQyOwpleHBvcnQgY29uc3QgZm4gPSAoKSA9PiAiSGVsbG8gd29ybGQiOw==';
Export anything as a default
or named export.
// Named exports
export var Count = 5;
export function Multiply(a, b) {
return a * b;
}
// Default export
export default {
// Some data...
};
function(string path):Promise
Dynamically load modules. Calls to import()
are treated as split points, meaning the requested module and its children are split out into a separate chunk.
if (module.hot) {
import('lodash').then((_) => {
// Do something with lodash (a.k.a '_')...
});
}
It is not possible to use a fully dynamic import statement, such as import(foo)
. Because foo
could potentially be any path to any file in your system or project.
The import()
must contain at least some information about where the module is located. Bundling can be limited to a specific directory or set of files so that when you are using a dynamic expression - every module that could potentially be requested on an import()
call is included. For example, import(`./locale/${language}.json`)
will cause every .json
file in the ./locale
directory to be bundled into the new chunk. At run time, when the variable language
has been computed, any file like english.json
or german.json
will be available for consumption.
// imagine we had a method to get language from cookies or other storage
const language = detectVisitorLanguage();
import(`./locale/${language}.json`).then((module) => {
// do something with the translations
});
Inline comments to make features work. By adding comments to the import, we can do things such as name our chunk or select different modes. For a full list of these magic comments see the code below followed by an explanation of what these comments do.
// Single target
import(
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
/* webpackExports: ["default", "named"] */
/* webpackFetchPriority: "high" */
'module'
);
// Multiple possible targets
import(
/* webpackInclude: /\.json$/ */
/* webpackExclude: /\.noimport\.json$/ */
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
/* webpackPrefetch: true */
/* webpackPreload: true */
`./locale/${language}`
);
import(/* webpackIgnore: true */ 'ignored-module.js');
JavaScript Usage
Disables dynamic import parsing when set to true
.
When using import.meta.url
, it does not remain as-is; instead, it gets replaced based on the baseURI
. For modules, it is replaced with new URL("./", import.meta.url)
, and for other cases, it defaults to document.baseURI
. This ensures that relative URLs work correctly, aligning with the base URL context.
import(/* webpackIgnore: true */ 'ignored-module.js');
new URL(/* webpackIgnore: true */ 'file1.css', import.meta.url);
CSS Usage
The webpackIgnore
comment can control whether webpack processes a specific import or URL reference.
It works in certain cases out of the box but doesn’t support all cases by default due to performance reasons.
We support webpackIgnore
in the following cases:
@import /* webpackIgnore: false */ url(./basic.css);
.class {
color: red;
background: /* webpackIgnore: true */ url('./url/img.png');
}
.class {
background-image: image-set(
/*webpackIgnore: true*/ url(./url/img1x.png) 1x,
url(./url/img2x.png) 2x,
url(./url/img3x.png) 3x
);
}
A name for the new chunk. Since webpack 2.6.0, the placeholders [index]
and [request]
are supported within the given string to an incremented number or the actual resolved filename respectively. Adding this comment will cause our separate chunk to be named [my-chunk-name].js instead of [id].js.
Set fetchPriority
for specific dynamic imports. It's also possible to set a global default value for all dynamic imports by using the module.parser.javascript.dynamicImportFetchPriority
option.
import(
/* webpackFetchPriority: "high" */
'path/to/module'
);
Since webpack 2.6.0, different modes for resolving dynamic imports can be specified. The following options are supported:
'lazy'
(default): Generates a lazy-loadable chunk for each import()
ed module.'lazy-once'
: Generates a single lazy-loadable chunk that can satisfy all calls to import()
. The chunk will be fetched on the first call to import()
, and subsequent calls to import()
will use the same network response. Note that this only makes sense in the case of a partially dynamic statement, e.g. import(`./locales/${language}.json`)
, where multiple module paths that can potentially be requested.'eager'
: Generates no extra chunk. All modules are included in the current chunk and no additional network requests are made. A Promise
is still returned but is already resolved. In contrast to a static import, the module isn't executed until the call to import()
is made.'weak'
: Tries to load the module if the module function has already been loaded in some other way (e.g. another chunk imported it or a script containing the module was loaded). A Promise
is still returned, but only successfully resolves if the chunks are already on the client. If the module is not available, the Promise
is rejected. A network request will never be performed. This is useful for universal rendering when required chunks are always manually served in initial requests (embedded within the page), but not in cases where app navigation will trigger an import not initially served.Tells the browser that the resource is probably needed for some navigation in the future. Check out the guide for more information on how webpackPrefetch works.
Tells the browser that the resource might be needed during the current navigation. Check out the guide for more information on how webpackPreload works.
A regular expression that will be matched against during import resolution. Only modules that match will be bundled.
A regular expression that will be matched against during import resolution. Any module that matches will not be bundled.
Tells webpack to only bundle the specified exports of a dynamically import()
ed module. It can decrease the output size of a chunk. Available since webpack 5.0.0-beta.18.
The goal of CommonJS is to specify an ecosystem for JavaScript outside the browser. The following CommonJS methods are supported by webpack:
require(dependency: String);
Synchronously retrieve the exports from another module. The compiler will ensure that the dependency is available in the output bundle.
var $ = require('jquery');
var myModule = require('my-module');
It's possible to enable magic comments for require
as well, see module.parser.javascript.commonjsMagicComments
for more.
require.resolve(dependency: String);
Synchronously retrieve a module's ID. The compiler will ensure that the dependency is available in the output bundle. It is recommended to treat it as an opaque value which can only be used with require.cache[id]
or __webpack_require__(id)
(best to avoid such usage).
See module.id
for more information.
Multiple requires of the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache causes new module execution and a new export.
var d1 = require('dependency');
require('dependency') === d1;
delete require.cache[require.resolve('dependency')];
require('dependency') !== d1;
// in file.js
require.cache[module.id] === module;
require('./file.js') === module.exports;
delete require.cache[module.id];
require.cache[module.id] === undefined;
require('./file.js') !== module.exports; // in theory; in praxis this causes a stack overflow
require.cache[module.id] !== module;
require.ensure(
dependencies: String[],
callback: function(require),
errorCallback: function(error),
chunkName: String
)
Split out the given dependencies
to a separate bundle that will be loaded asynchronously. When using CommonJS module syntax, this is the only way to dynamically load dependencies. Meaning, this code can be run within execution, only loading the dependencies
if certain conditions are met.
var a = require('normal-dep');
if (module.hot) {
require.ensure(['b'], function (require) {
var c = require('c');
// Do something special...
});
}
The following parameters are supported in the order specified above:
dependencies
: An array of strings declaring all modules required for the code in the callback
to execute.callback
: A function that webpack will execute once the dependencies are loaded. An implementation of the require
function is sent as a parameter to this function. The function body can use this to further require()
modules it needs for execution.errorCallback
: A function that is executed when webpack fails to load the dependencies.chunkName
: A name given to the chunk created by this particular require.ensure()
. By passing the same chunkName
to various require.ensure()
calls, we can combine their code into a single chunk, resulting in only one bundle that the browser must load.Asynchronous Module Definition (AMD) is a JavaScript specification that defines an interface for writing and loading modules. The following AMD methods are supported by webpack:
define([name: String], [dependencies: String[]], factoryMethod: function(...))
If dependencies
are provided, factoryMethod
will be called with the exports of each dependency (in the same order). If dependencies
are not provided, factoryMethod
is called with require
, exports
and module
(for compatibility!). If this function returns a value, this value is exported by the module. The compiler ensures that each dependency is available.
define(['jquery', 'my-module'], function ($, myModule) {
// Do something with $ and myModule...
// Export a function
return function doSomething() {
// ...
};
});
define(value: !Function)
This will export the provided value
. The value
here can be anything except a function.
define({
answer: 42,
});
require(dependencies: String[], [callback: function(...)])
Similar to require.ensure
, this will split the given dependencies
into a separate bundle that will be loaded asynchronously. The callback
will be called with the exports of each dependency in the dependencies
array.
require(['b'], function (b) {
var c = require('c');
});
The internal LabeledModulesPlugin
enables you to use the following methods for exporting and requiring within your modules:
Export the given value
. The label can occur before a function declaration or a variable declaration. The function name or variable name is the identifier under which the value is exported.
export: var answer = 42;
export: function method(value) {
// Do something...
};
Make all exports from the dependency available in the current scope. The require
label can occur before a string. The dependency must export values with the export
label. CommonJS or AMD modules cannot be consumed.
some-dependency.js
export: var answer = 42;
export: function method(value) {
// Do something...
};
require: 'some-dependency';
console.log(answer);
method(...);
Aside from the module syntaxes described above, webpack also allows a few custom, webpack-specific methods:
require.context(
(directory: String),
(includeSubdirs: Boolean) /* optional, default true */,
(filter: RegExp) /* optional, default /^\.\/.*$/, any file */,
(mode: String) /* optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', default 'sync' */
);
Specify a whole group of dependencies using a path to the directory
, an option to includeSubdirs
, a filter
for more fine grained control of the modules included, and a mode
to define the way how loading will work. Underlying modules can then be resolved later on:
var context = require.context('components', true, /\.html$/);
var componentA = context.resolve('componentA');
If mode
is set to 'lazy'
, the underlying modules will be loaded asynchronously:
var context = require.context('locales', true, /\.json$/, 'lazy');
context('localeA').then((locale) => {
// do something with locale
});
The full list of available modes and their behavior is described in import()
documentation.
require.include((dependency: String));
Include a dependency
without executing it. This can be used for optimizing the position of a module in the output chunks.
require.include('a');
require.ensure(['a', 'b'], function (require) {
/* ... */
});
require.ensure(['a', 'c'], function (require) {
/* ... */
});
This will result in the following output:
file.js
and a
b
c
Without require.include('a')
it would be duplicated in both anonymous chunks.
Similar to require.resolve
, but this won't pull the module
into the bundle. It's what is considered a "weak" dependency.
if (__webpack_modules__[require.resolveWeak('module')]) {
// Do something when module is available...
}
if (require.cache[require.resolveWeak('module')]) {
// Do something when module was loaded before...
}
// You can perform dynamic resolves ("context")
// similarly to other require/import methods.
const page = 'Foo';
__webpack_modules__[require.resolveWeak(`./page/${page}`)];
If the module source contains a require that cannot be statically analyzed, critical dependencies warning is emitted.
Example code:
someFn(require);
require.bind(null);
require(variable);
This section covers all variables available in code compiled with webpack. Modules will have access to certain data from the compilation process through module
and other variables.
This is false
if the module is currently executing, and true
if the sync execution has finished.
Indicates whether or not Hot Module Replacement is enabled and provides an interface to the process. See the HMR API page for details.
The ID of the current module.
module.id === require.resolve('./file.js');
Defines the value that will be returned when a consumer makes a require
call to the module (defaults to a new object).
module.exports = function doSomething() {
// Do something...
};
This variable is equal to the default value of module.exports
(i.e. an object). If module.exports
gets overwritten, exports
will no longer be exported.
exports.someValue = 42;
exports.anObject = {
x: 123,
};
exports.aFunction = function doSomething() {
// Do something
};
See node.js global.
For compatibility reasons webpack polyfills the global
variable by default.
Depending on the configuration option node.__dirname
:
false
: Not definedmock
: equal to '/'
true
: node.js __dirnameIf used inside an expression that is parsed by the Parser, the configuration option is treated as true
.
The import.meta
exposes context-specific metadata to a JavaScript module, such as the URL of the module. It is only available in ESM.
Please note that webpack does not support direct access to import.meta
. Instead, you should access its properties or use destructuring assignment. E.g.,
// webpack will warn about this
Object.keys(import.meta);
// fine to use
console.log(import.meta.url);
const { url } = import.meta;
Returns the absolute file:
URL of the module.
src/index.js
console.log(import.meta.url); // output something like `file:///path/to/your/project/src/index.js`
Returns the webpack version.
src/index.js
console.log(import.meta.webpack); // output `5` for webpack 5
Webpack specific. An alias for module.hot
, however import.meta.webpackHot
can be used in strict ESM while module.hot
can't.
Returns the same value as require.context
but only for javascript/auto
and javascript/esm
.
Type:
(
request: string,
options?: {
recursive?: boolean;
regExp?: RegExp;
include?: RegExp;
exclude?: RegExp;
preload?: boolean | number;
prefetch?: boolean | number;
chunkName?: string;
exports?: string | string[][];
mode?: 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once';
}
) => webpack.Context;
Available: 5.70.0+
Example:
const contextRequire = import.meta.webpackContext('.', {
recursive: false,
regExp: /two/,
mode: 'weak',
exclude: /three/,
});
Depending on the configuration option node.__filename
:
false
: Not definedmock
: equal to '/index.js'
true
: node.js __filenameIf used inside an expression that is parsed by the Parser, the configuration option is treated as true
.
The resource query of the current module. If the following require
call was made, then the query string would be available in file.js
.
require('file.js?test');
file.js
__resourceQuery === '?test';
Equals the configuration option's output.publicPath
.
The raw require function. This expression isn't parsed by the Parser for dependencies.
The internal chunk loading function. Takes one argument:
chunkId
The id for the chunk to load.Example to load chunks from alternate public path when one failed:
const originalLoad = __webpack_chunk_load__;
const publicPaths = ['a', 'b', 'c'];
__webpack_chunk_load__ = async (id) => {
let error;
for (const path of publicPaths) {
__webpack_public_path__ = path;
try {
return await originalLoad(id);
} catch (e) {
error = e;
}
}
throw error;
};
import('./module-a').then((moduleA) => {
// now webpack will use the custom __webpack_chunk_load__ to load chunk
});
It provides access to the the current module
. module
is not available in strict ESM.
It provides access to the ID of current module
(module.id
). module
is not available in strict ESM.
Access to the internal object of all modules.
It provides access to the hash of the compilation.
function (chunkId)
It provides filename of the chunk by its id.
It is assignable, which allows changing the filename used by the runtime. For example, it can be used to determine the final path when loading chunks.
const oldFn = __webpack_get_script_filename__;
__webpack_get_script_filename__ = (chunkId) => {
const filename = oldFn(chunkId);
return filename + '.changed';
};
Generates a require
function that is not parsed by webpack. Can be used to do cool stuff with a global require function if available.
In modules, __webpack_exports_info__
is available to allow exports introspection:
__webpack_exports_info__
is always true
__webpack_exports_info__.<exportName>.used
is false
when the export is known to be unused, true
otherwise
__webpack_exports_info__.<exportName>.useInfo
is
false
when the export is known to be unusedtrue
when the export is known to be usednull
when the export usage could depend on runtime conditionsundefined
when no info is available__webpack_exports_info__.<exportName>.provideInfo
is
false
when the export is known to be not providedtrue
when the export is known to be providednull
when the export provision could depend on runtime conditionsundefined
when no info is availableAccessing the info from nested exports is possible: i. e. __webpack_exports_info__.<exportName>.<exportName>.<exportName>.used
Check whether exports can be mangled with __webpack_exports_info__.<name>.canMangle
Test whether or not the given module is bundled by webpack.
if (__webpack_is_included__('./module-a.js')) {
// do something
}
Change base URI at runtime.
Type: string
Available: 5.21.0+
Example:
__webpack_base_uri__ = 'https://example.com';
Access the runtime id of current entry.
This is a webpack specific feature and it's available since webpack 5.25.0.
src/index.js
console.log(__webpack_runtime_id__ === 'main');
Equals the configuration option debug
.
The Compiler
module is the main engine that creates a compilation instance
with all the options passed through the CLI or Node API. It extends the
Tapable
class in order to register and call plugins. Most user-facing plugins
are first registered on the Compiler
.
When developing a plugin for webpack, you might want to know where each hook is called. To learn this, search for hooks.<hook name>.call
across the webpack source.
The Compiler
supports watching which monitors the file
system and recompiles as files change. When in watch mode, the compiler will
emit the additional events such as watchRun
, watchClose
, and invalid
.
This is typically used in development, usually under
the hood of tools like webpack-dev-server
, so that the developer doesn't
need to re-compile manually every time. Watch mode can also be entered via the
CLI.
The following lifecycle hooks are exposed by the compiler
and can be accessed
as such:
compiler.hooks.someHook.tap('MyPlugin', (params) => {
/* ... */
});
Depending on the hook type, tapAsync
and tapPromise
may also be available.
For the description of hook types, see the Tapable docs.
SyncHook
Called while preparing the compiler environment, right after initializing the plugins in the configuration file.
SyncHook
Called right after the environment
hook, when the compiler environment setup is complete.
SyncBailHook
Called after the entry
configuration from webpack options has been processed.
compiler.hooks.entryOption.tap('MyPlugin', (context, entry) => {
/* ... */
});
SyncHook
Called after setting up initial set of internal plugins.
compiler
SyncHook
Triggered after resolver setup is complete.
compiler
SyncHook
Called when a compiler object is initialized.
AsyncSeriesHook
Adds a hook right before running the compiler.
compiler
AsyncSeriesHook
Hook into the compiler before it begins reading records
.
compiler
AsyncSeriesHook
Executes a plugin during watch mode after a new compilation is triggered but before the compilation is actually started.
compiler
SyncHook
Called after a NormalModuleFactory is created.
normalModuleFactory
SyncHook
Runs a plugin after a ContextModuleFactory is created.
contextModuleFactory
AsyncSeriesHook
Executes a plugin after compilation parameters are created.
compilationParams
The compilationParams
variable is initialized as follows:
compilationParams = {
normalModuleFactory,
contextModuleFactory,
};
This hook can be used to add/modify the compilation parameters:
compiler.hooks.beforeCompile.tapAsync('MyPlugin', (params, callback) => {
params['MyPlugin - data'] = 'important stuff my plugin will use later';
callback();
});
SyncHook
Called right after beforeCompile
, before a new compilation is created. This hook is not copied to child compilers.
compilationParams
SyncHook
Executed while initializing the compilation, right before emitting the compilation
event. This hook is not copied to child compilers.
compilation
, compilationParams
SyncHook
Runs a plugin after a compilation has been created.
compilation
, compilationParams
AsyncParallelHook
Executed before finishing the compilation. This hook is not copied to child compilers.
compilation
AsyncSeriesHook
Called after finishing and sealing the compilation.
compilation
SyncBailHook
Called before emitting assets. Should return a boolean telling whether to emit.
compilation
compiler.hooks.shouldEmit.tap('MyPlugin', (compilation) => {
// return true to emit the output, otherwise false
return true;
});
AsyncSeriesHook
Executed right before emitting assets to output dir. This hook is not copied to child compilers.
compilation
AsyncSeriesHook
Called after emitting assets to output directory. This hook is not copied to child compilers.
compilation
AsyncSeriesHook
Executed when an asset has been emitted. Provides access to information about the emitted asset, such as its output path and byte content.
file
, info
For example, you may access the asset's content buffer via info.content
:
compiler.hooks.assetEmitted.tap(
'MyPlugin',
(file, { content, source, outputPath, compilation, targetPath }) => {
console.log(content); // <Buffer 66 6f 6f 62 61 72>
}
);
AsyncSeriesHook
Executed when the compilation has completed. This hook is not copied to child compilers.
stats
AsyncSeriesHook
This hook allows you to do a one more additional pass of the build.
SyncHook
Called if the compilation fails.
error
SyncHook
Executed when a watching compilation has been invalidated. This hook is not copied to child compilers.
fileName
, changeTime
SyncHook
Called when a watching compilation has stopped.
AsyncSeriesHook
Called when the compiler is closing.
SyncBailHook
Allows to use infrastructure logging when enabled in the configuration via infrastructureLogging
option.
name
, type
, args
SyncBailHook
Allows to log into stats when enabled, see stats.logging
, stats.loggingDebug
and stats.loggingTrace
options.
origin
, logEntry
The Compilation
module is used by the Compiler
to create new compilations
(or builds). A compilation
instance has access to all modules and their
dependencies (most of which are circular references). It is the literal
compilation of all the modules in the dependency graph of an application.
During the compilation phase, modules are loaded, sealed, optimized, chunked,
hashed and restored.
The Compilation
class also extends Tapable
and provides the following
lifecycle hooks. They can be tapped the same way as compiler hooks:
compilation.hooks.someHook.tap(/* ... */);
As with the compiler
, tapAsync
and tapPromise
may also be available
depending on the type of hook.
SyncHook
Triggered before a module build has started, can be used to modify the module.
module
compilation.hooks.buildModule.tap(
'SourceMapDevToolModuleOptionsPlugin',
(module) => {
module.useSourceMap = true;
}
);
SyncHook
Fired before rebuilding a module.
module
SyncHook
Run when a module build has failed.
module
error
SyncHook
Executed when a module has been built successfully.
module
AsyncSeriesHook
Called when all modules have been built without errors.
modules
SyncHook
Executed when a module has been rebuilt, in case of both success or with errors.
module
SyncHook
Fired when the compilation stops accepting new modules.
SyncHook
Fired when a compilation begins accepting new modules.
SyncBailHook
Fired at the beginning of dependency optimization.
modules
SyncHook
Fired after the dependency optimization.
modules
SyncHook
The afterChunks
hook is invoked following the creation of the chunks and module graph, and prior to their optimization.
This hook provides an opportunity to examine, analyze, and modify the chunk graph if necessary.
Here's an example of how to utilize the compilation.hooks.afterChunks
hook.
chunks
SyncHook
Triggered at the beginning of the optimization phase.
SyncBailHook
Called at the beginning of the module optimization phase. A plugin can tap into this hook to perform optimizations on modules.
modules
SyncHook
Called after modules optimization has completed.
modules
SyncBailHook
Called at the beginning of the chunk optimization phase. A plugin can tap into this hook to perform optimizations on chunks.
chunks
SyncHook
Fired after chunk optimization has completed.
chunks
AsyncSeriesHook
Called before optimizing the dependency tree. A plugin can tap into this hook to perform a dependency tree optimization.
chunks
modules
SyncHook
Called after the dependency tree optimization has completed with success.
chunks
modules
SyncBailHook
Called after the tree optimization, at the beginning of the chunk modules optimization. A plugin can tap into this hook to perform optimizations of chunk modules.
chunks
modules
SyncHook
Called after the chunkmodules optimization has completed successfully.
chunks
modules
SyncBailHook
Called to determine whether or not to store records. Returning anything !== false
will prevent every other "record" hook from being executed (record
, recordModules
, recordChunks
and recordHash
).
SyncHook
Restore module information from records.
modules
records
SyncHook
Executed before assigning an id
to each module.
modules
SyncHook
Called to assign an id
to each module.
modules
SyncHook
Called at the beginning of the modules id
optimization.
modules
SyncHook
Called when the modules id
optimization phase has completed.
modules
SyncHook
Restore chunk information from records.
chunks
records
SyncHook
Executed before assigning an id
to each chunk.
chunks
SyncHook
Called to assign an id
to each chunk.
chunks
SyncHook
Called at the beginning of the chunks id
optimization phase.
chunks
SyncHook
Triggered after chunk id
optimization has finished.
chunks
SyncHook
Store module info to the records. This is triggered if shouldRecord
returns a truthy value.
modules
records
SyncHook
Store chunk info to the records. This is only triggered if shouldRecord
returns a truthy value.
chunks
records
SyncHook
Called before modules are hashed.
syncHook
Called after modules are hashed.
SyncHook
Called before the compilation is hashed.
SyncHook
Called after the compilation is hashed.
SyncHook
Store information about record hash to the records
. This is only triggered if shouldRecord
returns a truthy value.
records
SyncHook
Store information about the compilation
to the records
. This is only triggered if shouldRecord
returns a truthy value.
compilation
records
SyncHook
Executed before module assets creation.
SyncHook
Create additional assets for the chunks.
chunks
SyncBailHook
Called to determine whether or not generate chunks assets. Returning anything !== false
will allow chunk assets generation.
SyncHook
Executed before creating the chunks assets.
AsyncSeriesHook
Create additional assets for the compilation. This hook can be used to download an image, for example:
compilation.hooks.additionalAssets.tapAsync('MyPlugin', (callback) => {
download('https://img.shields.io/npm/v/webpack.svg', function (resp) {
if (resp.status === 200) {
compilation.assets['webpack-version.svg'] = toAsset(resp);
callback();
} else {
callback(
new Error('[webpack-example-plugin] Unable to download the image')
);
}
});
});
AsyncSeriesHook
Optimize any chunk assets. The assets are stored in compilation.assets
. A
Chunk
has a property files
which points to all files created by a chunk.
Any additional chunk assets are stored in compilation.additionalChunkAssets
.
chunks
Here's an example that adds a banner to each chunk.
compilation.hooks.optimizeChunkAssets.tapAsync(
'MyPlugin',
(chunks, callback) => {
chunks.forEach((chunk) => {
chunk.files.forEach((file) => {
compilation.assets[file] = new ConcatSource(
'/**Sweet Banner**/',
'\n',
compilation.assets[file]
);
});
});
callback();
}
);
SyncHook
The chunk assets have been optimized.
chunks
Here's an example plugin from @boopathi that outputs exactly what went into each chunk.
compilation.hooks.afterOptimizeChunkAssets.tap('MyPlugin', (chunks) => {
chunks.forEach((chunk) => {
console.log({
id: chunk.id,
name: chunk.name,
includes: chunk.getModules().map((module) => module.request),
});
});
});
AsyncSeriesHook
Optimize all assets stored in compilation.assets
.
assets
SyncHook
The assets have been optimized.
assets
AsyncSeriesHook
Asset processing.
Hook parameters:
name: string
— a name of the pluginstage: Stage
— a stage to tap into (see the list of supported stages below)additionalAssets?: true | (assets, [callback]) => (void | Promise<void>)
— a callback for additional assets (see below)Callback parameters:
assets: { [pathname: string]: Source }
— a plain object, where key is the asset's pathname, and the value is data of the asset represented by the Source
.Example:
compilation.hooks.processAssets.tap(
{
name: 'MyPlugin',
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS, // see below for more stages
},
(assets) => {
console.log('List of assets and their sizes:');
Object.entries(assets).forEach(([pathname, source]) => {
console.log(`— ${pathname}: ${source.size()} bytes`);
});
}
);
In addition to name
and stage
, you can pass an additionalAssets
5.8.0+ option which accepts either a value of true
or a callback function that receives assets
as a first argument:
true
— run the provided callback again for assets added later by plugins.
In this mode, the callback will be called multiple times: once for assets added prior to the specified stage, and additional times for assets added by plugins later (on this or next stages).
compilation.hooks.processAssets.tap(
{
name: 'MyPlugin',
stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
additionalAssets: true,
},
(assets) => {
// this function will be called multiple times with each bulk of assets
}
);
(assets, [callback]) => (void | Promise<void>)
— run the specified callback against assets added by plugins later (on this or next stages). The callback must respect the type of the tap method used (e.g. when used with tapPromise()
, it should return a promise).
compilation.hooks.processAssets.tap(
{
name: 'MyPlugin',
stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
additionalAssets: (assets) => {
// this function potentially could be called multiple times for assets added on later stages
},
},
(assets) => {
// this function will be called once with assets added by plugins on prior stages
}
);
Here's a list of supported stages (in the order of processing):
PROCESS_ASSETS_STAGE_ADDITIONAL
— add additional assets to the compilation.PROCESS_ASSETS_STAGE_PRE_PROCESS
— basic preprocessing of the assets.PROCESS_ASSETS_STAGE_DERIVED
— derive new assets from the existing assets.PROCESS_ASSETS_STAGE_ADDITIONS
— add additional sections to the existing assets e.g. banner or initialization code.PROCESS_ASSETS_STAGE_OPTIMIZE
— optimize existing assets in a general way.PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT
— optimize the count of existing assets, e.g. by merging them.PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY
— optimize the compatibility of existing assets, e.g. add polyfills or vendor prefixes.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
— optimize the size of existing assets, e.g. by minimizing or omitting whitespace.PROCESS_ASSETS_STAGE_DEV_TOOLING
— add development tooling to the assets, e.g. by extracting a source map.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE
5.8.0+ — optimize the numbers of existing assets, e.g. by inlining assets into other assets.PROCESS_ASSETS_STAGE_SUMMARIZE
— summarize the list of existing assets.PROCESS_ASSETS_STAGE_OPTIMIZE_HASH
— optimize the hashes of the assets, e.g. by generating real hashes of the asset content.PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER
— optimize the transfer of existing assets, e.g. by preparing a compressed (gzip) file as separate asset.PROCESS_ASSETS_STAGE_ANALYSE
— analyze the existing assets.PROCESS_ASSETS_STAGE_REPORT
— creating assets for the reporting purposes.The "asset info" metadata is not automatically provided for this hook. If needed, you will have to resolve this metadata manually using the compilation instance and the provided asset pathname. This will be improved in a future version of the webpack.
Example:
compilation.hooks.processAssets.tap(
{
/** … */
},
(assets) => {
Object.entries(assets).forEach(([pathname, source]) => {
const assetInfo = compilation.assetsInfo.get(pathname);
// @todo: do something with "pathname", "source" and "assetInfo"
});
}
);
SyncHook
Called after the processAssets
hook had finished without error.
SyncBailHook
Called to determine if the compilation needs to be unsealed to include other files.
AsyncSeriesHook
Executed right after needAdditionalSeal
.
SyncHook
Triggered to emit the hash for each chunk.
chunk
chunkHash
SyncHook
Called when an asset from a module was added to the compilation.
module
filename
SyncHook
Triggered when an asset from a chunk was added to the compilation.
chunk
filename
SyncWaterfallHook
Called to determine the path of an asset.
path
options
SyncBailHook
Called to determine if an asset needs to be processed further after being emitted.
SyncHook
Executed after setting up a child compiler.
childCompiler
compilerName
compilerIndex
Since webpack v5 normalModuleLoader
hook was removed. Now to access the loader use NormalModule.getCompilationHooks(compilation).loader
instead.
HookMap
This HookMap is like a list of actions that gets triggered when a preset is used. It takes in an options object. When a plugin manages a preset, it should change settings in this object carefully without replacing existing ones.
options
context
Here's an illustrative plugin example:
compilation.hooks.statsPreset.for('my-preset').tap('MyPlugin', (options) => {
if (options.all === undefined) options.all = true;
});
This plugin ensures that for the preset 'my-preset'
, if the all
option is undefined, it defaults to true.
SyncHook
This hook is used to transform an options object into a consistent format that can be easily used by subsequent hooks. It also ensures that missing options are set to their default values.
options
context
Here's an illustrative plugin example:
compilation.hooks.statsNormalize.tap('MyPlugin', (options) => {
if (options.myOption === undefined) options.myOption = [];
if (!Array.isArray(options.myOption)) options.myOptions = [options.myOptions];
});
In this plugin, if the myOption
is missing, it sets it to an empty array. Additionally, it ensures that myOption
is always an array even if it was originally defined as a single value.
This hook provides access to the StatsFactory
class for specific options.
statsFactory
options
HookMap
object
data
context
data
contains the class. object is an object to which properties should be added. context
provides contextual information, such as classes on the path.
Example:
compilation.hooks.statsFactory.tap('MyPlugin', (statsFactory, options) => {
statsFactory.hooks.extract
.for('compilation')
.tap('MyPlugin', (object, compilation) => {
object.customProperty = MyPlugin.getCustomValue(compilation);
});
});
HookMap
Called with the result on each level.
result
context
This hook provides access to the StatsPrinter
class for specific options.
statsPrinter
options
HookMap
This hook is called when a part should be printed.
object
context
HookMap
This hook is called for the resulting string for a part.
result
context
The ContextModuleFactory
module is used by the Compiler
to generate dependencies from webpack specific require.context API. It resolves the requested directory, generates requests for each file and filters against passed regExp. Matching dependencies then passes through NormalModuleFactory.
The ContextModuleFactory
class extends Tapable
and provides the following
lifecycle hooks. They can be tapped the same way as compiler hooks:
ContextModuleFactory.hooks.someHook.tap(/* ... */);
As with the compiler
, tapAsync
and tapPromise
may also be available
depending on the type of hook.
AsyncSeriesWaterfallHook
Called before resolving the requested directory. The request can be ignored by returning false
.
data
AsyncSeriesWaterfallHook
Called after the requested directory resolved.
data
SyncWaterfallHook
Called after directory contents are read. On recursive mode, calls for each sub-directory as well. Callback parameter is an array of all file and folder names in each directory.
fileNames
AsyncSeriesWaterfallHook
Called for each file after the request is created but before filtering against regExp.
request
options
The parser
instance, found in the compiler
, is used to parse each module
being processed by webpack. The parser
is yet another webpack class that
extends tapable
and provides a variety of tapable
hooks that can be used by
plugin authors to customize the parsing process.
The parser
is found within NormalModuleFactory and therefore takes little
more work to access:
compiler.hooks.normalModuleFactory.tap('MyPlugin', (factory) => {
factory.hooks.parser
.for('javascript/auto')
.tap('MyPlugin', (parser, options) => {
parser.hooks.someHook.tap(/* ... */);
});
});
As with the compiler
, tapAsync
and tapPromise
may also be available
depending on the type of hook.
The following lifecycle hooks are exposed by the parser
and can be accessed
as such:
SyncBailHook
Triggered when evaluating an expression consisting in a typeof
of a free variable
identifier
expression
parser.hooks.evaluateTypeof
.for('myIdentifier')
.tap('MyPlugin', (expression) => {
/* ... */
return expressionResult;
});
This will trigger the evaluateTypeof
hook:
const a = typeof myIdentifier;
This won't trigger:
const myIdentifier = 0;
const b = typeof myIdentifier;
SyncBailHook
Called when evaluating an expression.
expressionType
expression
For example:
index.js
const a = new String();
MyPlugin.js
parser.hooks.evaluate.for('NewExpression').tap('MyPlugin', (expression) => {
/* ... */
return expressionResult;
});
Where the expressions types are:
'ArrowFunctionExpression'
'AssignmentExpression'
'AwaitExpression'
'BinaryExpression'
'CallExpression'
'ClassExpression'
'ConditionalExpression'
'FunctionExpression'
'Identifier'
'LogicalExpression'
'MemberExpression'
'NewExpression'
'ObjectExpression'
'SequenceExpression'
'SpreadElement'
'TaggedTemplateExpression'
'TemplateLiteral'
'ThisExpression'
'UnaryExpression'
'UpdateExpression'
SyncBailHook
Called when evaluating an identifier that is a free variable.
identifier
expression
SyncBailHook
Called when evaluating an identifier that is a defined variable.
identifier
expression
SyncBailHook
Called when evaluating a call to a member function of a successfully evaluated expression.
identifier
expression
param
This expression will trigger the hook:
index.js
const a = expression.myFunc();
MyPlugin.js
parser.hooks.evaluateCallExpressionMember
.for('myFunc')
.tap('MyPlugin', (expression, param) => {
/* ... */
return expressionResult;
});
SyncBailHook
General purpose hook that is called for every parsed statement in a code fragment.
statement
parser.hooks.statement.tap('MyPlugin', (statement) => {
/* ... */
});
Where the statement.type
could be:
'BlockStatement'
'VariableDeclaration'
'FunctionDeclaration'
'ReturnStatement'
'ClassDeclaration'
'ExpressionStatement'
'ImportDeclaration'
'ExportAllDeclaration'
'ExportDefaultDeclaration'
'ExportNamedDeclaration'
'IfStatement'
'SwitchStatement'
'ForInStatement'
'ForOfStatement'
'ForStatement'
'WhileStatement'
'DoWhileStatement'
'ThrowStatement'
'TryStatement'
'LabeledStatement'
'WithStatement'
SyncBailHook
Called when parsing an if statement. Same as the statement
hook, but triggered only when statement.type == 'IfStatement'
.
statement
SyncBailHook
Called when parsing statements with a label. Those statements have statement.type === 'LabeledStatement'
.
labelName
statement
SyncBailHook
Called for every import statement in a code fragment. The source
parameter contains the name of the imported file.
statement
source
The following import statement will trigger the hook once:
index.js
import _ from 'lodash';
MyPlugin.js
parser.hooks.import.tap('MyPlugin', (statement, source) => {
// source == 'lodash'
});
SyncBailHook
Called for every specifier of every import
statement.
statement
source
exportName
identifierName
The following import statement will trigger the hook twice:
index.js
import _, { has } from 'lodash';
MyPlugin.js
parser.hooks.importSpecifier.tap(
'MyPlugin',
(statement, source, exportName, identifierName) => {
/* First call
source == 'lodash'
exportName == 'default'
identifierName == '_'
*/
/* Second call
source == 'lodash'
exportName == 'has'
identifierName == 'has'
*/
}
);
SyncBailHook
Called for every export
statement in a code fragment.
statement
SyncBailHook
Called for every export
-import statement eg: export * from 'otherModule';
.
statement
source
SyncBailHook
Called for every export
statement exporting a declaration.
statement
declaration
Those exports will trigger this hook:
export const myVar = 'hello'; // also var, let
export function FunctionName() {}
export class ClassName {}
SyncBailHook
Called for every export
statement exporting an expression e.g.export default expression;
.
statement
declaration
SyncBailHook
Called for every specifier of every export
statement.
statement
identifierName
exportName
index
SyncBailHook
Called for every specifier of every export
-import statement.
statement
source
identifierName
exportName
index
SyncBailHook
Called when parsing a variable declaration.
declaration
SyncBailHook
Called when parsing a variable declaration defined using let
declaration
SyncBailHook
Called when parsing a variable declaration defined using const
declaration
SyncBailHook
Called when parsing a variable declaration defined using var
declaration
SyncBailHook
Triggered before renaming an identifier to determine if the renaming is allowed. This is usually used together with the rename
hook.
identifier
expression
var a = b;
parser.hooks.canRename.for('b').tap('MyPlugin', (expression) => {
// returning true allows renaming
return true;
});
SyncBailHook
Triggered when renaming to get the new identifier. This hook will be called only if canRename
returns true
.
identifier
expression
var a = b;
parser.hooks.rename.for('b').tap('MyPlugin', (expression) => {});
SyncBailHook
Called when parsing an AssignmentExpression
before parsing the assigned expression.
identifier
expression
a += b;
parser.hooks.assigned.for('a').tap('MyPlugin', (expression) => {
// this is called before parsing b
});
SyncBailHook
Called when parsing an AssignmentExpression
before parsing the assign expression.
identifier
expression
a += b;
parser.hooks.assigned.for('a').tap('MyPlugin', (expression) => {
// this is called before parsing a
});
SyncBailHook
Triggered when parsing the typeof
of an identifier
identifier
expression
SyncBailHook
Called when parsing a function call.
identifier
expression
eval(/* something */);
parser.hooks.call.for('eval').tap('MyPlugin', (expression) => {});
SyncBailHook
Triggered when parsing a call to a member function of an object.
objectIdentifier
expression, properties
myObj.anyFunc();
parser.hooks.callMemberChain
.for('myObj')
.tap('MyPlugin', (expression, properties) => {});
SyncBailHook
Invoked when parsing a new
expression.
identifier
expression
new MyClass();
parser.hooks.new.for('MyClass').tap('MyPlugin', (expression) => {});
SyncBailHook
Called when parsing an expression.
identifier
expression
const a = this;
parser.hooks.expression.for('this').tap('MyPlugin', (expression) => {});
SyncBailHook
Called when parsing a ConditionalExpression
e.g. condition ? a : b
expression
SyncBailHook
Get access to the abstract syntax tree (AST) of a code fragment
ast
comments
The NormalModuleFactory
module is used by the Compiler
to generate modules. Starting with entry points, it resolves each request, parses the content to find further requests, and keeps crawling through files by resolving all and parsing any new files. At last stage, each dependency becomes a Module instance.
The NormalModuleFactory
class extends Tapable
and provides the following
lifecycle hooks. They can be tapped the same way as compiler hooks:
NormalModuleFactory.hooks.someHook.tap(/* ... */);
NormaleModuleFactory creates Parser
and Generator
instances which can be accessed by HookMaps. Identifier must be passed to tap into these:
NormalModuleFactory.hooks.someHook.for('identifier').tap(/* ... */);
As with the compiler
, tapAsync
and tapPromise
may also be available
depending on the type of hook.
AsyncSeriesBailHook
Called when a new dependency request is encountered. A dependency can be ignored by returning false
. Otherwise, it should return undefined
to proceed.
resolveData
AsyncSeriesBailHook
Called before initiating resolve. It should return undefined
to proceed.
resolveData
AsyncSeriesBailHook
Called before the request is resolved. A dependency can be ignored by returning false
. Returning a Module instance would finalize the process. Otherwise, it should return undefined
to proceed.
resolveData
AsyncSeriesBailHook
Called before a request with scheme (URI) is resolved.
resolveData
AsyncSeriesBailHook
Called after the request is resolved.
resolveData
AsyncSeriesBailHook
Called before a NormalModule
instance is created.
createData
resolveData
HookMap<SyncBailHook>
A hook that allows you to override the NormalModule
class when creating modules. This hook is called after the createModule
hook and before the module
hook.
Hook Parameters: identifier
Callback Parameters: createData
resolveData
SyncWaterfallHook
Called after a NormalModule
instance is created.
module
createData
resolveData
HookMap<SyncBailHook>
Called before a Parser
instance is created. parserOptions
is options in module.parser for the corresponding identifier or an empty object.
Hook Parameters: identifier
Callback Parameters: parserOptions
HookMap<SyncHook>
Fired after a Parser
instance is created.
Hook Parameters: identifier
Callback Parameters: parser
parserOptions
Possible default identifiers:
javascript/auto
javascript/dynamic
javascript/esm
json
webassembly/sync
webassembly/async
asset
HookMap<SyncBailHook>
Called before a Generator
instance is created. generatorOptions
is options in module.parser for the corresponding identifier or an empty object.
Hook Parameters: identifier
Callback Parameters: generatorOptions
HookMap<SyncHook>
Called after a Generator
instance is created.
Hook Parameters: identifier
Callback Parameters: generator
generatorOptions
Possible default identifiers:
json
webassembly/sync
webassembly/async
asset
asset/source
asset/resource
asset/inline
The Compilation object has many methods and hooks available. On this page, we will list the available methods and properties.
function
Returns Stats object for the current compilation.
function (module, callback)
Adds a module to the current compilation.
Parameters:
module
- module to be addedcallback
- a callback after the module has been addedfunction (module)
Fetches a module from a compilation by its identifier.
Parameters:
module
- module to be fetched. The identifier is extracted from the module by the compilation using module.identifier()
method.function (module)
Attempts to search for a module by its identifier.
Parameters:
module
- module to be searched for. The identifier is extracted from the module by the compilation using module.identifier()
method.function (module, optional, origin, dependencies)
Builds the given module.
Parameters:
module
- the module to be built.optional
- optional flag.origin
- origin module from which this module build was requested.dependencies
- optional dependencies of the module to be built.function (module, callback)
Process the given module dependencies.
Parameters:
module
- module to be processed for the dependencies.callback
- function to be invoked when dependencies of the module had been processed.function (context, entry, name, callback)
Adds an entry to the compilation.
Parameters:
context
- context path for entry.entry
- entry dependency.name
- the name of entry.callback
- function to be invoked when addEntry finishes.function (module, thisCallback)
Triggers a re-build of the module.
Parameters:
module
- module to be rebuilt.thisCallback
- function to be invoked when the module finishes rebuilding.function (callback)
Finishes compilation and invokes the given callback.
Parameters:
callback
- function to be invoked when the compilation has been finished.function (callback)
Seals the compilation.
Parameters:
callback
- function to be invoked when the compilation has been sealed.function
Unseals the compilation.
Parameters:
callback
- function to be invoked when the compilation has been unsealed.function (module, blocks)
Adds errors and warnings of the given module to the compilation errors and warnings.
Parameters:
module
- the module whose errors and warnings are to be reported.blocks
- a set of dependency blocks to report from.function (groupOptions, module, loc, request)
Adds module to an existing chunk group or creates a new one. Returns a chunkGroup
.
Parameters:
groupOptions
- options for the chunk group.module
- a module that references the chunk group.loc
- the location from which the chunk group is referenced (inside of the module).request
- the request from which the chunk group is referenced.function (name)
Creates and adds a new chunk to the compilation.chunks
. Returns that chunk
.
Parameters:
name
- the name of the chunk.function (module)
Assigns depth
to the given module and its dependency blocks recursively.
Parameters:
module
- the module to assign depth to.function (module, dependency)
Returns the reference to the dependency from a given module.
Parameters:
module
- the module at question.dependency
- the dependency to get reference to.function (inputChunkGroups)
Creates the Chunk
graph from the Module
graph. The process is done in two phases. Phase one: traverse the module graph and build a basic chunks graph in chunkDependencies
. Phase two: traverse every possible way through the basic chunk graph and track the available modules. While traversing, processDependenciesBlocksForChunkGroups
connects chunks with each other and Blocks
with Chunks
. It stops traversing when all modules for a chunk are already available and it doesn't connect unneeded chunks.
Parameters:
inputChunkGroups
- chunk groups that are processed.function (module, block)
Removes relation of the module to the dependency block.
Parameters:
module
- a module relationship to be removed.block
- dependency block.function (module, chunk)
Patches ties of module and chunk after removing dependency reasons. Called automatically by removeReasonsOfDependencyBlock
.
Parameters:
module
- a module to patch tie.chunk
- a chunk to patch tie.function (block, chunk)
Removes given chunk from a dependencies block module and chunks after removing dependency reasons. Called automatically by removeReasonsOfDependencyBlock
.
Parameters:
block
- block tie for Chunk
.chunk
- a chunk to remove from dependencies.function
function
function
function
function
function (filename, data)
Returns the interpolated path.
Parameters:
filename
- used to get asset path with hash.data
- data object.function (filename, data)
Returns interpolated path and asset information.
Parameters:
filename
- used to get asset path with hash.data
- data object.function (name, outputOptions, plugins)
Allows running another instance of webpack inside of webpack. However, as a child with different settings and configurations applied. It copies all hooks and plugins from the parent (or top-level compiler) and creates a child Compiler
instance. Returns the created Compiler
.
Parameters:
name
- name for the child Compiler
.outputOptions
- output options object.plugins
- webpack plugins that will be applied.function
function (file, source, assetInfo = {})
Parameters:
file
- file name of the assetsource
- the source of the assetassetInfo
- additional asset informationfunction (file, newSourceOrFunction, assetInfoUpdateOrFunction)
Parameters:
file
- file name of the assetnewSourceOrFunction
- new asset source or function converting old to newassetInfoUpdateOrFunction
- new asset info or function converting old to newfunction (file)
Parameters:
file
- file name of the assetfunction
Returns array of all assets under the current compilation.
function (name)
Parameters:
name
- the name of the asset to returnPlugins are a key piece of the webpack ecosystem and provide the community with
a powerful way to tap into webpack's compilation process. A plugin is able to
hook into key events that are fired throughout each compilation. Every step
of the way, the plugin will have full access to the compiler
and, when
applicable, the current compilation
.
Let's start by going over tapable
utility, which provides the backbone of
webpack's plugin interface.
This small library is a core utility in webpack but can also be used elsewhere
to provide a similar plugin interface. Many objects in webpack extend the
Tapable
class. The class exposes tap
, tapAsync
, and tapPromise
methods
which plugins can use to inject custom build steps that will be fired
throughout a compilation.
Please see the documentation to learn
more. An understanding of the three tap
methods, as well as the hooks that
provide them, is crucial. The objects that extend Tapable
(e.g. the compiler),
the hooks they provide, and each hook's type (e.g. the SyncHook
) will be
noted.
Depending on the hooks used and tap
methods applied, plugins can function in
a different number of ways. The way this works is closely related to the
hooks provided by Tapable
. The
compiler hooks each note the underlying Tapable
hook indicating which
tap
methods are available.
So depending on which event you tap
into, the plugin may run differently. For
example, when hooking into the compile
stage, only the synchronous tap
method
can be used:
compiler.hooks.compile.tap('MyPlugin', (params) => {
console.log('Synchronously tapping the compile hook.');
});
However, for run
which utilizes the AsyncHook
, we can utilize tapAsync
or tapPromise
(as well as tap
):
compiler.hooks.run.tapAsync(
'MyPlugin',
(source, target, routesList, callback) => {
console.log('Asynchronously tapping the run hook.');
callback();
}
);
compiler.hooks.run.tapPromise('MyPlugin', (source, target, routesList) => {
return new Promise((resolve) => setTimeout(resolve, 1000)).then(() => {
console.log('Asynchronously tapping the run hook with a delay.');
});
});
compiler.hooks.run.tapPromise(
'MyPlugin',
async (source, target, routesList) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log('Asynchronously tapping the run hook with a delay.');
}
);
The moral of the story is that there are a variety of ways to hook
into the
compiler
, each one allowing your plugin to run as it sees fit.
In order to offer a custom hook to the compilation for other plugins to tap
into,
you need to do the following:
Create a module-scope WeakMap
for compilation hooks:
const compilationHooks = new WeakMap<Compilation, MyHooks>();
interface MyHooks {
custom: SyncHook<[number, string]>;
}
Create a static method on your plugin:
static getCompilationHooks(compilation: Compilation) : MyHooks {
let hooks = compilationHooks.get(compilation);
if(hooks === undefined) {
compilationHooks.set(compilation, hooks = {
custom: new SyncHook()
});
}
return hooks;
}
Call hooks like below in your plugin:
const hooks = MyPlugin.getCompilationHooks(compilation);
hooks.custom.call(1, 'hello');
Other plugins can access your custom hooks too:
import MyPlugin from 'my-plugin';
const hooks = MyPlugin.getCompilationHooks(compilation);
hooks.custom.tap('OtherPlugin', (n, s) => {
// magic
});
Again, see the documentation for tapable
to learn more about the
different hook classes and how they work.
Plugins can report progress via ProgressPlugin
, which prints progress messages to stderr by default. In order to enable progress reporting, pass a --progress
argument when running the webpack CLI.
It is possible to customize the printed output by passing different arguments to the reportProgress
function of ProgressPlugin
.
To report progress, a plugin must tap
into a hook using the context: true
option:
compiler.hooks.emit.tapAsync(
{
name: 'MyPlugin',
context: true,
},
(context, compiler, callback) => {
const reportProgress = context && context.reportProgress;
if (reportProgress) reportProgress(0.95, 'Starting work');
setTimeout(() => {
if (reportProgress) reportProgress(0.95, 'Done work');
callback();
}, 1000);
}
);
The reportProgress
function may be called with these arguments:
reportProgress(percentage, ...args);
percentage
: This argument is unused; instead, ProgressPlugin
will calculate a percentage based on the current hook....args
: Any number of strings, which will be passed to the ProgressPlugin
handler to be reported to the user.Note that only a subset of compiler and compilation hooks support the reportProgress
function. See ProgressPlugin
for a full list.
Logging API is available since the release of webpack 4.37. When logging
is enabled in stats configuration
and/or when infrastructure logging
is enabled, plugins may log messages which will be printed out in the respective logger format (stats, infrastructure).
compilation.getLogger('PluginName')
for logging. This kind of logging is stored in the Stats and formatted accordingly. It can be filtered and exported by the user.compiler.getInfrastructureLogger('PluginName')
for logging. Using infrastructure
logging is not stored in the Stats and therefore not formatted. It's usually logged to the console/dashboard/GUI directly. It can be filtered by the user.compilation.getLogger ? compilation.getLogger('PluginName') : console
to provide a fallback for cases when an older webpack version is used which does not support getLogger
method on compilation
object.See the compiler hooks section for a detailed listing of all the available
compiler
hooks and the parameters they make available.
Resolvers are created using the enhanced-resolve
package. The Resolver
class extends the tapable
class and uses tapable
to provide a few hooks.
The enhanced-resolve
package can be used directly to create new resolvers,
however any compiler
instance has a few resolver instances that can be
tapped into.
Before reading on, make sure to have a look at the
enhanced-resolve
and tapable
documentation.
There are three types of built-in resolvers available on the compiler
class:
normal
: Resolves a module via an absolute or relative path.context
: Resolves a module within a given context.loader
: Resolves a webpack loader.Depending on need, any one of these built-in resolvers, that are used by the compiler
,
can be customized via plugins:
compiler.resolverFactory.hooks.resolver
.for('[type]')
.tap('name', (resolver) => {
// you can tap into resolver.hooks now
resolver.hooks.result.tap('MyPlugin', (result) => {
return result;
});
});
Where [type]
is one of the three resolvers mentioned above.
See the enhanced-resolve
documentation for a full list of hooks and their description.
The resolvers mentioned above can also be customized via a configuration file
with the resolve
or resolveLoader
options. These options allow
users to change the resolving behavior through a variety of options including
through resolve plugins
.
The resolver plugins, e.g. DirectoryNamedPlugin
, can be included
directly in resolve.plugins
rather than using directly in plugins
configuration option.