Optimization

Webpack runs optimizations for you depending on the chosen mode, still all optimizations are available for manual configuration and overrides.

optimization.checkWasmTypes

boolean

Tells webpack to check the incompatible types of WebAssembly modules when they are imported/exported.

The default value of optimization.checkWasmTypes depends on the mode:

ModeDefault
"production"true
"development"false
"none"false

webpack.config.js

export default {
  // ...
  optimization: {
    checkWasmTypes: false,
  },
};

optimization.chunkIds

boolean: false string: 'natural' | 'named' | 'size' | 'total-size' | 'deterministic'

  • false: disable webpack's built-in chunk id algorithm
  • one of the following values:
    • 'natural'
    • 'named'
    • 'size'
    • 'total-size'
    • 'deterministic'

Tells Webpack which algorithm to use for chunk IDs. Setting optimization.chunkIds to false tells webpack that none of built-in algorithms should be used, as custom one can be provided via plugin. There are a couple of defaults for optimization.chunkIds:

The default value of optimization.chunkIds depends on the mode:

ModeDefault
"production"'deterministic'
"development"'named'
"none"'natural'

The following string values are supported:

OptionDescription
'natural'Numeric ids in order of usage.
'named'Readable ids for better debugging.
'deterministic'Short numeric ids which will not be changing between compilation. Good for long term caching. Enabled by default for production mode.
'size'Numeric ids focused on minimal initial download size.
'total-size'numeric ids focused on minimal total download size.

webpack.config.js

export default {
  // ...
  optimization: {
    chunkIds: "named",
  },
};

By default, a minimum length of 3 digits is used when optimization.chunkIds is set to 'deterministic'. To override the default behaviour, set optimization.chunkIds to false and use the webpack.ids.DeterministicChunkIdsPlugin.

webpack.config.js

export default {
  // ...
  optimization: {
    chunkIds: false,
  },
  plugins: [
    new webpack.ids.DeterministicChunkIdsPlugin({
      maxLength: 5,
    }),
  ],
};

optimization.concatenateModules

boolean object

Tells webpack to find segments of the module graph which can be safely concatenated into a single module. Depends on optimization.providedExports and optimization.usedExports.

The default value of optimization.concatenateModules depends on the mode:

ModeDefault
"production"true
"development"false
"none"false

webpack.config.js

export default {
  // ...
  optimization: {
    concatenateModules: true,
  },
};

Since webpack 5.109.0, CommonJS modules with statically analyzable exports are concatenated as well, and an object form is accepted for advanced options:

  • commonjs (boolean = true): Also concatenate CommonJS modules with statically analyzable exports. Set it to false to restrict concatenation to ECMAScript modules, matching the behavior of earlier webpack versions.

webpack.config.js

export default {
  // ...
  optimization: {
    concatenateModules: {
      commonjs: false,
    },
  },
};

optimization.emitOnErrors

boolean

Use the optimization.emitOnErrors to emit assets whenever there are errors while compiling. This ensures that erroring assets are emitted. Critical errors are emitted into the generated code and will cause errors at runtime.

The default value of optimization.emitOnErrors depends on the mode:

ModeDefault
"production"false
"development"true
"none"true

webpack.config.js

export default {
  // ...
  optimization: {
    emitOnErrors: true,
  },
};

optimization.avoidEntryIife

boolean

5.95.0+

Use optimization.avoidEntryIife ...

Currently, optimization.avoidEntryIife can only optimize a single entry module along with other modules.

The default value of optimization.avoidEntryIife depends on the mode:

ModeDefault
"production"true
"development"false
"none"false

webpack.config.js

export default {
  // ...
  optimization: {
    avoidEntryIife: true,
  },
};

optimization.flagIncludedChunks

boolean

Tells webpack to determine and flag chunks which are subsets of other chunks in a way that subsets don't have to be loaded when the bigger chunk has been already loaded.

The default value of optimization.flagIncludedChunks depends on the mode:

