Ivaylo Gerchev

A Beginner’s Guide to Webpack

Share this article

A Beginner’s Guide to Webpack

What Is Webpack?

Webpack main concepts, how webpack works.

  • What’s New in Webpack 5

Getting Started

Transpiling modern javascript to es5, working with styles, asset management, speed up the development process with webpack-dev-server, clean up the output, frequently asked questions (faqs) about webpack.

Nowadays, we’re forced to use many accessory tools to facilitate, speed up and optimize our web development workflow. Often, though, such tools add an extra layer of complexity into the stack. As a result, we need to utilize additional time and effort to learn, understand and use these tools correctly. The same is true for webpack .

When using webpack for the first time, it can be difficult to understand how it works and how it should be used. Although it has good documentation, it can be daunting for novices, and it has a steep learning curve. However, webpack is worth learning and can save considerable time and effort in the long run. In this tutorial, I’ll introduce all the core concepts to help you get started.

Note: in this tutorial I’ve used webpack 5.9.0.

As its core, webpack is a static module bundler. In a particular project, webpack treats all files and assets as modules. Under the hood, it relies on a dependency graph. A dependency graph describes how modules relate to each other using the references ( require and import statements) between files. In this way, webpack statically traverses all modules to build the graph, and uses it to generate a single bundle (or several bundles) — a JavaScript file containing the code from all modules combined in the correct order. “Statically” means that, when webpack builds its dependency graph, it doesn’t execute the source code but stitches modules and their dependencies together into a bundle. This can then be included in your HTML files.

Now, to expand the above cursory overview, let’s explore the main concepts webpack uses.

Webpack has some main concepts which we need to understand clearly before digging in its practical implementation. Let’s examine them one by one:

  • Entry : the entry point is the module that webpack uses to start building its internal dependency graph. From there, it determines which other modules and libraries that entry point depends on (directly and indirectly) and includes them in the graph until no dependency is left. By default, the entry property is set to ./src/index.js , but we can specify a different module (or even multiple modules) in the webpack configuration file.
  • Output : the output property instructs webpack where to emit the bundle(s) and what name to use for the file(s). The default value for this property is ./dist/main.js for the main bundle and ./dist for other generated files — such as images, for example. Of course, we can specify different values in the configuration depending on our needs.
  • Loaders : by default, webpack only understands JavaScript and JSON files. To process other types of files and convert them into valid modules, webpack uses loaders. Loaders transform the source code of non-JavaScript modules, allowing us to preprocess those files before they’re added to the dependency graph. For example, a loader can transform files from a CoffeeScript language to JavaScript or inline images to data URLs. With loaders we can even import CSS files directly from our JavaScript modules.
  • Plugins : plugins are used for any other task that loaders can’t do. They provide us with a wide range of solutions about asset management, bundle minimization and optimization, and so on.
  • Mode : typically, when we develop our application we work with two types of source code — one for the development build and one for the production build. Webpack allows us to set which one we want to be produced by changing the mode parameter to development , production or none . This allows webpack to use built-in optimizations corresponding to each environment. The default value is production . The none mode means that no default optimization options will be used. To learn more about the options webpack uses in development and production mode, visit the mode configuration page .

In this section, we’ll examine how webpack works. Even a simple project contains HTML, CSS and JavaScript files. Also, it can contains assets such as fonts, images, and so on. So, a typical webpack workflow would include setting up an index.html file with the appropriate CSS and JS links, and the necessary assets. Also, if you have many CSS and JS modules which depend on each other, they need to be optimized and properly combined in one unit ready for production.

To do all this, webpack relies on configuration. Starting from version 4 and above, webpack provides reasonable defaults out of the box, so creating a configuration file is not required. However, for any non-trivial project you’ll need to provide a special webpack.config.js file, which describes how the files and assets should be transformed and what kind of output should be generated. This file can quickly become monolithic, which makes it hard to understand how webpack does its job unless you know the main concepts behind its working.

Based on the provided configuration, webpack starts from the entry points and resolves each module it encounters while constructing the dependency graph. If a module contains dependencies, the process is performed recursively against each dependency until the traversal has completed. Then webpack bundles all the project’s modules into a small number of bundles — usually, just one — to be loaded by the browser.

What’s New in Webpack 5

A webpack 5 release was announced in October 2020 . The post is quite long and explores all the changes made to webpack. It’s impossible to mention all changes and it’s unnecessary for a beginner’s guide like this. Instead, I’ll try to put a small list with some general highlights:

  • The build performance is improved with Persistent Caching. Developers can now enable a file-system–based cache, which will speed up the development builds.
  • The Long Term Caching is also improved. In webpack 5, changes made to the code that don’t affect the minimized bundle version (comments, variable names) won’t result in cache invalidation. Also, new algorithms were added which assign short numeric IDs to modules and chunks and short names to exports in a deterministic way. In webpack 5, they’re enabled by default in production mode.
  • Improved bundle size, thanks to better Tree Shaking and Code Generation. Thanks to the new Nested Tree-Shaking feature, webpack is now able to track access to nested properties of exports. The CommonJs Tree Shaking allows us to eliminate unused CommonJs exports.
  • The minimum supported Node.js version has increased from 6 to 10.13.0 (LTS).
  • The codebase is cleaned up. All items marked as deprecated in webpack 4 are removed.
  • Automatic Node.js polyfills are removed. Previous versions of webpack have included polyfills for native Node.js libraries like crypto . In many cases they are unnecessary and increase the bundle size drastically. That’s why webpack 5 stops automatically polyfilling these core modules and focuses on front-end–compatible modules.
  • As an improvement of development, webpack 5 allows us to pass a list of targets and also support versions of target. It provides automatic determination of the public path. And also, it offers automatic, unique naming, which prevents conflicts between multiple webpack runtimes that use the same global variable for chunk loading.
  • The webpack-dev-server command is now webpack serve .
  • Asset modules are introduced, which replace the uses of file-loader , raw-loader , and url-loader .

Please open the announcement link above to find more complete and detailed information about all the updates.

Finally, if you’re coming from webpack 4, here’s the migration guide .

Note: you can find the files for our project in the GitHub repo .

Now that we have a solid theoretical foundation, let’s implement it in practice.

To start, we’ll create a new directory and switch to it. Then we’ll initialize a new project:

Next, we need to install webpack and webpack CLI (command line interface) locally:

Now, the content of the generated package.json should be similar to the following:

Besides being a package manager, npm can be used as a simple task runner. We can create webpack tasks by including the name of our task followed by its instructions in the scripts section of the package.json file. Let’s try this now. Open package.json and change the scripts object to the following:

Within the scripts property, npm allows us to reference locally installed Node.js packages by their names. We use that and the --mode flag to define dev and build tasks, which will run webpack in development ( npm run dev ) and production ( npm run build ) mode respectively.

Before we test the tasks we’ve just created, let’s create a src directory and put an index.js file in it so that it contains console.log("Hello, Webpack!"); . Now we can already run the dev task to start webpack in development mode:

As I mentioned before, webpack sets the default entry point to ./src/index.js and the default output to ./dist/main.js . So what webpack does when we run the dev task is to get the source code from index.js file and bundle the final code in a main.js file.

Great! It works as expected. But to verify that we get the correct output, we need to display the result in the browser. To do that, let’s create an index.html file in the dist directory:

Now, if we open the file in the browser, we should see the Hello, Webpack! message in the console.

Webpack Console Message Displayed

So far, so good. But writing our index.html file manually can be problematic in some cases. For example, if we change the name of our entry point, the generated bundle will be renamed, but our index.html file will still reference the old name. So, we’ll need to update our HTML file manually every time we rename an entry point or add new one. Fortunately, we can easily fix that with the html-webpack-plugin . Let’s install it now:

Note: notice that I have typed html-webpack-plugin@next instead of just html-webpack-plugin . At the time of writing, the former is the proper version for webpack 5, and the latter is the version for webpack 4. This could change in future, so for the actual version check the html-webpack-plugin repo .

At this point, to activate the plugin, we need to create a webpack.config.js file in the root directory with the following content:

As you can see, to activate a webpack plugin, we need to include it in the file and then add it to the plugins array. If needed, we also pass options to the plugin. See the html-webpack-plugin repo for all available options and the ability to write and use your own templates .

Let’s run webpack now to see what will happen:

Let’s open the index.html . As we can see, the plugin automatically creates an updated index.html file for us, which uses the title option from the configuration:

Let’s now expand our project and specify custom names for the entry and output properties. In webpack.config.js we add the following before the plugins property:

Here, we change the entry file to app.js and the output folder to deploy . We also tweak the name of the generated bundle file slightly. Now it will start with the name of the entry (“main”) followed by the word “bundle” and the .js file extension.

Now, we’ll create an src/component.js file:

Next, we rename index.js to app.js to reflect our changes, and replace its content with the following:

Now, let’s run webpack again:

Let’s examine and clarify the information from the webpack output. After the “Compilation finished” message you can see the files generated in the deploy directory ( main.bundle.js and index.html ). Below them, you can see the source files: the entry module ( app.js ) and its dependency ( component.js ).

So now, in the deploy folder, we have the newly generated bundle file main.bundle.js . If we open the index.html file in the browser, we should see Hello, Webpack! displayed on the page.

Webpack Browser Message Displayed

Also, if we check the source of index.html , we’ll see that the value of the src property in the script tag is updated to main.bundle.js .

At this point, we can delete the dist folder, which webpack generated initially, because we won’t need it anymore.

In this section, we’ll discover how ES6 can be transpiled to ES5-compliant code that works in all browsers. Let’s start by running the following command:

Here, I run webpack with devtool option set to inline-source-map in order to render the code more readable. This way I can demonstrate the code transpilation from ES6 to ES5 more clearly.

Next, let’s open main.bundle.js :

As you can see, the modern ES6 features (the arrow function and the const declaration) from component.js module are not transformed to ES5-compliant code by default. To make our code work in older browsers, we must add the Babel loader:

Then, in webpack.config.js add module after the output property:

When we define rules for a webpack loader, there are usually three main properties we need to define:

  • test , which describes what kind of files should be transformed.
  • exclude , which defines the files that shouldn’t be processed from the loader(s), if we have such.
  • use , which tells which loader(s) should be used against the matched modules. Here, we can also set the loader options, as we’ve just done with the presets option.

Run the following command again:

This time, the code in main.bundle.js is compiled:

Perfect. Now we can use the modern JS features, and webpack will transform our code so it can be executed by older browsers.

In this section, we’ll see how we can add some styles to our project. To do this, we need to install two loaders:

  • css-loader parses the CSS into JavaScript and resolves any dependencies
  • style-loader outputs our CSS into a <style> tag in the HTML document.

Let’s add the necessary configuration in webpack.config.js :

Here, the order of loaders is important. They’re evaluated in reverse order — that is, from right to left and from bottom to top. In our case, the css-loader is evaluated first, followed by the style-loader .

Now, let’s create a file src/style.css :

Then we import it into app.js :

When we run webpack ( npm run dev ) and then open the index.html , we should see the Hello, Webpack! message in red color.

Webpack Browser Message With Style Applied

Most often your project will contain assets such as images, fonts, and so on. In webpack 4, to work with assets, we had to install one or more of the following loaders: file-loader , raw-loader , and url-loader . In webpack 5, as we saw earlier, this is not needed anymore, because the new version comes with the built-in asset modules .

Here, we’ll explore an example with images. Let’s add new rule in the webpack.config.js :

Here, the type asset/resource is used instead of file-loader .

Now, to test the loader we’ll create an image-component.js file, in the src directory, with the following content:

Here, we import our image as a module and use it to create an <img/> tag. To make the above code work, you need to download the image and then rename it to image.png and put it in the src directory.

