Webpack Tutorial: From Zero Configuration To Production (webpack 5)

All you need to know about webpack, the modern module bundler. In this webpack tutorial you will go from zero configuration to bundling your JavaScript apps, step by step.

Webpack Tutorial: From Zero Configuration To Production

webpack 4 came out in 2018 with a lot of improvements over the previous versions: “almost zero” configuration, better performances, and sane defaults for production.

Now it’s that time of the year again: webpack 5 is coming soon.

In this tutorial you’ll learn how to use webpack by building a JavaScript development environment step by step. Enjoy!

Webpack tutorial: getting started

To start off create a new JavaScript project, move into the folder and initialize package.json:

mkdir webpack-tutorial && cd $_

npm init -y

Next up install webpack and webpack-cli:

mkdir webpack-tutorial && cd $_

npm i webpack@next webpack-cli

And now configure a new script named “build” for running webpack:

  "name": "webpack-tutorial",
  "scripts": {
    "build": "webpack"
  "devDependencies": {
    "webpack": "^5.0.0-beta.0",
    "webpack-cli": "^3.3.9"

Now in theory you’re ready to run webpack, but first let’s talk about configuration.

Webpack tutorial: almost zero configuration

webpack is a powerful tool, but one of its pain points was the configuration file. webpack 4 simplified things a bit. Same is true for webpack 5. Give it a shot with:

npm run build

and you’ll see an error:

Module not found: Error: Can't resolve './src' in '~/webpack-tutorial'

There’s no need for a configuration file, but you should provide at least an entry point, that is, a JavaScript file with some code. Create a new file in ./src/index.js:

mkdir src
touch src/index.js

Any piece of JavaScript will do:

const myArrowFunc = (a, b) => {
  if (a === void 0) return b;
  return a;

And now run again npm run build. You should see something along these lines:

Version: webpack 5.0.0-beta.0
Time: 191ms
Built at: 2019-010-15 14:23:58
  Asset     Size
main.js  0 bytes  [emitted]  [name: main]
Entrypoint main = main.js
./src/index.js 77 bytes [built]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.

If everything went well you should see a new file in dist/main.js. That’s the result of your first webpack bundle. Way to go!

Now, it’s true that for bundling a super simple app there is no need for a configuration file. But for larger project there will be always the demand for custom configurations.

In the next section we’ll see another nice feature of webpack: production and development mode.

Webpack tutorial: production and development mode

In the past there was the need for two configuration files in webpack: one for development and one for production, the latter used for minification and optimization.

Starting with webpack 4 onward, the process is easier. If you noticed, in the last section we got a warning:

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.

webpack wants the “mode” flag after the script to differentiate between development and production. By doing so you’ll have sane defaults out of the box. Open up package.json, add another script named dev, and specify the mode for both:

  "name": "webpack-tutorial",
  "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
  "devDependencies": {
    "webpack": "^5.0.0-beta.0",
    "webpack-cli": "^3.3.9"

Now try to run:

npm run dev

and take a look at ./dist/main.js. You should see your JavaScript code with a bunch of webpack specific things. If instead you run the build script:

npm run build

you should see an empty (for now) file. Way to go!

Let’s continue our exploration …

Webpack tutorial: transpiling modern JavaScript with Babel

Today JavaScript is written in ECMAScript 2015 and beyond. Modern version of JavaScript are a dream for developers, but the reality is a bit harsh because older browsers do not understand ECMAScript > 2015.

So with time tools like Babel rose as translators from modern JavaScript to compatible versions (ECMAScript 2009). Babel works seamlessly with webpack and makes possible to write ECMAScript > 2015 that later is transpiled to ECMAScript 2009 during the build process.

For doing so we need to configure our first webpack loader, that is, a little tool that knows how to deal with certain file extensions. We will also configure a Babel plugin.

First install the dependencies:

npm i @babel/core babel-loader @babel/preset-env --save-dev

Next up configure Babel by creating a new file named .babelrc inside the project folder:

    "presets": [

At this point we have two options for configuring babel-loader, the webpack loader for transpiling JavaScript:

  • with a configuration file for webpack
  • with –module-bind in your npm scripts

For the scope of this post I’ll go with option 1. As you can see while webpack 4 marketed itself as a zero configuration tool, even for slightly simple task there is still configuration to do.

So create a new file named webpack.config.js and configure the loader:

module.exports = {
  module: {
    rules: [
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"

Now run:

npm run dev

and you should see your code transpiled to ECMAScript 2009 in dist/main.js:

/******/ (() => { // webpackBootstrap
  !*** ./src/index.js ***!
/*! exports [maybe provided (runtime-defined)] [no usage info] */
/*! runtime requirements:  */
eval("var myArrowFunc = function myArrowFunc(a, b) {\n  if (a === void 0) return b;\n  return a;\n};\n\n//# sourceURL=webpack:///./src/index.js?");
/******/ })()

By now you should have got the gist of webpack: it builds and transforms your JavaScript code through the help of one or more loaders.

Work in progress! I’m updating the tutorial to webpack 5! Stay tuned.

Wrapping up



After finishing this tutorial go read How to set up React, webpack, and Babel 7 from scratch.

143 Replies to “Webpack Tutorial: From Zero Configuration To Production (webpack 5)”

  1. Could you please explain how to configure loaders in Webpack 4? (react)
    This is webpack.config.js from webpack 3 (but is no longer allowed):
    module: {
    loaders: [
    test: /\.jsx?/,
    include: APP_DIR,
    loader: “babel-loader”

    1. You should use “rules” instead of “loaders” after the “module” property:

      module: {
      rules: [
      test: /\.jsx?/,
      include: APP_DIR,
      use: “babel-loader”

  2. @rune add this to the script: `–module-bind js=babel-loader` as in:
    `”dev”: “webpack –mode development –module-bind js=babel-loader”`

  3. Thanks for the detailed tutorial!
    I have a problem here: Is it possible to create a backend app with webpack 4?
    I was using webpack 3 to create a node.js backend app that runs on a server based on a tutorial I found. But I’m having trouble with webpack 4. There are some errors I don’t how to solve.
    “ReferenceError: window is not defined”
    I’m guessing webpack 4 assumes the app to be run on a browser not a server.

    The tutorial:

    1. I am very sorry but it’s not working…
      Still the same info “The CLI moved into a separate package: webpack-cli Would you like to install webpack-cli? (That will run npm install -D webpack-cli) (yes/NO)pawel@ProBook-4530s:~/JS/reactTestF$”?

  4. Thanks alot for this article. You were very clear. However you never told us how to configure the npm script for launching the app in development mode. or production mode. Tried out this:
    ` “start”: “webpack-dev-server –progress –colors –config ./webpack.config.js”,`
    It built 11 modules with this warning:
    `WARNING in configuration
    The ‘mode’ option has not been set. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for this environment.`
    But my none of my servers was launched. How do I go about this?

  5. Hi, is there some way how to define entry point?
    My angular app is in Modules folder, so no src.
    It’s still searching for ./src folder in Modules, but I dont have it.

  6. Lovely explanation of the new settings. Couple this with the migration steps given on the official website and you can move to the new version with ease.

  7. Thanks for your post. I started learning Node / webpack the last 2 days , and all the tutorials are for webpack<4 and for some reason nothing would compile all because I had used "webpack": "*" … God bless you 🙂

  8. Great post!
    I have a warning whwn I run webpack:
    DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
    DeprecationWarning: Tapable.apply is deprecated. Call apply on the plugin directly instead

    What is the problem?


  9. Fantastic tutorial on webpack4. Clear, thorough, and functional. With a lot of great explanation. I’ll be looking forward to your next tut. Thank you.

  10. webpack 4: the HTML webpack plugin

    Anyone get this to actually load?
    It complained about not having `ReactDom`, which makes sense since we installed it as a devDependency and excluded it in the config.

  11. As someone who has always considered Webpack to complex for me to understand, this was an immensely helpful! It completely demystified it all for me. Thanks for taking the time to write this post, Valentino.

  12. valentino g, this is not the first time i ahve visited your website, nor will it be the last.
    extravagant thanks are in order.

    thank you, valentino g.

  13. Hello Valentino,

    There is a typo in the section “webpack 4: production and development mode”. The sentence fragment below:

    “tipical project may have”

    should be:

    “typical project may have”

    Thank you so much for the article and updating it!

  14. Can u please update your article to extend react integration with webpack 4 for bootstrap4, saas and font-awesome

  15. hiya.. is there a way to integrate sass with this example too ? so compiling multiple sass files down to an outputted .css file ? that’d be ace!

  16. This guide worked great for me, but I’m still struggling to get my environmental variables defined as I have a rails API backend and other external API’s to fetch from. I tried the DefinePlugin, then the EnvironmentPlugin, and then babel-plugin-transform-inline-environment-variables. How can I get my environmental variables defined with this configuration??

  17. Hi. Super tutorial!! Very simple and clean. Really what I needed. Thank you!
    I tried the plugin “extract-text-webpack-plugin”
    “extract-text-webpack-plugin”: “^4.0.0-beta.0”,

    it works now with webpack 4.
    Here my config:
    test: /\.css$/,
    use: [ExtractTextPlugin.loader, “css-loader”]

    plugins: …
    new ExtractTextPlugin({
    filename: ‘style.css’,
    disable: false,
    allChunks: true

  18. Man, I have been dabbling around google quite a lot, to prepare webpack for small projects, until today i found this excellent piece of article. Thank you so much.

  19. Awesome tutorial Valentino.!!
    Each and everything is more informative. loved it .
    Thanks for your valuable effort for making us into webpack 4 🙂

  20. Does anybody know where can be found the features that comes with –mode development and –mode production?. Just to know what is behind the scenes.

    For example, I guess HRM comes built in with –mode development command.

  21. Does webpack 4 support aliases?

    resolve: {
    extensions: [‘.js’, ‘.jsx’],
    alias: {
    props: `${defaultSettings.srcPath}/props/`,
    logic: `${defaultSettings.srcPath}/logic/`,
    actions: `${defaultSettings.srcPath}/actions/`,
    selectors: `${defaultSettings.srcPath}/selectors/`,
    components: `${defaultSettings.srcPath}/components/`,
    helpers: `${defaultSettings.srcPath}/helpers/`,
    sources: `${defaultSettings.srcPath}/sources/`,
    stores: `${defaultSettings.srcPath}/stores/`,
    styles: `${defaultSettings.srcPath}/styles/`,
    config: `${defaultSettings.srcPath}/config/${process.env.REACT_WEBPACK_ENV}`,
    ‘react/lib/ReactMount’: ‘react-dom/lib/ReactMount’

  22. Thanks for the blog!
    This is the most recent webpack and easy to follow as well!
    The main question is how to compress multiple js and CSS file into one file?

  23. I would like to create a react application with multi brands using the different configs, assets and styles. How can i make it using webpack 4?

  24. Thanks so much for this its been a big help.

    what is main.css in this instance, the file created by the MiniCssPlugin?

    Finally import the CSS in the entry point:

    // PATH OF THIS FILE: ./src/index.js
    import style from “./main.css”;

    1. Here’s the relevant snippet from a project of mine:

      output: {
      chunkFilename: "[name].[chunkhash:4].js",
      filename: "[name].[chunkhash:4].js"
      optimization: {
      splitChunks: {
      chunks: "initial"

  25. Hi Valentino, Very helpful tutorial, can you touch upon the topic of Webpack 4 and Dynamic Imports of JavaScript files?

    Much appreciated!

  26. Hi, loved the tutorial.

    In order to get the webpack-dev-server working with the /dist no config default you need to att this to your webpack.config.js:

    output: {
    publicPath: “/dist”

  27. Your MiniCssExtractPlugin looks like this:

    plugins: [
    new MiniCssExtractPlugin({
    filename: ‘[name].css’,
    chunkFilename: ‘[id].css’,

    But I saw other example with this setting:

    plugins: [
    new MiniCssExtractPlugin({
    filename: ‘[name].[contentHash:8].css’,

    Could you please explain which one is the preferred method and why?

  28. Thank you Valentino!

    After setting up the HTML webpack plugin with the webpack config and the template html file in the src file, I can successfully run npm run build and get an index.html file built in my dist folder. However, none of the app.js content is in the output index.html. Just the html from the template. I can see the content of the app.js in the main.js file, but not in the html.

    Any theories as to my goof?

    Note I’m developing in windows, a big change for me at my new job. I’m used to OS. I tried using my webpack config from an app I built in OS and got the exact same problem, which makes me think it’s a windows thing.

  29. Thank you for the tutorial.

    How do we copy static assets in webpack 4? Like manifest.json, fav icon, images etc?

    Previous we used copy-webpack-plugin.


  30. Great article, thank you. Concise and working(!).

    I recommend to update it to use Babel 7, since it’s already released. It’s only a couple of lines of code + new dependency names. This will prolong the relevance of your post.

  31. Awesome article, thank you!

    One question though: when I am running my dev-server how do I get css changes from my “./src” folder to update the file in the “./dist” folder?

    At present I’m having to run “npm run build” and then restart the dev server.

    Thanks again 🙂

  32. Thank you for this concise, step-by-step guide to a basic config. It’s great to know what the different pieces are and why they are necessary. Also, that things like the css module have changed so recently.

  33. Hello! I’m doing first steps in learning webpack . I have a trouble: sh: 1: webpack: not found
    npm ERR! file sh
    npm ERR! code ELIFECYCLE
    npm ERR! errno ENOENT
    npm ERR! syscall spawn
    npm ERR! webpack-4-quickstart@1.0.0 build: `webpack`
    npm ERR! spawn ENOENT
    npm ERR!
    npm ERR! Failed at the webpack-4-quickstart@1.0.0 build script.
    npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

    my package.json

    “name”: “webpack-4-quickstart”,
    “version”: “1.0.0”,
    “description”: “”,
    “main”: “index.js”,
    “scripts”: {
    “build”: “webpack”
    “keywords”: [],
    “author”: “”,
    “license”: “ISC”,
    “devDependencies”: {
    “webpack-cli”: “^3.1.2”

  34. Great post Valentino.

    Some time has passed since you posted this, and I understand some bits may eventually get outdated. However, on trying to recreate the steps you have so efficiently explained, I was stuck at the transpiling JSX. Hence, building upon ConnerAiken’s comment, I’d like to point that JSX isn’t parsed just by implementing the @babel/preset-react.



  35. You have an error with the css rule configuration, it should be:

    test: /\.css$/,
    use: [
    loader: MiniCssExtractPlugin.loader

    Your syntax is not compatible with the latest webpack.

    1. Yes, I can confirm. I did not understand why I did not got any main.css file in the dist folder when I did a build. If I renamed the main.css to index.css I got it! It did not matter whatever I entered in the ./src/index.js.

      Thumbs up, now no problem specifying the css filename/s in ./src/index.js or even multiple imports… now just need to figure out why it always land as ./dist/main.css 😉

  36. Wow…I’m so glad I saw this..was on the brink of giving up on webpack but this truly was an eye opener
    My G. You are a God send
    I’m also looking for NextJS with webpack 4

  37. first of all , thanks for the tutorial valentino

    second.. in the webserver part im getting this error

    ERROR in multi (webpack)-dev-server/client?http://localhost:8080 ./src
    Module not found: Error: Can’t resolve ‘./src’ in /media/………../webpack_test
    @ multi (webpack)-dev-server/client?http://localhost:8080 ./src main[1]
    Child html-webpack-plugin for “index.html”:
    1 asset
    Entrypoint undefined = ./index.html
    [./node_modules/html-webpack-plugin/lib/loader.js!./src/index.html] 175 bytes {0} [built]
    ℹ 「wdm」: Failed to compile.

    the server loads but it wont push new changes in files , i dont get it … i do have a src folder !

  38. This article was a life savior. I was having troubles getting css to load… until this article. OUFFFF!!
    (It’s crazy how webpack configuration is all over the place)
    Thanks a lot,

  39. Nicely explained but it doesn’t work for most people who write JSX, ie for: .jsx files if you just include the test: /\.(js | jsx)$/ then errors

    So, you’ve written JSX in .js files which everyone’s Linters (JSlint etc) throws errors on so not really working for .js files either (unless you don’t write JSX which defeats the whole point)

    If you could please update to work with JSX files that would be awesome!

  40. First, thank you very much for the tutorial. I would like to know how it would be a webpack configuration for a traditional website, I usually use this folder structure:
    /librarys.css(e.g: bootstrap, font awesome, animate.css, normalize.css)
    Is it possible to configure the entry and output points with a similar structure?
    I know that this type of questions in an advanced tutorial like this could be basic, thank you!

  41. Great article. All other articles/blogs for setting up Babel, Webpack and React are really confusing. With one go I am fully able to understand Webpack, Babel and connecting React with it.
    Thanks a lot for this blog.

  42. Thanks a million for this,
    Wasted 3 hours yesterday trying to get an existing project working with Webpack4. Completed your steps in 20mins, and am now bringing code across.

    Extremely clear and concise.

  43. Thanks for this introduction, it helped me a lot to understand the Webpack 4 concepts and simplify my config file hell.

  44. Hello Valentino
    Thank you so much for this great article.
    I was looking for a good tutorial about Webpack which found it here.
    In addition, as a non-native English speaker, your English is so clear and understandable.
    I hope you write an article about config Sass in Webpack if you could and have free time to help people like me.
    Good luck

  45. Thanks you vwry much Valentino, i followed your steps , you explain very well,just wondering how do you deal with images on css files?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.