ModeDefault
"production"true
"development"false
"none"false

webpack.config.js

export default {
  // ...
  optimization: {
    flagIncludedChunks: true,
  },
};

optimization.innerGraph

boolean

optimization.innerGraph tells webpack whether to conduct inner graph analysis for unused exports.

The default value of optimization.innerGraph depends on the mode:

ModeDefault
"production"true
"development"false
"none"false

webpack.config.js

export default {
  // ...
  optimization: {
    innerGraph: false,
  },
};

optimization.inlineExports

boolean

5.108.0+

Inline ESM exports that bind to small primitive constants (a null, undefined, boolean, number or string of at most 6 bytes) at every import site, replacing the imported binding with the literal value. Once every import is replaced, the import dependency becomes inactive, the export turns unused, and dead-code elimination can drop the export and, if the module is side-effect free, the whole module.

The default value of optimization.inlineExports depends on the mode:

ModeDefault
"production"true
"development"false
"none"false

webpack.config.js

export default {
  // ...
  optimization: {
    inlineExports: true,
  },
};

This happens in two steps. Given these modules:

// flags.js
export const DEBUG = false; // a ≤6-byte boolean
// app.js
import { DEBUG } from "./flags.js";

if (DEBUG) doSomething();

First, every reference to the imported binding is replaced with its literal value (inlining):

// app.js (conceptual result)
if (false) doSomething();

Then, because no import references DEBUG anymore, the export const DEBUG is left unused and dead-code elimination drops it. If flags.js has no side effects, the whole module is removed too. The consuming code can additionally collapse the now-constant branch (if (false) ...).

Inlining also enables cross-module dead-branch skipping: when an imported constant is statically inlinable, webpack evaluates the condition that guards a branch and skips the dependencies that live only in the provably-dead branch (ESM import specifiers, require() calls, and dynamic import() calls), so the unreachable modules are never added to the bundle.

// env.js
export const isDEV = false;
// app.js
import { devOnly } from "./dev-tools";
import { isDEV } from "./env";
import { prodOnly } from "./prod-tools";

export const tools = isDEV ? devOnly : prodOnly;

Because isDEV inlines to false, the devOnly branch is dead, so ./dev-tools is never bundled. The same holds for require() and dynamic import() calls that sit only in the dead branch.

optimization.mangleExports

boolean string: 'deterministic' | 'size'

optimization.mangleExports allows to control export mangling.

The default value of optimization.mangleExports depends on the mode:

ModeDefault
"production"true
"development"false
"none"false

The following values are supported:

OptionDescription
'size'Short names - usually a single char - focused on minimal download size.
'deterministic'Short names - usually two chars - which will not change when adding or removing exports. Good for long term caching.
trueSame as 'deterministic'
falseKeep original name. Good for readability and debugging.

webpack.config.js

export default {
  // ...
  optimization: {
    mangleExports: true,
  },
};

optimization.mangleWasmImports

boolean = false

When set to true tells webpack to reduce the size of WASM by changing imports to shorter strings. It mangles module and export names.

webpack.config.js

export default {
  // ...
  optimization: {
    mangleWasmImports: true,
  },
};

optimization.mergeDuplicateChunks

boolean = true

Tells webpack to merge chunks which contain the same modules. Setting optimization.mergeDuplicateChunks to false will disable this optimization.

webpack.config.js

export default {
  // ...
  optimization: {
    mergeDuplicateChunks: false,
  },
};

optimization.minimize

boolean object 5.110.0+

Tell webpack to minimize the bundle using the MinimizerPlugin or the plugin(s) specified in optimization.minimizer.

The default value of optimization.minimize depends on the mode:

ModeDefault
"production"true
"development"false
"none"false

webpack.config.js

export default {
  // ...
  optimization: {
    minimize: false,
  },
};

Minimizing per asset type

5.110.0+

Since webpack 5.110.0 the default minimizer also handles CSS and HTML assets, not only JavaScript, and optimization.minimize accepts an object that configures it per asset type:

export default {
  // ...
  optimization: {
    minimize: {
      javascript: { compress: { passes: 3 } },
      css: { rewriteCustomProperties: true },
      html: false,
    },
  },
};

An asset type the object does not name is minimized with its defaults, and false disables minimizing that type while the others keep running. minimize: true is the same as minimize: {}.

The CSS and HTML minifiers only run when the corresponding built-in support is enabled (experiments.css, experiments.html), and webpack steps aside for a minimizer you already configured for those assets, so an existing css-minimizer-webpack-plugin setup keeps owning its assets.

optimization.minimize.javascript

5.110.0+

object = { compress: { passes: 2 } } false

Options handed as-is to the JavaScript minimizer, which is terser-compatible. false leaves JavaScript unminified while CSS and HTML are still minimized.

export default {
  // ...
  optimization: {
    minimize: {
      javascript: {
        compress: { passes: 2, drop_console: true },
        format: { comments: false },
      },
    },
  },
};

optimization.minimize.css

5.110.0+

object false

What the built-in CSS minifier may do beyond the transforms that always apply. The options apply wherever that minifier runs: on .css assets and on the inline <style> elements and style="" attributes the HTML minifier hands to it.

Every transform that keeps the stylesheet's meaning is on by default and can be turned off on its own, so a stylesheet that one rewrite breaks can still be minified by the rest. The two that change what the CSSOM hands back are off until you ask for them.