The next thing is to import our image component in app.js :

And voila. Now, when we run webpack ( npm run dev ) and open the page, we should see the image above the Hello, Webpack! message.

Webpack Image Component Displayed

If you take a look at the deploy folder right now, you’ll find three files generated in it: a1af828b4e65d37668e1.png , main.bundle.js , and index.js . Here’s what webpack does behind the scenes: the image is added to the deploy folder and assigned a unique hash, followed by the image extension. The image is then included in the newly generated main.bundle.js file as a module. Finally, an index.html file is generated with reference to the main.bundle.js file.

Currently, we need to rebuild our code every time we make a change. Fortunately, webpack offers a live-reloading web server which automatically builds and refreshes the page. To install it, run the following:

We need to update our dev script, in package.json , to use the server:

Now let’s configure the server in webpack.config.js by adding the following property after the output :

This tells webpack-dev-server to serve the files from the deploy directory and to open the entry page automatically.

Now, if we run webpack ( npm run dev ), we should see how the page is automatically opened in the browser on http://localhost:8080 .

Note: After running the webpack-dev-server you won’t find any files in the deploy folder (it will be empty) because the server doesn’t write any output files after compiling. Instead, it keeps bundle files in memory and serves them as if they were real files mounted at the server’s root path. See the webpack development guide for more information. However, when you run the build command, the deploy folder will be populated with the generated files as expected.

If we now change any of the source files and save them, the web server will automatically reload the page after the code has been compiled. Try to change the color property in our CSS file to green, for example, and you should see how the color is updated appropriately in the page.

Webpack Development Server In Action

As our project progresses, the deploy folder might become quite cluttered. On every build, webpack will generate the bundles and put them in the deploy folder, but it doesn’t keep track of which files are actually in use by your project. So it’s a good practice to clean the deploy folder before each build, so that only the files in use will be generated. To do this, we need to install and configure the clean-webpack-plugin :

In webpack.config.js :

Now, run webpack ( npm run build ) and inspect the deploy folder. You should now only see the files generated from the build without old and unused files. To test it, create a simple text file which is not used in the project and run the build script again. After the compilation the file will be deleted.

Webpack is a useful and powerful tool. This tutorial introduces only the core concepts, but webpack offers many more features, plugins, and different techniques to apply them, which you can adopt as your knowledge grows. Here’s a list of resources I suggest for further exploration of webpack’s capabilities:

  • Official webpack Documentation . The documentation offers you structured information about webpack’s main concepts and configuration, as well as plugins and loaders you can use in your project, and basic guides and API references.
  • Webpack 5: From Apprentice to Master . A complete manual which dives deeply into each webpack aspect. Written by Juho Vepsäläinen, a core developer of webpack.
  • Webpack: The Core Concepts . A great introductory video course by Sean Larkin, one of webpack’s maintainers.

What is the difference between Webpack and other module bundlers?

Webpack is a powerful module bundler that bundles JavaScript files for usage in a browser. Unlike other module bundlers, Webpack has a rich plugin system that allows you to customize its functionality. It also supports a variety of file types, not just JavaScript, including CSS, images, and fonts. This means you can manage all your assets in one place. Additionally, Webpack has a feature called “code splitting” that allows you to split your code into various bundles which can then be loaded on demand or in parallel.

How can I configure Webpack for multiple environments?

Webpack allows you to have separate configuration files for different environments like development, testing, and production. This can be achieved by creating separate configuration files for each environment and using the ‘webpack-merge’ utility to merge the common configuration with the environment-specific configuration. This way, you can have specific settings for each environment without duplicating code.

How does Webpack handle CSS?

Webpack can handle CSS files using loaders. Loaders are transformations that are applied to the source code of a module. To process CSS files, you can use the ‘style-loader’ and ‘css-loader’. The ‘css-loader’ interprets ‘@import’ and ‘url()’ like ‘import/require()’ and will resolve them, while the ‘style-loader’ injects CSS into the DOM.

What is Hot Module Replacement in Webpack?

Hot Module Replacement (HMR) is a feature in Webpack that allows modules to be updated at runtime without the need for a full refresh. This can significantly speed up development as it allows you to see changes without losing the state of the application.

How can I optimize my Webpack build for production?

Webpack provides several ways to optimize your build for production. This includes minifying your code using plugins like ‘UglifyJsPlugin’, eliminating unused code with ‘tree shaking’, and splitting your code into chunks using the ‘SplitChunksPlugin’. You can also use the ‘DefinePlugin’ to create global constants which can reduce code size and improve performance.

How can I use Webpack with Babel?

Babel is a popular JavaScript compiler that allows you to use next-generation JavaScript today. To use Babel with Webpack, you need to install the ‘babel-loader’ and configure it in your Webpack configuration file. This will allow Webpack to process your JavaScript files with Babel before bundling them.

Can I use Webpack with TypeScript?

Yes, you can use Webpack with TypeScript. To do this, you need to install the ‘ts-loader’ or ‘awesome-typescript-loader’. Then, you can configure Webpack to process your TypeScript files with these loaders before bundling them.

How can I handle images with Webpack?

Webpack can handle images using the ‘file-loader’ or ‘url-loader’. These loaders allow you to import images in your JavaScript files, and Webpack will process them and include them in your bundle.

Can I use Webpack with React?

Yes, you can use Webpack with React. Webpack can handle JSX syntax (used in React) with the help of ‘babel-loader’. You can also use the ‘react-hot-loader’ for hot module replacement in your React components.

How can I debug my Webpack configuration?

Webpack provides a variety of options for debugging. You can use the ‘debug’ option in your configuration file to enable debug mode. You can also use the ‘devtool’ option to control how source maps are generated. Additionally, Webpack provides detailed error messages and stack traces to help you debug your configuration.

I am a web developer/designer from Bulgaria. My favorite web technologies include SVG, HTML, CSS, Tailwind, JavaScript, Node, Vue, and React. When I'm not programming the Web, I love to program my own reality ;)

SitePoint Premium

How to use Webpack with React: an in-depth tutorial

Esau Silva

Updated to Babel 7

In this tutorial we will see the basics of Webpack for React to get you started, including React Router , Hot Module Replacement (HMR), Code Splitting by Route and Vendor , production configuration and more.

Before we start, here’s the full list of features we are going to set up together in this tutorial:

  • React Router 5
  • Semantic UI as the CSS Framework
  • Hot Module Replacement (HMR)
  • CSS Autoprefixer
  • CSS Modules
  • @babel/plugin-proposal-class-properties
  • @babel/plugin-syntax-dynamic-import
  • Code Splitting by Route and Vendor
  • Webpack Bundle Analyzer

Pre-requisites

Have the following pre-installed:

  • Yarn — Package manager, similar to npm

And you should have at least some basic knowledge of React and React Router.

Note: You can use npm if you wish, although the commands will vary slightly.

Initial Dependencies

Let us start by creating our directory and package.json .

In your terminal type the following:

This first command will create our directory and move into it, then we initialize a package.json accepting defaults. If you inspect it you will see the bare bones configuration:

Now we install our initial (production) dependencies and development dependencies. In your terminal type the following:

The development dependencies will only be used, as implied, during the development phase, and the (production) dependencies is what our application needs in production.

Note: Changes to previously created files will be bolded. Note: Dependencies versions might be different than yours from the time of this writing.

  • react — I’m sure you know what React is
  • react-dom — Provides DOM-specific methods for the browser
  • prop-types — Runtime type checking for React props
  • react-router-dom — Provides routing capabilities to React for the browser
  • semantic-ui-react — CSS Framework
  • @babel/core — Core dependencies for Babel
  • Babel is a transpiler that compiles JavaScript ES6 to JavaScript ES5 allowing you to write JavaScript “from the future” so that current browsers will understand it. Detailed description in Quora .
  • babel-loader — This package allows transpiling JavaScript files using Babel and webpack
  • @babel/preset-env — With this you don’t have to specify if you will be writing ES2015, ES2016 or ES2017. Babel will automatically detect and transpile accordingly.
  • @babel/preset-react — Tells Babel we will be using React
  • @babel/plugin-proposal-class-properties — Use class properties. We don’t use Class Properties in this project, but you will more than likely use them in your project
  • @babel/plugin-syntax-dynamic-import — Be able to use dynamic imports
  • css-loader — Interprets @import and url() like i mport/require() and will resolve them
  • html-webpack-plugin — Can generate an HTML file for your application, or you can provide a template
  • style-loader — Adds CSS to the DOM by injecting a <sty le> tag
  • webpack — Module bundler
  • webpack-cli — Command Line Interface, needed for Webpack 4.0.1 and latest
  • webpack-dev-server — Provides a development server for your application

Setting up Babel

In the root directory ( webpack-for-react ) we create the Babel configuration file.

At this point you can open your favorite editor (mine is VS Code by the way), then point the editor to the root of this project and open .babelrc file and copy the following:

This tells Babel to use the presets (plugins) we previously installed. Later when we call babel-loader from Webpack, this is where it will look to know what to do.

Setting up Webpack

Now the fun begins! Let’s create the Webpack configuration file.

Open webpack.config.js and copy the following:

This is the basic shell for Webpack. We require webpack and html-webpack-plugin . Provide a default port if the environment variable PORT does not exist and export the module.

The following will be additions for webpack.config.js (one after another).

mode tells Webpack this configuration will be for either development or production . “Development Mode [is] optimized for speed and developer experience… Production defaults will give you a set of defaults useful for deploying your application ( webpack 4: mode and optimization )”.

To get a running instance of Webpack we need:

  • entry — Specifies the entry point of your application; this is where your React app lives and where the bundling process will begin ( Docs )

Webpack 4 introduced some defaults, so if you don’t include entry in your configuration, then Webpack will assume your entry point is located under the ./src directory, making entry optional as opposed to Webpack 3. For this tutorial I have decided to leave entry as it makes it obvious where our entry point will be, but you are more than welcome to remove it if you so decide.

  • output — Tells Webpack how to write the compiled files to disk ( Docs )
  • filename — This will be the filename of the bundled application. The [hash] portion of the filename will be replaced by a hash generated by Webpack every time your application changes and is recompiled (helps with caching).

devtool will create source maps to help you with debugging of your application. There are several types of source maps and this particular map ( inline-source-map ) is to be used only in development. (Refer to the docs for more options).

  • module — What types of modules your application will include, in our case we will support ESNext (Babel) and CSS Modules
  • rules — How we handle each different type of module

We test for files with a .js extension excluding the node_modules directory and use Babel, via babel-loader , to transpile down to vanilla JavaScript (basically, looking for our React files).

Remember our configuration in .babelrc ? This is where Babel looks at that file.

Second Rule

We test for CSS files with a .css extension. Here we use two loaders, style-loader and css-loader , to handle our CSS files. Then we instruct css-loader to use CSS Modules , camel case and create source maps.

CSS Modules and Camel Case

This gives us the ability to use import Styles from ‘./styles.css’ syntax (or destructuring like this import { style1, style2 } from ‘./styles.css’ ).

Then we can use it like this in a React app:

Camel case gives us the ability to write our CSS rules like this:

And use it in our React files like this:

This section is where we configure (as the name implies) plugins.

html-webpack-plugin accepts an object with different options. In our case we specify the HTML template we will be using and the favicon. (Refer to the docs for more options).

Later we will be adding other plugins for Bundle Analyzer and HMR.

Finally, we configure the development server. We specify localhost as the host and assign the variable port as the port (if you remember, we assigned port 3000 to this variable). We set historyApiFallback to true and open to true. This will open the browser automatically and launch your application in http://localhost:3000. ( Docs )

