At its core, webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it internally builds a dependency graph from one or more entry points and then combines every module your project needs into one or more bundles, which are static assets that serve your content.
[!TIP] Learn more about JavaScript modules and webpack modules here.
Since version 4.0.0, webpack does not require a configuration file to bundle your project. Even so, it is incredibly configurable to better fit your needs.
To get started, you only need to understand its core concepts:
This document gives a high-level overview of these concepts while linking to more detailed, concept-specific use cases.
For a deeper understanding of the ideas behind module bundlers and how they work under the hood, consult these resources:
- Manually Bundling an Application
- Live Coding a Basic Module Bundler
- Detailed Explanation of a Basic Module Bundler
An entry point tells webpack which module to use to begin building its internal dependency graph. From there, webpack determines which other modules and libraries that entry point depends on, both directly and indirectly.
By default the entry is ./src/index.js, but you can specify a different entry point — or multiple — by setting the entry property in the webpack configuration. For example:
export default {
entry: './path/to/my/entry/file.js',
};[!TIP] When you run webpack without a configuration file, the entry defaults to
'./src/index.js'. If that file does not exist — even when yoursrc/directory does — webpack throws:
ERROR in Entry module not found: Error: Can't resolve './src'The error mentions
'./src'rather than'./src/index.js'because webpack resolves the directory first and then fails to find the defaultindex.jsinside it. To use a different entry filename, add awebpack.config.jsas shown in the example above.
[!TIP] Learn more in the entry points section.
The output property tells webpack where to emit the bundles it creates and how to name those files. It defaults to ./dist/main.js for the main output file and to the ./dist folder for any other generated file.
You can configure this part of the process with an output field in your configuration:
import path from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js',
},
};In the example above, the output.filename and output.path properties tell webpack the name of our bundle and where to emit it. If you're wondering about the path module imported at the top, it is a core Node.js module used to manipulate file paths.
[!TIP] The
outputproperty has many more configurable features. To learn about the concepts behind it, read more in the output section.
Out of the box, webpack only understands JavaScript and JSON files. Loaders let webpack process other types of files and convert them into valid modules that your application can consume and that can be added to the dependency graph.
[!WARNING] One of webpack's distinctive features is the ability to
importany type of module, for example.cssfiles, which other bundlers or task runners may not support. We feel this extension of the language is warranted, because it lets developers build a more accurate dependency graph.
At a high level, loaders have two properties in your webpack configuration:
- The
testproperty identifies which file or files should be transformed. - The
useproperty indicates which loader should perform the transformation.
import path from 'node:path';
export default {
output: {
filename: 'my-first-webpack.bundle.js',
},
module: {
rules: [{ test: /\.js$/, use: 'babel-loader' }],
},
};The configuration above defines a rules property with a single rule that has the two required properties test and use. This tells webpack's compiler the following:
"Hey webpack compiler, when you come across a path that resolves to a '.js' file inside a
require()/importstatement, use thebabel-loaderto transform it before you add it to the bundle."
[!WARNING] Remember that when you define rules in your webpack configuration, you define them under
module.rules, notrules. webpack will warn you if you get this wrong.
[!WARNING] Keep in mind that when you use a regular expression to match files, you must not quote it. For example,
/\.txt$/is not the same as'/\.txt$/'or"/\.txt$/". The former tells webpack to match any file ending in.txt, while the latter tells webpack to match a single file with the absolute path'.txt', which is likely not your intention.
You can learn more about including loaders in the loaders section.
While loaders transform certain types of modules, plugins can perform a much wider range of tasks, such as bundle optimization, asset management, and injecting environment variables.
[!TIP] Check out the plugin interface and how to use it to extend webpack's capabilities.
To use a plugin, you import it and add it to the plugins array. Most plugins are customizable through options. Since you can use a plugin multiple times in a configuration for different purposes, you create an instance of it by calling it with the new operator.
import HtmlWebpackPlugin from 'html-webpack-plugin';
import webpack from 'webpack'; // to access built-in plugins
export default {
module: {
rules: [{ test: /\.js$/, use: 'babel-loader' }],
},
plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};In the example above, the html-webpack-plugin generates an HTML file for your application and automatically injects all of your generated bundles into it.
[!TIP] webpack provides many plugins out of the box. Check out the list of plugins.
Using plugins in your webpack configuration is straightforward, but there are many use cases worth exploring further. Learn more about them here.
By setting the mode parameter to development, production, or none, you can enable webpack's built-in optimizations for the corresponding environment. The default value is production.
export default {
mode: 'production',
};Learn more about the mode configuration here and which optimizations each value enables.
webpack supports all browsers that are ES5-compliant; IE8 and below are not supported. webpack needs Promise for import() and require.ensure(). To support older browsers, you will need to load a polyfill before using these expressions.
webpack 5 requires Node.js version 10.13.0 or later.