OptionDefaultWhat it does
comments"some"Which comments survive. "some" keeps a /*! banner and anything annotated @license or @preserve, true / "all" keeps every comment, false keeps none. A string is read as a regular expression source, and a RegExp or a (comment) => boolean predicate is asked about each comment and replaces the default rule rather than adding to it.
mergeLonghandstrueWrite a family of longhands as the one shorthand that sets them, even where unrelated declarations stand between them.
mergeRulestrueJoin rules nothing stands between: adjacent rules printing the same block, at-rules sharing a prelude, a named @layer reopened by a later sibling.
normalizeQuotestrueGive each string the quote that needs fewer escapes, drop the quotes a url() or an attribute selector does not need, and unquote a font family that is a run of identifiers.
reduceFunctionstrueCompute a call into the shorter call naming the same value: calc() and the other math functions over constants, single-axis transforms, a gradient's default direction, an easing function that has a keyword.
removeDeadRulestrueDrop a rule or declaration nothing can read: an empty block, a declaration an identical later one overrides, a rule an identical later sibling makes dead.
shortenColorstrueWrite each color in the shortest spelling of the same value (#ffffff to #fff, rgb(1 2 3) to #010203).
shortenMediaQueriestrueWrite a media feature in its range spelling where the target reads one, and collapse an and of two one-sided ranges into the interval it describes.
shortenNumberstrueWrite each number in its shortest equal spelling: no leading zero, no trailing fraction, no +, no unit on a zero.
shortenSelectorstrueRewrite a selector into an equal one: a deduplicated and ordered selector list, a CSS2 pseudo-element's second colon dropped, the shortest An+B.
shortenValuestrueWrite a value the shortest way its property's grammar allows: a {1,4} box notation collapsed, a slot holding its own initial dropped, short flex / font-weight / display.
vendorPrefixestrueAdd the -webkit- / -moz- / -ms- spelling a selected browser still needs and drop one none of them does. Only in effect for a browserslist target, which is what names the browsers.
convertLengthUnitsfalseRewrite a length into a shorter unit it is exactly equal in (16px to 1pc). Off because the authored unit is lost and compression rarely earns anything back.
rewriteCustomPropertiesfalseShorten the values of custom properties (--x: #ffffff to #fff). Off because getComputedStyle().getPropertyValue() hands this text back verbatim, so a rewrite changes what a script reads.
export default {
  // ...
  optimization: {
    minimize: {
      css: {
        // this one page relies on the authored custom property text
        rewriteCustomProperties: false,
        comments: false,
      },
    },
  },
};

optimization.minimize.html

5.110.0+

object false

What the built-in HTML minifier may do. Every transform that keeps the document's DOM is on by default and can be turned off on its own; the ones that change what a script or a selector reads back are off until you ask for them.

OptionDefaultWhat it does
collapseBooleanAttributestrueWrite disabled="disabled" as the bare disabled the spec canonicalizes it to.
collapseWhitespace"conservative"Collapse each run of whitespace in text to a single space, never inside pre, textarea or listing. true / "conservative" never removes whitespace entirely, since that would join two inline elements that render apart. "smart" also drops the whitespace against a block element's edge. "all" drops it at every text node's edges, which does change how adjacent inline elements render.
comments"some"Which comments survive. For HTML "some" keeps nothing, since every comment a parser reads is inert. Otherwise it works like the CSS option above. Conditional comments, server-side includes and <?…?> directives are code rather than comments and are kept whatever this says.
minifyJsontrueStrip the whitespace between the tokens of a <script> whose type is a JSON MIME type, copying every literal byte for byte.
minifyStylestrueRun the CSS minifier over inline <style> elements and every style="" attribute, with the optimization.minimize.css options.
normalizeAttributeQuotestrueWrite an attribute value with whichever delimiters cost least: bare where the grammar allows it, otherwise the quote needing fewer character references.
normalizeEnumeratedAttributestrueFold an enumerated attribute's value to the keyword it names (type="TEXT" to type=text), which the DOM matches case-insensitively.
normalizeListAttributestrueNormalize a list-shaped attribute value: token lists like class and rel, comma-separated ones like accept and sizes, srcset, and the viewport <meta content>.
normalizeNumericAttributestrueWrite an integer attribute (tabindex, colspan, width, …) the one way its own rules read it.
removeOptionalTagstrueLeave out a tag the parser is allowed to imply, other than the <html> / <head> / <body> shell, which removeImpliedTags decides.
removeImpliedTags"smart"How much of the <html> / <head> / <body> shell may be left out. "smart" leaves out only the <html> start tag, and only when it carries no attribute, so the <html lang=en> that tooling greps for keeps its tag. true / "all" leaves out all six tags, false none.
mergeStylesfalsePrint a run of adjacent <style> elements as one sheet. Off because it removes elements, so document.styleSheets, style:nth-child() and querySelectorAll("style").length all read a different document.
minifyConditionalCommentsfalseMinify the markup inside a downlevel-hidden conditional comment. Off because the body is minified as though it started a document of its own, and only browsers older than IE10 read them at all.
minifySrcdocfalseMinify the document held in an <iframe srcdoc> attribute. Off because the attribute is readable from script, and a consumer comparing iframe.srcdoc byte for byte would see it change.
removeEmptyAttributesfalseDrop an attribute whose empty value leaves it in the state its absence gives. Off because an attribute selector matches on presence, so [class] stops matching. title, lang, sandbox and event handlers are never dropped.
removeEmptyElementsfalseDrop an element with no children and no attributes. Off because CSS can give an empty element a size or a ::before, and the minifier cannot see the stylesheet.
removeRedundantAttributesfalseDrop an attribute whose value is the element's own default. true / "smart" drops only markers on elements that render nothing (<script type=text/javascript>, <style type=text/css>, <link media=all>). "all" also drops spec defaults such as <input type=text>, which stops input[type=text] from matching.
sortAttributesfalsePrint attributes in a fixed order so the same markup compresses better across pages. Off because a script reading element.attributes, or an HTML snapshot test, sees the new order.
sortTokenListsfalsePrint the token lists the DOM reads as a set (class, rel, part, sandbox, …) in sorted order, for the same compression reason. Off because a script reading className or rel back sees the new order. ping and accesskey are never sorted, since their order is meaningful.
export default {
  // ...
  optimization: {
    minimize: {
      html: {
        collapseWhitespace: "smart",
        removeRedundantAttributes: true,
        sortAttributes: true,
        sortTokenLists: true,
      },
    },
  },
};

optimization.minimizer

[MinimizerPlugin] and or [function (compiler)] or undefined | null | 0 | false | ""

Allows you to override the default minimizer by providing a different one or more customized MinimizerPlugin instances. Starting with webpack 5.87.0 falsy values can be used to conditionally disable specific minimizers.

webpack.config.js

import MinimizerPlugin from "minimizer-webpack-plugin";

export default {
  optimization: {
    minimizer: [
      new MinimizerPlugin({
        parallel: true,
        minimizerOptions: {
          // https://github.com/webpack/minimizer-webpack-plugin#minimizeroptions
        },
      }),
    ],
  },
};

Or, as function:

import MinimizerPlugin from "minimizer-webpack-plugin";

export default {
  optimization: {
    minimizer: [
      (compiler) => {
        new MinimizerPlugin({
          /* your config */
        }).apply(compiler);
      },
    ],
  },
};