Now, below is the complete Webpack configuration. ( webpack.config.js ):

Creating the React App

We will be creating a simple Hello World app with three routes: a home , a page not found and a dynamic page that we will be loading asynchronously when we implement code splitting later.

Note: Assuming you have a basic understanding of React and React Router, I will not go into many details and only highlight what’s relevant to this tutorial.

We currently have the following project structure:

We create a public directory, move into it and also create an index.html file. Here is where we also have the favicon . You can grab it from here and copy it into public directory.

Open the index.html file and copy the following:

Nothing much here (just a standard HTML template) only, we are adding the Semantic UI stylesheet and also creating a div with an ID of root . This is where our React app will render.

Back to your terminal type the following:

Open index.js and copy the following:

After creating the React component files, we have the following project structure:

Open App.js and copy the following:

We create our basic “shell” with React Router and have a home , dynamic page and page not found route.

Open Layout.css and copy the following:

Open Layout.js and copy the following:

This is our container component where we define the layout of the site. Making use of CSS Modules, we are importing two CSS rules from layout.css . Also notice how we are using camel case for pullRight .

Open Home.js and copy the following:

Open DynamicPage.js and copy the following:

Open NoMatch.js and copy the following:

We are done creating the React components. For a final step before running our application, open package.json and add the bolded lines:

We add the scripts key and also the start key. This will allow us to run React with the Webpack Development Server. If you don’t specify a configuration file, webpack-dev-server will look for webpack.config.js file as the default configuration entry within the root directory.

Now the moment of truth! Type the following in your terminal (remember to be in the root directory) and Yarn will call our start script.

iHJNOlQ4O11i7ONPbmXDRkbKF7WAGqZRFcCY

Now we have a working React app powered by our own Webpack configuration. Notice at the end of the GIF I am highlighting the bundled JavaScript file Webpack generated for us, and as we indicated in the configuration, the filename has a unique hash, bundle.d505bbab002262a9bc07.js .

Setting up Hot Module Replacement (HMR)

Back to your terminal, install React Hot Loader as a development dependency.

Open .babelrc and add lines 3 and 9. Don’t forget to include the comma (,) at the end of line 3:

Open webpack.config.js and modify it as below.

I’m only including the relevant code and omitting code that stayed the same for brevity.

  • publicPath: ‘/’ — Hot reloading won’t work as expected for nested routes without it
  • webpack.HotModuleReplacementPlugin — Prints more readable module names in the browser terminal on HMR updates
  • hot: true — Enable HMR on the server
  • resolve: alias  — replaces react-dom with the custom react-dom from hot-loader

Open index.js and change it to the following.

Now we are ready to test HMR! Back in the terminal run your app, make a change, and watch as the app updates without a full-page refresh.

tBaz3tT6Vsnxk7ijy1xFl03YFWmktaaktUWH

After updating the file, the page changes without a full refresh. To show this change in the browser I select Rendering -> Paint flash ing in Chrome DevTools, which highlights the areas of the page, in green, that changed. I also highlight in Terminal the change Webpack sent to the browser to make this happen.

Code Splitting

With code splitting , instead of having your application in one big bundle, you can have multiple bundles each loading asynchronously or in parallel. Also you can separate vendor code from you app code which can potentially decrease loading time.

There are several ways we can achieve code splitting by route, however in our case we will be using react-imported-component .

We would also like to show a loading spinner when the user navigates to a different route. This is a good practice as we don’t want the user to just stare at a blank screen while he/she waits for the new page to load. So, we will be creating a Loading component.

However, if the new page loads really fast, we don’t want the user to see a flashing loading spinner for a couple of milliseconds, so we will delay the Loading component by 300 milliseconds. To achieve this, we will be using React-Delay-Render .

Start by installing the two additional dependencies.

Now we are going to create the Loading components.

Open Loading.js and copy the following:

Now that we have the Loading component, open App.js and modify it as follows:

This will create three bundles, or chunks, one for the DynamicPage component, one for the NoMatch component, and one for the main app.

Let’s also change the bundle filename. Open webpack.config.js and change it as follows:

It is time to run the app and take a look at code splitting by route in action.

dNGa5cqDKitNHQAKtH7ZDce3fvrCCWuE1zYh

In the GIF, I first highlight the three different chunks created by Webpack in terminal. Then I highlight that upon the app launching, only the main chuck was loaded. Finally, we see that upon clicking Navigate to Dynamic Page the chunk corresponding to this page loaded asynchronously.

We also see that the chunk corresponding to the page not found was never loaded, saving the user bandwidth.

Now let’s split the application by vendor. Open webpack.config.js and make the following changes:

  • entry.vendor: [‘semantic-ui-react’] — Specifies which library we want to extract from our main app and into the vendor chunk
  • optimization — if you leave out this entry, Webpack will still split your application by vendor, however I noticed the bundle sizes were big and after addding this entry, the bundle sizes were reduced significantly. (I got this from Webpack 4 migration draft CommonsChunkPlugin -> Initial vendor ch unk)

Note: Previously Webpack 3 made use of the CommonsChunkPlugin to split the code by vendor and/or commons, however it was deprecated in Webpack 4 and many of its features are now enabled by default. With the removal of CommonsChunkPlugin they have added optimization.splitChunks for those who need fine-grained control over their caching-strategy (See this for an in-depth explanation).

In terminal, launch the app:

L5D5dDH3r5DkNfhN2oilt1BaejnhCYfpdnQw

In terminal, I highlight the three previous chunks plus the new vendor chunk. Then when we inspect the HTML we see that both vendor and app chunks were loaded.

Since we have made several updates to our Webpack configuration, below you will find the complete webpack.config.js file.

Production Configuration

Rename the Webpack configuration from webpack.config.js to webpack.config. development .js . Then make a copy and name it webpack.config.production.js .

We will need a development dependency, Extract Text Plugin . From their docs: “It moves all the required *.css modules in entry chunks into a separate CSS file. So, your styles are no longer inlined into the JS bundle, but in a separate CSS file ( styles.css ). If your total stylesheet volume is big, it will be faster because the CSS bundle is loaded in parallel to the JS bundle.”

Open webpack.config.production.js and make the following bolded changes:

Doing something different here…I will add explanations with inline comments.

Notice we removed the port variable, the plugins related to HMR and the devServer entry.

Also since we added PostCSS to the production configuration, we need to install it and create a configuration file for it.

Open postcss.config.js and copy the following:

Here we are specifying what browsers we want autoprefixer (Refer to the Docs for more options) to support and minifying the CSS output.

Now for the last step before we create our production build, we need to create a build script in package.json .

Open the file and make the following changes to the scripts section:

First thing to notice here is that we changed the start script from start to dev , then we added two additional scripts, prebuild and build .

Finally, we are indicating which configuration to use when in development or production.

  • prebuild — Will run before the build script and delete the dist directory created by our last production build. We use the library rimraf for this
  • build — First we use cross-env library just in case somebody is using Windows. This way setting up environment variables with NODE_ENV will work. Then we call Webpack with the -p flag to tell it to optimize this build for production, and finally we specify the production configuration.

In your terminal install the two new dependencies we included in package.json :

Before creating the production build, let us look at our new project structure:

At last we can create our production bundle.

T81PYokNYP1m76WiEbGipkFrmGYKee46P4IR

As you noticed, after we ran the build script, Webpack created a dist directory containing our production ready app. Now inspect the files that were created and notice they are minified and each has a corresponding source map. You will also notice PostCSS has added autoprefixing to the CSS file.

Now we take our production files and fire up a Node server to serve our site, and this is the result:

A44vaXq-Jc68ClNMgWe5O0o4a3XjIfj3XLrU

Note: I am using this server in the GIF above to serve our production files.

At this point we have two working Webpack configurations, one for development and one for production. However, since both configurations are very similar, they share many of the same settings. If we wanted to add something else, we would have to add it to both configurations files. Let’s fix this inconvenience.

Webpack Composition

Let’s start by installing webpack-merge and Chalk as development dependencies.

We will also need a couple of new directories and a few new files.

Now let’s look at our new project structure:

Open common-paths.js and copy the following:

Here we define, as the name implies, the common paths for our Webpack configurations. PROJECT_ROOT needs to look one directory up as we are working under build-utils directory (one level down from the actual root path in our project).

Open build-validations.js and copy the following:

Later when we modify our package.json we will be requiring –env.env flag in the scripts. These validations are to verify that the flag is present; if not, it will throw an error.

In the next three files, we will be separating the Webpack configurations into configurations that are shared among development and production, configurations that are only for development and configurations only for production.

Open webpack.common.js and copy the following:

We basically extracted out what was shared among webpack.config.development.js and webpack.config.production.js and transferred it to this file. At the top we require common-paths.js to set the output.path .

Open webpack.dev.js and copy the following:

This is the same concept as with the previous file. Here we extracted out development only configurations.

Open webpack.prod.js and copy the following:

We extracted out production only configurations.

Now that we have the shared configurations and the ones specific for development and production in separate files, it is time to put everything together.

In terminal, if you are still in build-utils directory, go up one level to the root of the project, then delete the previous Webpack configurations and create a new Webpack configuration. Name it webpack.config.js .

Before configuring webpack.config.js , let’s open package.json and update the scripts section.

Modify the section as follows:

Since we removed the –config flag, Webpack will now be looking for the default configuration, which is webpack.config.js . Now we use the –env flag to pass an environment variable to Webpack, env=dev for development and env=prod for production.

Explanations with inline comments.

Now, this might seem like a lot of setup, but in the long run, it will come in handy.

At this time, you can launch the application or build the production files, and everything will function as expected (sorry, no GIF this time).

Note: This “Webpack Composition” technique was taken from Webpack Academy , a free course by Sean Larkin which I recommend taking to learn more about Webpack, not specific to React.

BONUS: Setting up Webpack Bundle Analyzer

You don’t necessarily need Webpack Bundle Analyzer , but it does comes in handy when trying to optimize your builds.

Start by installing the dependency and creating the configuration file.

Open webpack.bundleanalyzer.js and copy the following:

We are just exporting the plugins section, which includes Bundle Analyzer, for Webpack. Then webpack-merge will combine it into the final Webpack configuration. Remember the addons in webpack.config.js ? Well, this is where it comes into place.

For the final step, let’s open package.json and include the new scripts as follows:

  • dev:bundleanalyzer — Calls the dev script and passes a new environment variable addons=bundleanalyzer
  • build:bundleanalyzer — Calls the build script and passes a new environment variable addons=bundleanalyzer

Time to run the app with the bundle analyzer addon.

EFwowawQtLlHdJQGL9gwuz77O2wfhz784xW2

The application launches alongside Webpack Bundle Analyzer.

Including addons with Webpack Composition can be very useful, as there are many plugins that you would want to use only at certain times.

First of all, you can get the full code on the GitHub repository .

Well, you made it to the end. Congratulations!! ? Now that you know the basics (and a little more) of Webpack for React, you can go ahead and keep exploring and learning more advanced features and techniques.

Thank you for reading and I hope you enjoyed it. If you have any questions, suggestions or corrections let me know in the comments below. Don’t forget to give this article a Share and some Claps ??.

You can follow me here on Medium , Twitter , GitHub , LinkedIn or all of them.

This article was originally published on my personal blog website .

Update 8/25/19: I have been building a prayer web app called " My Quiet Time - A Prayer Journal ". If you would like to stay in the loop please sign up through the following link: http://b.link/mqt  

The app will be released before the end of the year, I have big plans for this app. To see some mockup screenshots follow the following link: http://pc.cd/Lpy7

My DMs on Twitter are open if you have any questions regarding the app ?

Full Stack Software Engineer and avid Brazilian Jiu-Jitsu practitioner

If you read this far, thank the author to show them you care. Say Thanks

Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started

DEV Community

DEV Community

Alex Eagleson

Posted on Oct 8, 2021 • Updated on Oct 9, 2021

  • Understanding the Modern Web Stack: Webpack - The Basics

(This tutorial is written using webpack v5 however the general concepts will apply to any version)

Table of Contents

  • What is Webpack?

Prerequisites

Initializing the project, why bundling, installing webpack, webpack plugins, modules in javascript.

  • Modules in webpack

Minimizing Bundle Size

Wrapping up, what is webpack.

In webpack's own words :

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 to serve your content from.

If you find it difficult to understand exactly what that means, don't worry at all, that's why we're here!

Many of us, including myself, first seek out webpack tutorials when we reach a point with our projects when we know we need it -- but we may not know exactly what we need it to do, or the specific terms to describe the problems we are trying to solve.

webpack (stylized with a lowercase w ) is extremely configurable and customizable by design, which means that at the cost of a slightly higher learning curve than an out-of-the-box solution, you get incredible power to do whatever it is you need to do.

If webpack core doesn't do it, you can get a plugin. If you can't find a plugin for it, you can write your own plugin. You're probably getting the idea at this point.

The idea behind this tutorial is that we will keep things as simple as possible. Start with a super basic web app / page, and gradually add pieces as you would on a real project until you encounter a scenario where you realize webpack would help.

At that point we install, configure, and add it to our project.

So we're ready to dive in -- but before we do there are a few prerequisites we should address first.

You will need to have Node.js installed on your machine and available from your terminal. Installing Node will automatically install npm as well, which is what you will use to install Babel.

Open up your terminal of choice. If you see version numbers when running the two commands below (your numbers will likely be different than this example) then you are ready to go:

You will want to have at least a basic understanding of Javascript . We don't deal with any complicated code in this tutorial, but we'll assume you can comfortable read simple programs. webpack's configuration file is written in JS format.

We will assume you have the ability to run a local server and test the HTML/JS code we are using. If not, then check out this tutorial first:

  • Understanding the Modern Web Stack: Running a Local Web Server

Let's start by initializing a new npm project. Run the following command to generate one:

The -y flag will automatically select default values for everything, which is appropriate in our example.

We'll start by creating an HTML entry point where we can load and test our bundle. Any basic HTML template will work. Create a file called index.html in your root directory. If you are using VS Code you can generate an instant template by opening the file and typing ! (then click ! menu).

Otherwise we can use the template below:

Next we will create a directory called src . in the root directory of your project. Inside that directory we will have a file called script.js with the following code:

src/script.js

(You will notice that at this beginning stage we are essentially following along with webpack's own fantastic Getting Started guide. webpack's documentation is known for being extremely high quality thanks to its amazing contributors .)

You may notice that we are using a Lodash function inside our script.js file. That's the little _ underscore variable with the join() method. Might be a bit of a simplistic example, but you can replace it with any scenario you can imagine where you might want to use the benefit of an external library function rather than coding it yourself.

Since we are using Lodash in our file, we'll need to add it to our project. From the root directory run the following terminal command:

Now your directory structure should look like this:

Next we need to load both our script.js file and the Lodash library into out index.html to see everything work together. Update your index.html file like so:

Make sure to notice a couple about our script tags. script.js must be prefixed with src/ as it is in that directory, and since our JS is working with the DOM, we want to use the defer attribute so that it doesn't load until after the HTML is finished parsing.

At this point you can serve up your root directory and you should be able to see the following result:

Page Example

If you are not sure how to host a local server check out this post to help get you up and running:

So if everything is working, what do we need webpack for? Well consider if you were now planning to release this as a product. You want to be able to say Hello webpack to the entire world! You're hoping to get a minimum of 1 million unique visitors per day.

You take your project directory and you upload it to your web server. You need to make sure you also include the node_modules folder because that's where the Lodash library is. Every time our page loads, it loads the lodash.min.js file. Every one of our million users per day (disregarding cache and gzip options for the moment) will be downloading this file.

Lodash is a huge library that comes with tons of great functions for all kinds of different use cases. Even after being minified, our lodash.min.js file is still a sizable 73KB. That's 73KB of data for every user just to gain access to the join() function.

Wouldn't it be great if we could just extract that join() function and leave behind all the excess parts of the library we aren't using?

That's where webpack comes in.

Let's take a look at what each one is doing:

webpack - This is the main engine of webpack, it understands everything related about how the code and files relate to one another, and how to bundle them into a single package.

webpack-cli - This is the actual program we are going to run to trigger the core engine. It allows us to run webpack on our command line and generate a bundle.

Our first goal will be to simply configure webpack to process our script.js file and output it without doing any transformations. We'll add those in soon after.

Create a new file in the root directory called webpack.config.js with the following code:

webpack.config.js

Before we fun this, let's look at what we expect it will do:

mode - This determines what kind of extra processing is done to your output file.

  • none - No extra processing at all. We are using this for the tutorial because it makes the output file cleaner for a human to read and understand.
  • development - Extra work done to add features that make debugging and tracing issues easier. Will be slower and result in larger file sizes. Designed only to be used during development.
  • production - Removes all unnecessary code and only produces the smallest and leanest file possible. Designed for your release build.

entry - The starting point of our app, it's pointing to our script.js file with our Javascript code

output - This is the name and location of the file it fill generate after all the bundling is done. This is the file our index.html file will load. Includes both the name of the file and path. We are going to output everything into a directory called dist

Let's run webpack now and see if our assumptions are true. ON your terminal run:

We don't need any arguments with that command because it gets all the config information it needs automatically from your webpack.config.js file. At this point you should see a file generated called main.js in your dist folder that looks nearly identical to your script file.

The idea is that your entire project gets bundled into the dist directory and that is what you upload to your server as your release build. OUr issue right now however is that neither your index.html nor your node_modules folder existed in your dist folder. If you tried to release your project now there would be nothing to load.

We will start by configuring webpack to bundle your index.html in your output. We could technically just copy it in there ourselves, but of course webpack has its own way of handling that. This is where we introduce our first plugin.

Plugins are code that give webpack additional information about how to perform certain tasks. The most common one you will use is called HtmlWebpackPlugin . Its purpose is exactly as we described above, to let you include an HTML file in your output bundle.

Before we can use it, we have to add it to our project. Run the following command:

Once that is installed we update our webpack config file:

Two new lines have been added indicated with the "NEW" comments. We need to first require the plugin, and then add it to our config.

We are also going to move our index.html file into our src directory. The src directory will be the location of all our source code related to the web application itself. Config files can continue to live in the project root directory. When we move the index file we are going to update and remove a couple of the script tags.

Our new file looks like: src/index.html

The only different here is that we have removed the two <script> tags with our script.js and the Lodash library. We'll see why in a moment. Before we run let's confirm the shape of our project directory:

Now let's run our npx webpack command again and take a look at the output.

Inside your dist directory thanks to our new plugin you should see an index.html file. It will look the same as your template with one exception.

HtmlWebpackPlugin has automatically added that script tag for you based on the output filename in your webpack.config.js file. Pretty cool!

Now you can update your HTML template in your src directory any time you like, and a copy will be generated on webpack run that automatically points to your bundle.

Next, if you remember, we removed the reference to the Lodash library, so we're still not ready to run the app. Before we're ready to do that there's an extremely important concept we need to understand called modules .

Modules are not a unique feature of webpack, they are a core part of the modern Javascript ecosystem. The quick and easy explanation is that they are designed as a way to separate unrelated pieces of code to make it easier to build systems that don't overlap unnecessarily.

A good example is Lodash, It is comprised of smaller modules that separate the methods it provides between the ones that work on objects vs arrays vs strings. Keeping them separate makes it easier for developers to work with them and reason about them.

Modules have a long and complicated history because they never existed in the original design of the language, so there have always been challenges in both syntax standardization and browser support.

Fortunately webpack supports virtually all module styles, so you can write your code the way you want and run it in any browser. For the sake of our tutorial we are going to use the modern native module syntax of import and export .

Modules in Webpack

Modules in the webpack ecosystem act as a means for your code to communicate to webpack a list of exactly which pieces are needed.

With this information, webpack can build a dependency graph of all the relationships in your project.

The real power of this graph becomes apparent when you realize that once webpack knows exactly what your program is using, it can leave behind everything that it isn't.

That's not just full Javascript files either. It can extract individual values and functions from JS files, and even individual files themselves -- for example only pulling images and fonts that your project uses from a large directory of fonts.

This gives you (the developer) the luxury of having instant access to any image or font you want while working, and then when you build your project for release you only include the ones you actually use.

Ultimately this describes the true value or webpack, and why it's one of the most popular common tools in real world applications today.

So with that said, let's take a look at how we can apply this knowledge to extract only the piece of the Lodash library that we are actually using. We will begin by adding an import statement to our script.js file:

The new line import _ from 'lodash' is telling JS to load the entirety of the lodash library and make all the code available on the _ variable. If you try and run this code in classic browsers (or even modern ones without the proper config) you will see an error, but webpack understands it perfectly.

Let's run npx webpack again and check the output.

You can see that dist.main.js has now ballooned from roughly ~15 lines of code to almost 20,000! That's because webpack has done exactly what we asked it to do: load the entirely of Lodash into our project.

When you run the npx webpack command you will also get some great bundle information on the terminal. Let's take a quick look at that:

Lodash Bundle Large

Our main.js is a whopping 536KB in size. The info also tells us that 531KB of that comes from lodash.js .

This would be a good time to test out the difference production mode.

Edit your webpack.config.js file to change mode to production from none and then run npx webpack again. You will probably find you have to wait a bit longer, as your machine is working hard to minimize the size of these files.

Here's what the bundle information looks like now:

Lodash Bundle Medium

We've made a huge drop from 536KB to 69.5KB in our main.js file!

If you're wondering where all that space went take a look at dist/main.js . Since this is considered a production release the most important thing is fast speeds and small file sizes, it's no longer important that the developer be able to read the file. So webpack shrinks it down into the smallest size it can while still having the same function.

This process is called minification .

But even though the library is minified, we're still including the entire library while only using the single join() function. The final step is simply to change what we are asking to do.

If you recall the line:

We are specifically asking JS to load everything from Lodash and place it into our file, but that's not actually what we want. We only want the join function.

The syntax for exactly how to do so will depend on the way the library itself has set up ts modules (if at all). It's good practice to check the library's documentation before you decide how you will do your imports.

Lodash makes each individual function available in its own JS file (you can see this easily by simply navigating to node_modules/lodash ).

Rather than importing from the lodash.min.js file that contains everything , let's just import from the join.js file that contains the function we want.

So we change the syntax of our import to:

Since we are now importing the join function directly and not creating the underscore variable, we need to change the _.join() syntax to just join() .

Before we run our bundler again let's change the mode in webpack.config.js back to none so that we can see exactly what the output looks like in a human-readable format.

Run npx webpack again and look at the bundle info:

Lodash Bundle Small

We are now down from 69.5KB to only 4KB! And we switched out of production mode so that's not even minified! We could still shrink it even further if we wanted.

Let's take a look at our dist/main.js output file to see what happened.

We're down to around 100 lines (including some webpack administrative code for modules). It should be possible for you to see with your own eyes how your code from script.js has been blended into a single file along with Lodash's join() function.

And that's webpack! You can write your code in as many files as you like, with import and export to manage how they depend and relate to each other, and still package it all together into an efficient single JS file that any browser can load, regardless of its support for modules.

You now understand the fundamentals of webpack. Of course there's a lot more to it, and we'll continue to explore those features ahead, but this is a great place to stop and take a breather and absorb what you've learned so far.