By default, webpack would set optimization.minimizer to the following value:

import MinimizerPlugin from "minimizer-webpack-plugin";

const minimizer = [
  {
    apply: (compiler) => {
      new MinimizerPlugin({
        minimizerOptions: {
          compress: {
            passes: 2,
          },
        },
      }).apply(compiler);
    },
  },
];

Which can be accessed with '...' in case you want to keep it when customizing optimization.minimizer:

export default {
  optimization: {
    minimizer: [new CssMinimizer(), "..."],
  },
};

Basically, '...' is a shortcut to access the default configuration value webpack would otherwise set for us.

optimization.moduleIds

boolean: false string: 'natural' | 'named' | 'deterministic' | 'size'

Tells webpack which algorithm to use when choosing module ids. Setting optimization.moduleIds to false tells webpack that none of built-in algorithms should be used, as custom one can be provided via plugin.

The default value of optimization.moduleIds depends on the mode:

ModeDefault
"production"'deterministic'
"development"'named'
"none"'natural'

The following string values are supported:

OptionDescription
naturalNumeric ids in order of usage.
namedReadable ids for better debugging.
deterministicModule names are hashed into small numeric values.
sizeNumeric ids focused on minimal initial download size.

webpack.config.js

export default {
  // ...
  optimization: {
    moduleIds: "deterministic",
  },
};

The deterministic option is useful for long term caching, but still results in smaller bundles compared to hashed. Length of the numeric value is chosen to fill a maximum of 80% of the id space. By default a minimum length of 3 digits is used when optimization.moduleIds is set to deterministic. To override the default behaviour set optimization.moduleIds to false and use the webpack.ids.DeterministicModuleIdsPlugin.

webpack.config.js

export default {
  // ...
  optimization: {
    moduleIds: false,
  },
  plugins: [
    new webpack.ids.DeterministicModuleIdsPlugin({
      maxLength: 5,
    }),
  ],
};

optimization.nodeEnv

boolean: false string

Tells webpack to set process.env.NODE_ENV to a given string value. optimization.nodeEnv uses DefinePlugin unless set to false.

The default value of optimization.nodeEnv depends on the mode:

ModeDefault
"production"'production'
"development"'development'
"none"false

Possible values:

  • any string: the value to set process.env.NODE_ENV to.
  • false: do not modify/set the value of process.env.NODE_ENV.

webpack.config.js

export default {
  // ...
  optimization: {
    nodeEnv: "production",
  },
};

optimization.portableRecords

boolean

optimization.portableRecords tells webpack to generate records with relative paths to be able to move the context folder.

By default optimization.portableRecords is disabled. Automatically enabled if at least one of the records options provided to webpack config: recordsPath, recordsInputPath, recordsOutputPath.

webpack.config.js

export default {
  // ...
  optimization: {
    portableRecords: true,
  },
};

optimization.providedExports

boolean

Tells webpack to figure out which exports are provided by modules to generate more efficient code for export * from .... By default optimization.providedExports is enabled.