Everything onward from here just builds on these same concepts you've just learned. When you're ready, check out some of the more advanced tutorials introducing loaders, optimization, DevServer, React & Typescript.

Please check out the other entries in this series! Feel free to leave a comment or question and share with others if you find any of them helpful:

  • Understanding the Modern Web Stack: Babel
  • Understanding the Modern Web Stack: Webpack - Loaders, Optimizations & Bundle Analysis
  • Understanding the Modern Web Stack: Webpack - DevServer, React & Typescript

@eagleson_alex on Twitter

Thanks for reading, and stay tuned!

Top comments (10)

pic

Templates let you quickly answer FAQs or store snippets for re-use.

audreybozorgi profile image

  • Education later...
  • Work later...
  • Joined Apr 14, 2022

two problems.

  • first one where you said index.html and script.js exist in dist folder, but you mean they does not exist in
  • second : in body you should have a div element with id='div' due to your script.js run correctly

junxdev profile image

  • Joined Jan 4, 2023

This is the perfect guide to Webpack for beginners who has started front-end dev with modern stacks like React, Vue. Other articles end at "Yeah, Webpack is a bundler and bundling is good, so that's why we use". This tells us how we were doing in the past without bundlers so that has us understand why we use them.

If u don't mind, Could I post a summary in Korean with the reference link?

ps173 profile image

  • Email [email protected]
  • Location India, Delhi
  • Work Software engineer at codeword.tech
  • Joined Nov 20, 2020

Thanks a lot. This helped me understand webpack better

alexeagleson profile image

  • Email [email protected]
  • Location Barrie, Ontario
  • Education University of Guelph
  • Work Rust Developer @ 1Password
  • Joined Jun 27, 2021

Glad it helped!

srikanth597 profile image

  • Location India
  • Work Software Engineer II at Intuit
  • Joined Sep 12, 2020

Excellent Alex, I'm excited to read your next articles. Presentation is excellent

bronkan profile image

  • Joined Apr 28, 2021

That's the clearest explanation I've read so far! Thanks a lot!!!!!

supernova12034 profile image

  • Joined Jun 18, 2022

Phenomenal article, thanks for writing it!

hayder86al profile image

  • Joined May 27, 2023

Thanks alot very helpful :)

benphs5 profile image

  • Work Full Stack Developer at monday.com
  • Joined Jun 1, 2020

This series is awesome! Thank you Alex :)

h0sny profile image

  • Joined Oct 8, 2021

that was solid , thanks for sharing

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink .

Hide child comments as well

For further actions, you may consider blocking this person and/or reporting abuse

johndivam profile image

Filament: add a confirmation password field in a form

JohnDivam - Jun 26

alisamirali profile image

Understanding Progressive Web Apps (PWAs) 🔥

Ali Samir - Jul 5

jkettmann profile image

Path To A Clean(er) React Architecture (Part 7) - Domain Logic

Johannes Kettmann - Jul 5

vyan profile image

10 Facts About ReactJS Lazy Loading: Optimizing Your Web Application's Performance

Vishal Yadav - Jul 5

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

ag grid

In this guide, we'll dive into some of the best practices and utilities for building a production site or application.

The goals of development and production builds differ greatly. In development , we want strong source mapping and a localhost server with live reloading or hot module replacement. In production , our goals shift to a focus on minified bundles, lighter weight source maps, and optimized assets to improve load time. With this logical separation at hand, we typically recommend writing separate webpack configurations for each environment.

While we will separate the production and development specific bits out, note that we'll still maintain a "common" configuration to keep things DRY. In order to merge these configurations together, we'll use a utility called webpack-merge . With the "common" configuration in place, we won't have to duplicate code within the environment-specific configurations.

Let's start by installing webpack-merge and splitting out the bits we've already worked on in previous guides:

webpack.common.js

webpack.dev.js

webpack.prod.js

In webpack.common.js , we now have setup our entry and output configuration and we've included any plugins that are required for both environments. In webpack.dev.js , we've set mode to development . Also, we've added the recommended devtool for that environment (strong source mapping), as well as our devServer configuration. Finally, in webpack.prod.js , mode is set to production which loads TerserPlugin , which was first introduced by the tree shaking guide.

Note the use of merge() calls in the environment-specific configurations to include our common configuration in webpack.dev.js and webpack.prod.js . The webpack-merge tool offers a variety of advanced features for merging but for our use case we won't need any of that.

NPM Scripts

Now, let's modify our npm scripts to use the new configuration files. For the start script, which runs webpack-dev-server , we will use webpack.dev.js , and for the build script, which runs webpack to create a production build, we will use webpack.prod.js :

package.json

Feel free to run those scripts and see how the output changes as we continue adding to our production configuration.

Specify the Mode

Many libraries will key off the process.env.NODE_ENV variable to determine what should be included in the library. For example, when process.env.NODE_ENV is not set to 'production' some libraries may add additional logging and testing to make debugging easier. However, with process.env.NODE_ENV set to 'production' they might drop or add significant portions of code to optimize how things run for your actual users. Since webpack v4, specifying mode automatically configures process.env.NODE_ENV for you through DefinePlugin :

If you're using a library like react , you should actually see a significant drop in bundle size after adding DefinePlugin . Also, note that any of our local /src code can key off of this as well, so the following check would be valid:

src/index.js

Minification

Webpack v4+ will minify your code by default in production mode .

Note that while the TerserPlugin is a great place to start for minification and being used by default, there are other options out there:

  • ClosureWebpackPlugin

If you decide to try another minification plugin, make sure your new choice also drops dead code as described in the tree shaking guide and provide it as the optimization.minimizer .

Source Mapping

We encourage you to have source maps enabled in production, as they are useful for debugging as well as running benchmark tests. That said, you should choose one with a fairly quick build speed that's recommended for production use (see devtool ). For this guide, we'll use the source-map option in the production as opposed to the inline-source-map we used in the development :

Minimize CSS

It is crucial to minimize your CSS for production. Please see the Minimizing for Production section.

CLI Alternatives

Many of the options described above can be set as command line arguments. For example, optimization.minimize can be set with --optimization-minimize , and mode can be set with --mode . Run npx webpack --help=verbose for a full list of CLI arguments.

While these shorthand methods are useful, we recommend setting these options in a webpack configuration file for more configurability.

21 Contributors

rajagopal4890

InfoQ Software Architects' Newsletter

A monthly overview of things you need to know as an architect or aspiring architect.

View an example

We protect your privacy.

InfoQ Dev Summit Munich (Sep 26-27): Learn practical strategies to clarify critical development priorities. Register Now

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

  • English edition
  • Chinese edition
  • Japanese edition
  • French edition

Back to login

Login with:

Don't have an infoq account, helpful links.

  • About InfoQ
  • InfoQ Editors
  • Write for InfoQ
  • About C4Media

Choose your language

webpack presentation

Get clarity from senior software practitioners on today's critical dev priorities. Register Now.

webpack presentation

Level up your software skills by uncovering the emerging trends you should focus on. Register now.

webpack presentation

Discover emerging trends, insights, and real-world best practices in software development & tech leadership. Join now.

webpack presentation

Your monthly guide to all the topics, technologies and techniques that every professional needs to know about. Subscribe for free.

InfoQ Homepage Presentations Webpack: The One Build Step to Rule Them All

Webpack: The One Build Step to Rule Them All

Sean Larking talks about the four concepts everyone should know when using Webpack so they can take and make it their own.

Sean Larkin is a User Experience Developer at Mutual of Omaha. He is a member of the Webpack core team, Angular team and Angular-CLI core team.

About the conference

Software is changing the world. QCon empowers software development by facilitating the spread of knowledge and innovation in the developer community. A practitioner-driven conference, QCon is designed for technical team leads, architects, engineering directors, and project managers who influence innovation in their teams.

webpack presentation

Recorded at:

webpack presentation

Jan 22, 2017

Sean Larkin

This content is in the Web Development topic

Related topics:.

  • Development
  • QCon San Francisco 2016
  • Dynamic Languages
  • Artifacts & Tools
  • QCon Software Development Conference
  • Software Build
  • Web Development

Sponsored Content

Related editorial, related sponsored content, [ebook] how to build a software factory to support devsecops, related sponsor.

webpack presentation

Join Red Hat Developer for the software and tutorials to develop cloud applications using Kubernetes, microservices, serverless and Linux.

webpack presentation

Advisory boards aren’t only for executives. Join the LogRocket Content Advisory Board today →

LogRocket blog logo

  • Product Management
  • Solve User-Reported Issues
  • Find Issues Faster
  • Optimize Conversion and Adoption
  • Start Monitoring for Free

Building micro-frontends with webpack’s Module Federation

webpack presentation

Good frameworks exist out there that help us create micro-frontends such as single-spa and OpenComponents. But what if we don’t want to integrate a different framework in our architecture? Let’s take a look at how to implement micro-frontends in our Vue apps.

Deploying Micro-Frontends Using webpack's Module Federation

In this article, we will discuss how to dramatically simplify our app architecture by using webpack 5’s Module Federation to consume and share micro-frontend components with example code.

What is module federation?

Module federation is a JavaScript architecture invented by Zack Jackson . This architecture allows the sharing of code and dependencies between two different application codebases.

The code is loaded dynamically, and if a dependency is missing, the dependency will be downloaded by the host application, which allows for less code duplication in the application.

What are micro-frontends?

The concept of micro-frontends has been gaining traction in recent times. The push for microservices has also brought about the same implementation to the modern web in the form of micro-frontends. As the monolith app scales, it becomes difficult to maintain, especially across several teams working on the same app.

We can look at micro-frontends as feature-based, where there are different teams and each team handles a particular feature component while another team handles something else. In the end, all teams merge the different components they have built to form one application.

Developers made use of frameworks like single-spa and OpenComponents to achieve this, but with the new release of webpack 5 and the module federation, we can easily achieve the same goal, but way easier.

The advantages of micro-frontends

Adopting a micro-frontend approach to building your web applications is probably the best strategy. This is especially true if you are building a large-scale web application with many moving parts or applications that are branched out into sub-applications where you want some consistency in the overall look.

Let me highlight a few reasons you might want to switch to the micro-frontend approach:

  • Adopting a micro-frontend approach will allow us to create an end-to-end feature architecture. This approach will allow us to develop and deploy features locally, without the need for large-scale deployment infrastructures
  • With a smaller and more optimized bundle size, micro-frontends provide an overall better developer and user experience as a result of shared components and dependencies that can be lazy loaded whenever we want
  • One of the biggest advantages for me is the ability for teams of developers working on that particular product to be able to pick a technology stack of their choice without fear of incompatibility with the other team’s code

How do we split our apps?

These are some ways developers split large apps:

  • By page ⁠— In our frontend applications, sometimes having different pages run at the same time in the browser can cause a crash in older devices, so the safest way is to split by page. If you have good routing, you can run separate, specific micro-apps for every page, which is also good for the developers on your team, because they will always work on that one page assigned to them
  • By functionality ⁠— If you have one page with multiple things features performing different operations, you can split those big features into smaller apps and make it an independent application running that specific feature
  • By section ⁠— You can also split your applications by section, with different apps sharing the same section or components

Proof of concept

We have explained some concepts about micro-frontends and module federation. Now it’s time for a proof of concept.

Here, we will demonstrate how we can use the module federation to create micro-frontends in Vue. To test this out, we will be spinning up two different apps, so we can create a micro-frontend in one of them and share it with the other.

First, we create a folder to host the two Vue applications:

It is in the vue-mf folder we will run our Vue application. We won’t be using the Vue CLI here. Instead, we will be using the new release of webpack, which is webpack 5, to set up the Vue application.

We will name the two applications we want to share components as Company and Shop respectively. We create a folder for each of them in the vue-mf folder and then grab a webpack starter file of Vue created by Jherr from GitHub into each folder:

Let’s take a look at the file structure now that we have set up the app:

When we open up one of the app folders, this is the structure:

Set up webpack config

So we have two apps, Company and Shop , which are exactly the same for now. When we survey the file structure, we take a look at the package.json . We have our webpack loader, CSS loader, and all the basic loaders and webpack stuff we need:

If we take a look at the webpack.config.js file, we can see that our public path is set to port 8080 . We can also see webpack checking for our file extensions and using the appropriate loaders.

The important thing to take note of here is our Vue loader plugin used in parsing our files and the Module federation plugin from webpack 5 we have imported and used, which will allow us to perform sharing functionality. We will get back to the configuration of the ModuleFederationPlugin later in this tutorial.

webpack presentation

Over 200k developers use LogRocket to create better digital experiences

webpack presentation

N.B., make sure to set the public path and dev server port in the other application (Shop) to port 8081 , so we can be able to run both apps simultaneously.

Create components to be shared

In our application, the App.vue file will serve as the homepage, so let’s add some markup:

The header component is one part of an application we would like to share between applications. Let’s say one of the teams of developers decides to build the header, so we create a header component that we can share in the two applications.

In the src folder in our Company app, we will create a header component. To do this, we create a Header.vue file, and in it, we create the header component:

After creating the header, navigate to App.vue and import the header component:

We can now start our development server by navigating to each folder and running:

Right now our app looks like this in the Company app.

Sample App for a Vue Micro-Frontend

Exposing the header component through the Module Federation plugin

We now have our header in the Company app, we would like to use it in the Shop app. So we head over to the webpack configuration in the Company app:

In the webpack Module Federation configuration, we set the name to the app name, which is Company , and remoteEntry.js to be our filename. When we navigate to the remoteEntry.js file name, we see the code related to the components and dependencies we want to share. We also exposed the header component with its location.

Now, if we restart our server and navigate to http://localhost:8080/remoteEntry.js , we will see this:

remoteentry.js Example for Vue Micro-Frontend

Now grab the remote entry URL and switch to the webpack configuration file in our Shop app:

Here, we give the plugin a name of Shop and set the remote to remoteEntry URL. Then in our App.vue file in the Shop app, we import and use the header component from our Company app:

If we restart our server, we can see that the shop page now has the header component, meaning we have successfully shared the component between the two apps. Yay!

N.B., if the team working on the header decides to push a new update for the header component, the Shop app team will immediately see the update once the Shop app is refreshed.

Sharing app state between federation modules

Let’s say you are using a state manager in your Vue application like Vuex. You might be asking yourself how you might have state, share it between the two components, and also have it update. So, let’s install Vuex for both apps:

Once we have installed Vuex, navigate to the bootloader.js file in our Company app, where we initialize our Vue app. Here, we import our store and create a state:

If, for instance, this is an ecommerce store where we want to display the number of cart items we have in our cart, we create a cartItems state and display it in our company header. Then go to our header component, access the state, and display it:

We have successfully set up our state, but the problem with this is if we start the server for both apps and check the Company app, we can see the header display with the state:

Header with State for Vue Micro-Frontend

But if we navigate to the Shop app, we can no longer see the shared header component anymore, much less the state we added. Instead, we get an error message that says we can’t read the state of undefined, because in our Shop app, we haven’t set up any store.

To rectify this problem, we copy all the code we have in the bootloader of the Company app and paste it into the bootloader.js file of the Shop app. This time, we changed the cartCount state to 12 . If we restart the server, we now have our header in the Shop app, with cart items of 12 .

Let’s say we want to mimic the addition of more shop items to the cart, so in the Shop app, we add a button that increments the cartCount state:

If we restart the Shop application, we can see that the items in the header now update. Yay!

  • GitHub source code
  • webpack 5’s Module Federation

We have come to the end of this tutorial.

Here, we discussed how to dramatically simplify our app architecture by using webpack 5 ’s Module Federation to consume and share micro-frontend components with example code.

Whether you should or should not adopt micro-frontends depends on the kind of project you are building, because this approach will not be the best for small applications or businesses. A micro-frontend architectural approach is your best bet when working on a large project with distributed teams.