webpack.config.js

export default {
  // ...
  optimization: {
    providedExports: false,
  },
};

optimization.realContentHash

boolean

Adds an additional hash compilation pass after the assets have been processed to get the correct asset content hashes. If realContentHash is set to false, internal data is used to calculate the hash and it can change when assets are identical.

The default value of optimization.realContentHash depends on the mode:

ModeDefault
"production"true
"development"false
"none"false

webpack.config.js

export default {
  // ...
  optimization: {
    realContentHash: false,
  },
};

optimization.removeAvailableModules

boolean = false

Tells webpack to detect and remove modules from chunks when these modules are already included in all parents. Setting optimization.removeAvailableModules to true will enable this optimization.

webpack.config.js

export default {
  // ...
  optimization: {
    removeAvailableModules: true,
  },
};

optimization.removeEmptyChunks

boolean = true

Tells webpack to detect and remove chunks which are empty. Setting optimization.removeEmptyChunks to false will disable this optimization.

webpack.config.js

export default {
  // ...
  optimization: {
    removeEmptyChunks: false,
  },
};

optimization.runtimeChunk

object string boolean

Setting optimization.runtimeChunk to true or 'multiple' adds an additional chunk containing only the runtime to each entrypoint. This setting is an alias for:

webpack.config.js

export default {
  // ...
  optimization: {
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}`,
    },
  },
};

The value 'single' instead creates a runtime file to be shared for all generated chunks. This setting is an alias for:

webpack.config.js

export default {
  // ...
  optimization: {
    runtimeChunk: {
      name: "runtime",
    },
  },
};

By setting optimization.runtimeChunk to object it is only possible to provide the name property which stands for the name or name factory for the runtime chunks.

Default is false: each entry chunk embeds runtime.

webpack.config.js

export default {
  // ...
  optimization: {
    runtimeChunk: {
      name: (entrypoint) => `runtimechunk~${entrypoint.name}`,
    },
  },
};

optimization.sideEffects

boolean string: 'flag'

Tells webpack to recognise the sideEffects flag in package.json or rules to skip over modules which are flagged to contain no side effects when exports are not used.

package.json

{
  "name": "awesome npm module",
  "version": "1.0.0",
  "sideEffects": false
}

optimization.sideEffects depends on optimization.providedExports to be enabled. This dependency has a build time cost, but eliminating modules has positive impact on performance because of less code generation. Effect of this optimization depends on your codebase, try it for possible performance wins.

The default value of optimization.sideEffects depends on the mode:

ModeDefault
"production"true
"development"'flag'
"none"'flag'

webpack.config.js

export default {
  // ...
  optimization: {
    sideEffects: true,
  },
};

To only use the manual flag and do not analyse source code:

export default {
  // ...
  optimization: {
    sideEffects: "flag",
  },
};

optimization.splitChunks

object

By default webpack v4+ provides new common chunks strategies out of the box for dynamically imported modules. See available options for configuring this behavior in the SplitChunksPlugin page.

optimization.usedExports

boolean string: 'global'

Tells webpack to determine used exports for each module. This depends on optimization.providedExports. Information collected by optimization.usedExports is used by other optimizations or code generation i.e. exports are not generated for unused exports, export names are mangled to single char identifiers when all usages are compatible. Dead code elimination in minimizers will benefit from this and can remove unused exports.

The default value of optimization.usedExports depends on the mode:

ModeDefault
"production"true
"development"false
"none"false

webpack.config.js

export default {
  // ...
  optimization: {
    usedExports: false,
  },
};

To opt-out from used exports analysis per runtime:

export default {
  // ...
  optimization: {
    usedExports: "global",
  },
};
Edit this page·
« Previous
Resolve
Next »
Plugins

14 Contributors

EugeneHlushkojeremenichellisimon04byzykmadhavarshneydhurlburtusajamesgeorge007anikethsahasnitin315pixel-raychenxsanRoberto14hai-xshivxmsharma