Share this:

  • Click to share on Twitter (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Facebook (Opens in new window)

Hey there, want to help make our blog better?

Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

webpack presentation

Stop guessing about your digital experience with LogRocket

Recent posts:.

Exploring Native File Watching In Node Js Version 22

Exploring native file watching in Node.js v22

Native file watching being stable in Node.js 22 raises a question: is it a worthy candidate to replace the industry favorite Nodemon?

webpack presentation

Exploring the React Compiler: A detailed introduction

The new React Compiler promises to streamline frontend development with React by eliminating the need for manual memoization and optimization.

webpack presentation

Leveraging Perplexity AI for frontend development

Perplexity AI is a powerful tool that can transform how you approach development tasks, research information, and more.

webpack presentation

User agent detection and the ua-parser-js license change

Explore the recent license change for ua-parser-js, a library for user agent detection.

webpack presentation

3 Replies to "Building micro-frontends with webpack’s Module Federation"

Thanks for writing this. I think you should check out the articles and work of Florian Rappl like https://dev.to/florianrappl/11-popular-misconceptions-about-micro-frontends-463p . We recently migrated away from a larger monolith and first tried module federation. Did not work out well, as this made everything quite tight and spaghetti.

Micro frontends when done right require a lot more than just some tool like module federation.

Nice Article 👍

const HtmlWebPackPlugin = require(“html-webpack-plugin”); is missing webpack.config.js

Leave a Reply Cancel reply

Hi, I'm MalekBenz. I author this blog, I'm FullStack Developer, create courses & love learning, writing, teaching technology. ( Javascript, C#, ASP.NET , NodeJS, SQL Server )

Webpack for beginners.

  • By: Malekbenz
  • Category: Nodejs
  • tags: JavaScript, Nodejs, and Wabpack
  • Time: 03 Mar 2017

I was about creating a new project, and decided to use webpack to manage my dependency, so let’s me share with you what I think is the esiest way to learn Webpack, guess what ?… Exactly is by creating a simple project, so let’s do it.

  • If you don’t have node js already installed you can Install & run your first application Nodejs .

What is Webpack

Webpack is a powerful module bundler. A bundle is a JavaScript file that incorporate assets that belong together and should be served to the client in a response to a single file request. A bundle can include JavaScript, CSS styles, HTML, and almost any other kind of file.

Webpack roams over your application source code, looking for import statements, building a dependency graph, and emitting one (or more) bundles. With plugins and rules, Webpack can preprocess and minify different non-JavaScript files such as TypeScript, SASS, and LESS files.

CMD

You determine what Webpack does and how it does it with a JavaScript configuration file, webpack.config.js.

Entries and outputs

You supply Webpack with one or more entry files and let it find and incorporate the dependencies that radiate from those entries. The one entry point file in this example is the application’s root file, app/app.js and the outputs of these files is bundle.js file designated in configuration webpack.config.js :

This bundle.js output is a single JavaScript file that contains the application source and its dependencies. You’ll load it later with a script tag in the index.html

Sample application

Create a directory webpack-intro

CMD

Create new project and install webpack.

CMD

Now install Jquery :

CMD

Create a subdirectory app with an app.js file.

Create index.html and update the file :

In this case, there are implicit dependencies between the <script> tags .

app.js depends on jquery being included . It is implicit because index.js never declared a need for Jquery ; it just assumes that a global variable $ exists.

/CMD

Now run the the app:

/CMD

As you can see we access to $title and $ul variable from the console which is bad:

/CMD

Using Webpack.

Create a webpack.config.js file, and update with.

Remove jquery dependency from index.html , replace app/app.js with dist/bundle.js :

/CMD

Update app/app.js using import $ from jquery :

/CMD

Run the webpack cli :

/CMD

Now browse your application :

/CMD

Now open you F12 inspector and try to access $title and $ul variable:

/CMD

Using webpack with npm

We can set up a little shortcut. By updating package.json like this:

/CMD

You can now achieve the same as above by using npm run build command. npm picks up the scripts through it and patches the environment temporarily so that it contains the bin commands.

/CMD

That’s it see you soon!.

Recent posts

Sql server how to remove a duplicated rows.

  • Date: 11 Jun 2019
  • Category: SQL

Sql server how to remove a duplicated names using cursor

  • Date: 28 Jun 2018
  • Date: 20 Feb 2018
  • Category: GIT

How to truncate sql server log file

  • Date: 25 Jan 2018
  • Category: SQL Server

Reindexing in Elasticsearch

  • Date: 24 Jan 2018
  • Category: elasticsearch
  • Javascript 100
  • Express 100
  • Angularjs 100
  • Asp.Net 100
  • Optimization 100
  • SignalR 100
  • elasticsearch 100
  • SQL Server 100
  • sqlServer 100
  • EntityFramework
  • Compression
  • Optimization
  • elasticsearch

Copyright © 2023 - malekbenz Blog content licensed under the Creative Commons CC BY 2.5 | Unless otherwise stated or granted, code samples licensed under the MIT license .| privacy

Navigation Menu

Search code, repositories, users, issues, pull requests..., provide feedback.

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly.

To see all available qualifiers, see our documentation .

  • Notifications You must be signed in to change notification settings

"Webpack is Awesome" presentation.

unindented/webpack-presentation

Folders and files.

NameName
1,139 Commits

Repository files navigation

Webpack is awesome.

I think Webpack is an awesome tool, but not enough people know it. I want to change that.

Daniel ( @unindented )

Front-end developer at Yammer

What is Webpack

  • Module bundler
  • Understands CJS and AMD
  • Creates one or many bundles
  • Treats every asset as a module
  • Gives you hooks to transform modules
  • Gives you hooks into the bundling process

Webpack is a module bundler, in the lines of RequireJS and Browserify , but it is much better suited for big projects.

The main differences with those other tools are:

It handles both CommonJS and AMD syntaxes (plus ES6 modules through loaders).

It allows you to split the dependency tree into chunks loaded on demand.

It can extract dependencies that are common to multiple entry points into their own chunk.

It can treat any asset as a requireable module, and transform it, through the use of loaders.

It allows you to customize almost every part of the bundling process through plugins.

Docs: webpack.github.io/docs/

Examples: github.com/.../examples

The docs are really dense, but they are not bad. You just need to spend time with them.

The examples are useful once you understand the underlying concepts.

Single Entry

Simplest example: an app with a single entry point.

Via command line:

... or via config:

webpack.config.js

Keeping things in a configuration file is the way to go for non-trivial setups.

If your config file is called webpack.config.js you don't even have to specify the --config parameter to webpack .

The runtime overhead compared to Browserify and RequireJS:

  • Webpack : 243b + 20b per module + 4b per dependency
  • Browserify : 14.7kb + 0b per module + (3b + X) per dependency
  • RequireJS : 415b + 25b per module + (6b + 2X) per dependency

Multiple Entries

Next step: an app with multiple entry points. Think https://twitter.com/ , https://twitter.com/settings/account , etc.

Webpack outputs a bundle-entry1.js containing entry1.js plus greeter.js , and a bundle-entry2.js containing entry2.js plus greeter.js . The number between curly braces (e.g. {1} ) tells you which chunks contain that module.

This is not a good solution for a web application, as a user will probably hit multiple entry points in a session, and would have to download common dependencies multiple times.

The CommonsChunkPlugin plugin identifies dependencies that are shared among the entry points, and puts them into their own chunk. You end up with bundle-entry1.js containing entry1.js , bundle-entry2.js containing entry2.js , and bundle-common.js containing greeter.js .

In this simple example it may seem overkill, but when you are depending on huge libraries, like jQuery, Moment or Angular, it is totally worth it.

Module Resolution

Having to specify paths to dependencies can be a pain, specially when you have to move things around. Webpack allows you to tweak how modules are resolved.

Webpack will try to find your dependency in those directories.

It's pretty common to apply transformations to modules. Think CoffeeScript to JavaScript, or Less to CSS. That's the job of loaders.

greeter.coffee

We are telling Webpack that all files ending with .coffee should go through the coffee loader. We are also telling it to try the .coffee extension when resolving modules.

Much better than inlining, as all your configuration is in one place, so it's much easier to change things.

HTML, CSS, Assets

Loaders can help you with much more than transforming CoffeeScript to JavaScript.

You can use the file and url loaders to process assets like images. The url loader is just like file , but allows you to inline dependencies under certain conditions.

The html and css loaders are able to identify dependencies in HTML files (e.g. <img src="foo.gif" /> ) and CSS files (e.g. background-image: url('bar.png') ) respectively.

CSS files need to go through yet another loader, style , to be injected into the head of the HTML document.

If you want to extract CSS content into its own file, you can use the ExtractTextPlugin plugin.

Busting Caches

You even have cache-busting hashes built in.

Pre/Post Loaders

You can also specify pre- and post-loaders. Here we'd be running our JavaScript files through two linting libraries, and through a code instrumenting library.

The order in which loaders are applied is the following:

  • The file is read from the filesystem
  • module.preLoaders are applied
  • module.loaders are applied
  • Inlined loaders are applied
  • module.postLoaders are applied

Plugins allow us to hook into different phases of the bundling process. For example, the I18nPlugin plugin replaces occurrences of the \_\_ function with strings from a dictionary (e.g. __("Hello World") is replaced with "Hello World" or "Hola Mundo" , depending on the current locale).

The DefinePlugin plugin allows us to define free variables, like DEBUG and LANGUAGE . The value of those variables is specified in the config file.

webpack.config.js (continued)

We are generating a bundle for each of the languages in the langs object, storing the language code in the LANGUAGE variable.

We are also defining the value of DEBUG through an environment variable.

When we bundle the app with the DEBUG environment variable set to true , we see the debugging statement.

The DEBUG variable got replaced with true .

If we don't specify the DEBUG environment variable, the condition in the if statement is always false. That's why the whole block gets dropped by UglifyJS when we enable optimizations with the -p flag, and we don't see the debugging statement in the output.

A context is created if your request contains expressions, so the exact module is not known at compile time.

You can also create contexts by hand through the require.context function.

Here we are using that functionality to require a random module from the lib folder.

Webpack includes all modules matching our regular expression in the bundle.

At runtime it does the right thing.

Why would anyone want to do this?

  • Require resource based on locale
  • Require all components to build a gallery

Context Replacement

Some third-party libraries, like Moment, also create contexts when processed through Webpack.

Why is the bundle so big?

Webpack is creating a context and including all locales in the bundle.

We can use the ContextReplacementPlugin plugin to manipulate the context. Here, we are only including the English locale.

The resulting bundle is much smaller, because we've left all other locales out.

Load On Demand

If your app is big, you may want to load some things on demand, rather than upfront. You can do so through require.ensure if you are using CommonJS syntax, or require if you are using AMD syntax.

require.ensure does not evaluate the module. require does.

Calling require.ensure here will create a split point that will put b into its own chunk. This chunk will be loaded on demand when the bar method is called.

You can see that b has been split into its own chunk.

You can see this in action by launching webpack-dev-server .

The webpack-dev-server is a little express server, which uses the webpack-dev-middleware to serve a bundle.

When you make a change, webpack-dev-middleware will recompile only the modules that are affected by it.

If you run webpack-dev-server with hot module replacement enabled, you can inject your changes into the runtime as you make them.

Circular Dependencies

Circular dependencies are handled the same way as in Node.js.

When you create a loop in the dependency graph, the requiring module will get a reference to an incomplete module.exports from the required module. If you are adding properties by doing module.exports.foo = ... , the incomplete object will receive them eventually. But if you declare your exports by doing module.exports = ... , you will be creating a new object which the requiring module has no way to access.

At that point, a is an empty object.

One possible solution is to defer the calls to require .

We could also move our module.exports statement above the require calls.

Dependency Visualization

http://webpack.github.io/analyse/

We can output stats from the bundling process, and query the information.

The analyse tool draws a pretty graph of all the modules, and gives us all sorts of useful details.

Dependency graph

  • Source maps
  • Ignore dependencies
  • Dedupe dependencies
  • Loaders for every format

https://unindented.github.io/webpack-presentation/

Contributors 104

  • JavaScript 68.0%
  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Error: Cannot find module 'webpack'

I'm just getting started with webpack and am having difficulty getting the multiple-entry-points sample to build. The webpack.config.js file in the example includes the line

which fails for me with the error

Searching around, I found other examples of using the CommonsChunkPlugin with the expression

which fails with the error

Some more searching found a number of examples including

and my build now fails with

I'm at a loss as to how to proceed.

Ed.'s user avatar

  • 4 Did you run npm install webpack before? –  Johannes Ewald Commented Apr 8, 2015 at 7:49
  • Yes. Webpack is installed and working on other examples. It was in trying to add the plugin for the multiple-entry-points example that I ran into trouble. –  Ed. Commented Apr 8, 2015 at 11:21
  • 1 Error: Cannot find module 'webpack' is a node error. So this has nothing to do with webpack itself (afaict). It seems like node is looking in the wrong folders... –  Johannes Ewald Commented Apr 8, 2015 at 13:13
  • 9 I see, npm install -g webpack didn't work for me either. But it does with npm install webpack - make sure you are in the app root folder when you call npm install webpack then check if the module exists in node_modules folder. It also seems that webpack needs fsevents (optional) module on linux systems - I'm using Windows so I'm not sure - try installing fsevents also –  AndreiDMS Commented Apr 9, 2015 at 13:40
  • 3 As I said above, global installation didn't work for me either, so try installing webpack in the local app folder, using npm install webpack , without -g –  AndreiDMS Commented Apr 9, 2015 at 14:12

25 Answers 25

Link globally installed package to your project:

Checkout the official documentation of yarn link .

johannchopin's user avatar

  • 16 This is the simplest answer out there. –  Thomas Wagenaar Commented Mar 12, 2017 at 11:11
  • 1 On which file does this setting affects ? I didn't see any changes to the json files. Can you please elaborate ? –  Royi Namir Commented Mar 20, 2017 at 11:01
  • there doesnt seem anyway to unlink . webpack-dev-server crashed after this. –  Plankton Commented Jun 7, 2017 at 7:13
  • After a month not being able to make it work I was very close to give up and keep working with Angularjs. This finally worked! Thank you. –  NestorArturo Commented May 27, 2018 at 15:57
  • 1 i'm installing webpack, but i run webpack without any parameter show , this type of message : which one do you like to install (webpack-cli/ web-command) –  Ng Sharma Commented Aug 18, 2018 at 4:52

I solved the same problem by reinstalling, execute these commands

rm is always a dangerous command, especially with -f , please notice that before executing it!!!!!

psygo's user avatar

  • 10 package-lock.json is the culprit –  Sérgio S. Filho Commented Oct 8, 2019 at 19:49
  • @SérgioS.Filho how so? –  DJ_Stuffy_K Commented Dec 21, 2020 at 19:04
  • I had to change the Node version as well because of any issue, but removing the package-lock.json was essential to resolve the issue. Removing node_modules and starting clean again –  Flavio Lima Commented Mar 18, 2021 at 12:00
  • this is the way if you npm install with the wrong node version, even if you switch to another node version it won't work until you remove package-lock.json and npm install again –  Linh Nguyen Commented Nov 17, 2022 at 3:23
  • This helped me because linking to webpack (as otherwise suggested) was not an option on the build server. –  KrimblKrum Commented Nov 29, 2022 at 21:37

While working on windows, I've installed webpack locally and it fixed my problem

So, on your command prompt, go to the directory of which you want to run webpack, install webpack locally (without the -g) and enjoy...

Ran's user avatar

  • 14 but you didnt mention how to install it "locally" –  jpganz18 Commented Sep 27, 2018 at 2:06
  • 2 locally is npm install webpack , without using -g as mentioned. This worked in my case. –  Honza P. Commented Jun 12, 2020 at 9:11

Run below commands in Terminal:

npm install --save-dev webpack

npm install --save-dev webpack-dev-server

Community's user avatar

Seems to be a common Windows problem. This fixed it for me:

Nodejs cannot find installed module on Windows?

"Add an environment variable called NODE_PATH and set it to %USERPROFILE%\Application Data\npm\node_modules (Windows XP), %AppData%\npm\node_modules (Windows 7), or wherever npm ends up installing the modules on your Windows flavor. To be done with it once and for all, add this as a System variable in the Advanced tab of the System Properties dialog (run control.exe sysdm.cpl,System,3)."

Note that you can't actually use another environment variable within the value of NODE_PATH . That is, don't just copy and paste that string above, but set it to an actual resolved path like C:\Users\MYNAME\AppData\Roaming\npm\node_modules

Jamie Treworgy's user avatar

  • 1 not work for me on Windows 10. There is no node_modules folder in C:\Users\MYNAME\AppData\Roaming\npm`. I tried to set NODE_PATH` value C:\Program Files (x86)\nodejs\node_modules but it didn't help –  VB_ Commented Sep 7, 2015 at 19:52
  • 3 Works just fine for me on Windows 10: setx NODE_PATH %AppData%\npm\node_modules . You might need to restart your cmd before the NODE_PATH variable is availble or also run set NODE_PATH=%AppData%\npm\node_modules . –  Nux Commented Oct 15, 2016 at 22:14
  • Yes. Works fine on Windows 10. –  Siva Commented Aug 5, 2020 at 15:08

I was having this issue on OS X and it seemed to be caused by a version mismatch between my globally installed webpack and my locally installed webpack-dev-server . Updating both to the latest version got rid of the issue.

Cody Sand's user avatar

  • that worked for me as well, so I figure it's well worth considering under various scenarios if you have this problem. –  JL Peyret Commented Mar 9, 2020 at 20:05

I was facing same problem, and I solved through this command, check this out will solve your issue.

Aman Jha's user avatar

  • This is just a repeat of an existing answer. rm -R and rm -r are synonymous. –  Akaisteph7 Commented Jan 26 at 17:22
  • @Akaisteph7 Yes, maybe but this worked for me, so I thought to put up this answer to help. –  Aman Jha Commented Jan 28 at 4:46
  • 1 If you think an existing answer is right, what you should do is upvote it, not post it again. –  Akaisteph7 Commented Jan 29 at 15:34

Installing both webpack and CLI globally worked for me.

David  Gogua's user avatar

If you have installed a node package and are still getting message that the package is undefined, you might have an issue with the PATH linking to the binary. Just to clarify a binary and executable essentially do the same thing, which is to execute a package or application. ei webpack... executes the node package webpack.

In both Windows and Linux there is a global binary folder. In Windows I believe it's something like C://Windows/System32 and in Linux it's usr/bin. When you open the terminal/command prompt, the profile of it links the PATH variable to the global bin folder so you are able to execute packages/applications from it.

My best guess is that installing webpack globally may not have successfully put the executable file in the global binary folder. Without the executable there, you will get an error message. It could be another issue, but it is safe to say the that if you are here reading this, running webpack globally is not working for you.

My resolution to this problem is to do away with running webpack globally and link the PATH to the node_module binary folder, which is /node_modules/.bin.

WINDOWS: add node_modules/.bin to your PATH. Here is a tutorial on how to change the PATH variable in windows.

LINUX: Go to your project root and execute this...

In Linux you will have to execute this command every time you open your terminal. This link here shows you how to make a change to your PATH variable permanent.

neves's user avatar

  • 1 A good answer will always include an explanation why this would solve the issue, so that the OP and any future readers can learn from it. –  Tyler2P Commented Oct 16, 2022 at 20:35
  • Answers containing nothing but code are liable to be downvoted or deleted (even if the code provides a valid fix). Include some text in your answer to clarify/explain why it will work. For example, why have you provided two alternatives for npm install ? How does the reader know which alternative is appropriate? While this may be obvious to you, it may not be obvious to others. Also: [1] Did you mean to write package-json.lock rather than package.json-lock ? [2] How is your answer different/better than that already posted by Aman Jha ? –  skomisa Commented Oct 18, 2022 at 18:24

On windows, I have observed that this issue shows up if you do not have administrative rights (i.e., you are not a local administrator) on the machine.

As someone else suggested, the solution seems to be to install locally by not using the -g hint.

dev.bv's user avatar

for me, it is a wrong error feedback.

there was config error in webpack.config.js ,

delete the file and start over solved my issue

Seeliang's user avatar

Open npm command prompt and -- cd solution folder and then just run npm link webpack in NPM cmd prommt and re build..

SAIRAM's user avatar

You can try this.

It works for me.

aermin's user avatar

In my case helped me changing the parent folder name and remove some & from this name, you can also try changing the name or folder where you keep your code.

Panda's user avatar

I resolved this issue simply running this command:

Sabin Bogati's user avatar

Nothing suggested above worked for me (including the NODE_PATH variable). I created a sym link of "node_modules" from my local folder to the global AppData(eg below) and it worked like charm.

Mazhar's user avatar

Just found out that using Atom IDE terminal did not install dependencies locally (probably a bug or just me). Installing git bash externally and running npm commands again worked for me

Oladayo agbolade's user avatar

I had a ton of issues getting a very simple .NET Core 2.0 application to build in VS 2017. This is the error from AppVeyor, however it was essentially the same thing locally (some paths omitted for security) :

Performing first-run Webpack build... module.js:327 throw err; EXEC : error : Cannot find module '......../node_modules/webpack/bin/webpack.js' at Function.Module._resolveFilename (module.js:325:15) at Function.Module._load (module.js:276:25) at Function.Module.runMain (module.js:441:10) at startup (node.js:140:18) at node.js:1043:3 csproj(25,5): error MSB3073: The command "node node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js" exited with code 1. Build FAILED.

I stumbled upon this question and answer , and I noticed my local instance also had the same warning sign over the {Project Root} -> Dependencies -> npm folder. Right clicking and hitting "Restore packages" got everything loaded up properly, and I was able to build successfully.

X3074861X's user avatar

npm link webpack worked for me.

My webpack configuration: "webpack": "^4.41.2", "webpack-dev-server": "^3.9.0", "webpack-cli": "^3.3.10"

jayesh's user avatar

For Visual Studio users: Right click on the npm folder and "Restore Packages".

acousticplanet's user avatar

While the suggested solution ( npm link webpack ) worked locally, on my CI (GitHub actions) I had the same problem, and to resolve it I used:

Francesco Borzi's user avatar

Laravel Users

If none of the above options work for you, then you probably need to install Laravel-mix correctly. Here is how:

npm install laravel-mix --save-dev

Now create a webpack.mix.js file using this command:

touch webpack.mix.js

Add this code into your webpack.mix.js file:

You probably will also need to create a tailwind.config.js file using the command touch tailwind.config.js and then add this code ainto it:

Finally run npm run dev

Hefaz's user avatar

So there are quite few possible issues, in my case on windows:

I moved my project to a folder with an & in the name, which is fine for windows but it break npm. My solution was to remove the & from the name.

test&mocking -> test_and_mocking

Patrick Aleman's user avatar

What solved it for me was that the path to webpack.config was wrong in build.js

Paulo Guilherme's user avatar

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged node.js webpack or ask your own question .

  • Featured on Meta
  • We spent a sprint addressing your requests — here’s how it went
  • Upcoming initiatives on Stack Overflow and across the Stack Exchange network...
  • The [lib] tag is being burninated
  • What makes a homepage useful for logged-in users

Hot Network Questions

  • 为什么「五二〇运动」没有别称「五廿运动」?
  • Can computer components be damaged if they stay off for a long time?
  • Finding the Zeckendorf Representation of a Positive Integer (BIO 2023 Q1)
  • Why does King Aegon speak to his dragon in the Common Tongue (English)?
  • What real-world cultures inspired the various human name examples?
  • Is it possible to understand in simple terms what a Symplectic Structure is?
  • CiviRule based on "Activity Date reached" - how to stop it triggering an email every 24 hours after that date
  • If Biden steps back or is replaced, until when must he do it?
  • Why \IfPackageAtLeastTF{⟨package⟩}{⟨date⟩}{\PassOptionsToPackage{⟨option⟩}{⟨package⟩}}{} doesn't pass ⟨option⟩ to ⟨package⟩?
  • Does there exist a Dehn filling of an irreducible 3-manifold with toroidal boundaries which is still irreducible?
  • When, if ever, is bribery legal?
  • Chip identification, SOP-4, "HPTD"
  • pkh() nested in tr() is allowed?
  • Why the number of bits or bytes is different for a folder that has been copied between two external drives?
  • Can compositions "da + preposition" be used as a relative pronoun?
  • Move the equation to left side inside split environment
  • Real-life problems involving solving triangles
  • Difference Artifacts of Quantization and Spur
  • How can I watch a timelapse movie on the Nikon D7100?
  • Reducing decimal places of coordinates in vector data using QGIS
  • Definability of acyclic graphs
  • Is a "single" cpu safer than multiple cores?
  • Why is QR considered a problem for disc rotor alignment and not rim brake alignment?
  • What enforcement exists for medical informed consent?

webpack presentation

COMMENTS

  1. Webpack Fundamentals

    Program Manager. Microsoft Web Platform, Edge Dev Tools Maintainer & Advocate. Webpack Core Team. Angular / angular-cli Evangelist. Open Source Sustainability

  2. Webpack Fundamentals

    8 Expectations Why webpack? - History of Web Performance & JavaScript Getting Started - Setup, Installation, Scripts, and CLI The Core Concepts Starting out Right The Essentials Putting it to practice Triage and Debug

  3. A Beginner's Guide to Webpack

    To install it, run the following: npm install webpack-dev-server --save-dev. We need to update our dev script, in package.json, to use the server: "dev": "webpack serve --mode development". Now ...

  4. An intro to Webpack: what it is and how to use it

    Next up we need to add webpack, so we can bundle our app together. Not only bundle, but we will also require hot reloading which is possible using the webpack dev server. $ npm i webpack webpack-dev-server webpack-cli --save--dev. The --save--dev is to specify that these modules are just dev dependencies. Now since we are working with React, we ...

  5. Getting Started

    Getting Started. Webpack is used to compile JavaScript modules. Once installed, you can interact with webpack either from its CLI or API. If you're still new to webpack, please read through the core concepts and this comparison to learn why you might use it over the other tools that are out in the community.

  6. webpack

    Every little bit helps, and we appreciate even the smallest contributions. This list shows 100 randomly chosen backers: webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

  7. How to use Webpack with React: an in-depth tutorial

    Updated to Babel 7. In this tutorial we will see the basics of Webpack for React to get you started, including React Router, Hot Module Replacement (HMR), Code Splitting by Route and Vendor, production configuration and more. Before we start, here's the full list of features we are going to set up together in this tutorial: React 16.

  8. Guides

    Guides. This section contains guides for understanding and mastering the wide variety of tools and features that webpack offers. The first is a guide that takes you through getting started. The guides get more advanced as you go on. Most serve as a starting point, and once completed you should feel more comfortable diving into the actual ...

  9. Introduction to Webpack 5.0 Presentation

    Introduction to Webpack 5.0 Presentation. Webpack is a free and open-source module bundler for JavaScript. It is made primarily for JavaScript, but it can transform front-end assets such as HTML, CSS, and images if the corresponding loaders are included. [9] Webpack takes modules with dependencies and generates static assets representing those ...

  10. Understanding the Modern Web Stack: Webpack

    webpack - This is the main engine of webpack, it understands everything related about how the code and files relate to one another, and how to bundle them into a single package. webpack-cli - This is the actual program we are going to run to trigger the core engine. It allows us to run webpack on our command line and generate a bundle.

  11. PDF webpack: One Build Step To Rule Them All

    HTTP2: Webpack's AgressiveSplittingPlugin (in latest!!) HTTP2: Dependency Tree driven Push Manifest Usability: Complete overhaul of the main interface Optimization: Module Inlining and Concatenation (Rollup) DevTools: Working with Multiple Browser Teams to Bring DevTools custom instrumentation and UI's for webpack.

  12. Enabling Micro-front end Architecture with Webpack 5 Module ...

    Webpack 5's Module Federation is a revolutionary feature that brings a new level of flexibility to the world of web development. It allows for better code sharing, independent deployments, and a ...

  13. A Beginner's Guide to Micro Frontends with Webpack Module ...

    Therefore, Webpack will then head over to host/webpack.config.js to determine if SubA is a bundle that can be requested remotely. Sure enough, Webpack will be able to see that SubA is actually ...

  14. Production

    webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

  15. Webpack: The One Build Step to Rule Them All

    Sean Larking talks about the four concepts everyone should know when using Webpack so they can take and make it their own. BT InfoQ Software Architects' Newsletter

  16. Building micro-frontends with webpack's Module Federation

    Here, we will demonstrate how we can use the module federation to create micro-frontends in Vue. To test this out, we will be spinning up two different apps, so we can create a micro-frontend in one of them and share it with the other. First, we create a folder to host the two Vue applications: mkdir vue-mf.

  17. Webpack for beginners

    In this case, there are implicit dependencies between the <script> tags.. app.js depends on jquery being included . It is implicit because index.js never declared a need for Jquery; it just assumes that a global variable $ exists.. Now run the the app:

  18. Module Federation · GitHub

    Practical Module Federation - The official book on Webpack Module Federation by Jack Herrington & Zack Jackson "Practical Module Federation" is the first, and only, book on Webpack 5's innovative new live code sharing mechanism. It walks you through everything you need to do to start with Module Federation. It covers the internal implementation of Module Federation, and how Module Federation ...

  19. GitHub

    Webpack presentation This repository contains sample code used for the webpack presentation , a short introduction to webpack, describing its benefits over a task runner and basic usages on how to use it.

  20. How to use Webpack with React: an in-depth tutorial

    Webpack 4 introduced some defaults, so if you don't include entry in your configuration, then Webpack will assume your entry point is located under the ./src directory, making entry optional as ...

  21. GitHub

    Note: Webpack outputs a bundle-entry1.js containing entry1.js plus greeter.js, and a bundle-entry2.js containing entry2.js plus greeter.js.The number between curly braces (e.g. {1}) tells you which chunks contain that module. This is not a good solution for a web application, as a user will probably hit multiple entry points in a session, and would have to download common dependencies multiple ...

  22. node.js

    I see, npm install -g webpack didn't work for me either. But it does with npm install webpack - make sure you are in the app root folder when you call npm install webpack then check if the module exists in node_modules folder. It also seems that webpack needs fsevents (optional) module on linux systems - I'm using Windows so I'm not sure - try installing fsevents also