120

I have two files which are combined under 600 bytes (.6kb) as below.

So how is it that my app.bundle.js is so large (987kb) and more importantly how does one manage the size of it?

src file index.js

import _ from 'lodash';
import printMe from './print.js';


  function component() {
    var element = document.createElement('div');
    var btn = document.createElement('button');

    // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');

    btn.innerHTML = 'click and check console';
    btn.onclick = printMe;

    element.appendChild(btn);

    return element;
  }

  document.body.appendChild(component());

src file print.js

export default function printMe() {
  consoe.log('Called from print.js');
}

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  entry: {
    app: './src/index.js',
    print:'./src/print.js'
  },
  devtool: 'inline-source-map',
  plugins: [
    new CleanWebpackPlugin(['dist']),
    new HtmlWebpackPlugin({
        title: 'Output Management'
    })
  ],
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

package.json

{
  "name": "my-webpack-4-proj",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "mode": "development",
  "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production",
    "watch": "webpack --watch",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^0.1.19",
    "css-loader": "^0.28.11",
    "csv-loader": "^2.1.1",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^3.0.6",
    "style-loader": "^0.20.3",
    "webpack": "^4.1.1",
    "webpack-cli": "^2.0.12",
    "xml-loader": "^1.2.1"
  },
  "dependencies": {
    "express": "^4.16.3",
    "lowdash": "^1.2.0"
  }
}

Warning message:

WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB). This can impact web performance. Assets: app.bundle.js (964 KiB)

Michael Nelles
  • 5,426
  • 8
  • 41
  • 57
  • 8
    I would leave a comment but I don't have enough reputation yet. I wanted to point out that Riyadh's suggestion of doing ``` performance: { hints: false, maxEntrypointSize: 512000, maxAssetSize: 512000 } ``` Doesn't solve the underlying issue, it just disables the warning that you are seeing. If any novice webpack users out there find that solution and see that it clears the warnings. Just know you aren't actually clearing the warning, just disabling it. – gibsonsp Apr 30 '19 at 17:10
  • @gibsonsp: It's OK to do so. The authors made these thresholds very low to help people notice this feature in the early stage of development. I would like to recommend people either disable it or increase the limit to a much higher number(as indicated by most of the answers below) during the learning and fine-tune it after you really know what's your budget(s) based on the resource you have. – Kindred Apr 12 '22 at 06:37

10 Answers10

100

Simply use below code in webpack.config.js :

 performance: {
    hints: false,
    maxEntrypointSize: 512000,
    maxAssetSize: 512000
}

or follow

You can create multiple config file for (development, production). In dev config file use devtool or others necessary dev configuration and vice versa .

you have to use webpack-merge package and config package.json scripts code like

"scripts": {
 "test": "echo \"Error: no test specified\" && exit 1",
 "start": "webpack --open --config webpack.dev.js",
 "dev": "webpack-dev-server --mode development --open",
 "build": "webpack --config webpack.prod.js"
 },

For example :

create a file webpack.common.js

// webpack.common.js

  use your common configuration like entry, output, module, plugins,

Create webpack.dev.js

// webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
    contentBase: './dist'
 }
});

Create webpack.prod.js

const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
    mode: 'production',
    performance: {
        hints: false,
        maxEntrypointSize: 512000,
        maxAssetSize: 512000
    }
});
Riyadh Ahmed
  • 1,139
  • 1
  • 9
  • 17
  • 3
    I had to do `const { merge } = require('webpack-merge')`. Otherwise it says merge is not a function. – robev Jan 04 '21 at 08:48
67

This happens because webpack is bundling all your code dependencies. And as you are using lodash, so lodash minified version will be added to your source code. Plus you are including the source maps:

devtool: 'inline-source-map',

While this should be fine for debug, there is no reason to include your source maps in a Prod build. So some things that you can do to reduce your bundle size.

  1. Make sure to set properly the mode: flag inside your webpack config. You can put either mode: 'development', or mode: 'production'. This will hint webpack about what kind of build you are doing so it will give you the proper warnings.
  2. Make sure to not include source maps on your prod build
  3. Avoid overusing external dependencies that you don't need and make.

Sometimes even these things will not bring your bundle size to below 244kb, what you can do in these cases is to split your bundle and start to use logical chunks. First of all, you can easily separate your js from your styesheets by using the mini css extract plugin.

Another technique that you can use are dynamic imports.

Dynamic Imports: Split code via inline function calls within modules

This will allow you to break your code logically into modules tied to the screens so only the required libraries will be loaded. For more info about dynamic imports, you can check the official documentation. https://webpack.js.org/guides/code-splitting/

Community
  • 1
  • 1
  • 1
    Question since I am new to webpack. My understanding was it was intelligent enough to not bundle non-needed packages – Michael Nelles Mar 18 '18 at 14:19
  • Not necessarily, you need to tell it that you want it to split the code properly. Check the code splitting link. Anyway I believe that in your case just removing the inline source maps shall resolve the problem – Victor Ribeiro da Silva Eloy Mar 18 '18 at 14:22
  • Hi, I've implemented this, but it didn't make my error go away :( could you have a look here? https://stackoverflow.com/questions/52723381/webpack-size-exceeds-the-recommended-limit-244-kib – Leon Gaban Oct 09 '18 at 14:25
  • Webpack *is* smart enough to not bundle not needed packages. What it does is follow the `require` (or `import`) statements in your code and make sure that whatever you `require` is included in your bundle. Since you `import _ from 'lodash'` it includes lodash. One thing you can do is not import all of lodash, but only the bits you actually use. lodash is structured in a way that facilitates this. – Stijn de Witt Feb 08 '19 at 23:56
  • 7
    I don't agree with the comment about not deploying source maps to production - you will have a hard time debugging production-only issues, and source maps are required for code-quality monitoring services such as sentry.io. Sourcemaps dont get downloaded by the client unless they open devtools>Sources>source file – Graham Phillips Feb 23 '19 at 10:31
  • To add to this; making the lodash import simply: `import join from 'lodash/join'` should also make a significant difference. – DarkPurple141 May 22 '19 at 09:27
  • @GrahamPhillips by changing `inline-source-map` to `source-map`, the normal bundle will be smaller, and it can still be debugged, so `source-map` is another solution. – programmerRaj Jul 12 '21 at 18:33
  • Removing `inline-source-map` worked for me! – sayandcode Apr 28 '22 at 13:21
19

Add the below line in your vue.config.js file. It is because of the size. We need to split into chunks.

configureWebpack:{
    performance: {
      hints: false
    },
    optimization: {
      splitChunks: {
        minSize: 10000,
        maxSize: 250000,
      }
    }
}

This may help somebody.

Tony
  • 301
  • 3
  • 10
16

I had the same problem. My bundle file was (1.15 MiB). In my webpack.config.js, replacing :

devtool: 'inline-source-map'

by this line:

devtool: false,

takes my bundle file size from 1.15 MiB to 275 Kib.

Or create 2 separate webpack config files. One for dev and one for prod. In the prod webpack config file, delete the devtool option.

Alee
  • 740
  • 7
  • 19
  • not works for me... using this line `devtool: isProduction ? false : 'cheap-module-source-map', it stays in the same size – jose920405 Sep 12 '18 at 21:15
  • How are you building? If you use webpack cli, you must specify the production mode: webpack --mode=production – Alee Sep 13 '18 at 12:59
11

set mode flag to development/production in webpack.config.js. Example:

var mode = process.env.NODE_ENV || 'development';
module.exports = {
    ...
    devtool: (mode === 'development') ? 'inline-source-map' : false,
    mode: mode,
    ...
}
Kick Buttowski
  • 6,709
  • 13
  • 37
  • 58
Varun Kumar
  • 2,543
  • 1
  • 23
  • 22
3

Nuxt solution nuxt.config.js:

module.exports = {
 build: {
  extend(config, { isDev , isClient }) {
    if (isClient && !isDev) {
      config.optimization.splitChunks.maxSize = 250000
    }
  }
 }
}
Patryk
  • 329
  • 3
  • 12
  • 1
    you can define it normally within the webpack config, however this will not help because the warning refers to combined asset size, spliting it into chunks won't reduce it – Krzysztof Krzeszewski Sep 28 '21 at 10:38
  • It was to old nuxt (check date: Mar 25 '20 at 16:36) when there was error regarding this size. It don't fix website speed or size assets as a whole - just proper slice it to what you need (copy&paste solution above other methods). Fixing other thinks is more important - this just for webpack setting in nuxt without another file – Patryk Sep 28 '21 at 11:05
2

The main problem is devtool: 'inline-source-map' in webpack.common.js file in your case, in my case I use in development 'cheap-module-eval-source-map', this devtool is very nice for development mode but make my bundle.js to 4.2MiB, so, in production mode in webpack.prod.js file I change devtool like this:

module.exports = merge(common, {
    mode: 'production',
    performance: {
        hints: false
    },
    devtool: 'source-map'
});

and now from 4.2mb I've got 732KiB of bundle.js. This devtool will slow down process of bundling for few more seconds but will remarkably reduce the size of the file, in my example from 4.18 MiB to 732 KiB.

LW001
  • 2,452
  • 6
  • 27
  • 36
Goran_Ilic_Ilke
  • 812
  • 12
  • 16
  • 1
    MiB is not megabyte – atilkan Jan 27 '20 at 19:08
  • 1
    @atilkan . . . And strictly speaking, mb is not MB. MB = megabyte, mb = millibit?... But 'millibit' is ridiculous, of course. Like if one wants just a fraction of an atom. So I could accept mb to mean megabyte as well. ;) But... 'Mb' would actually mean 'megabit' instead of 'megabyte'! – Bart Hofland Jul 07 '20 at 13:00
  • 1
    If what you are saying is correct i find it confusing. Wonder where that standart comes from. – atilkan Jul 07 '20 at 19:31
  • @atikan From webpack. – Goran_Ilic_Ilke Jan 18 '21 at 12:38
  • this is correct, it's called Mebibyte which is 1024 * 1024, the mega prefix means x1,000,000 which is most commonly used and accepted but not as accurate – Schroed Nov 28 '22 at 17:50
1

For me, this was solved as said by others eliminating devtool in production

The code of webpack.config.js

module.exports = (env, argv) => {
  const mode = argv.mode || 'development'

  const config = {
    entry: './src/index.js',
    output: {
      path: `${__dirname}/lib`,
      filename: 'index.js',
      library: 'my-library',
      libraryTarget: 'umd',
    },
    module: {
      rules: [
        {
          test: /\.(js|jsx)$/,
          exclude: /node_modules/,
          use: ['babel-loader'],
        },
      ],
    },
    devtool: mode === 'development' ? 'cheap-module-eval-source-map' : false,
  }
  return config
}
GWorking
  • 4,011
  • 10
  • 49
  • 90
1

For me, code-splitting and adding 'CompressionPlugin' reduced the webpack size form 1.51 MiB to 350 KiB

new CompressionPlugin({
      filename: "[path][base].br",
      algorithm: "brotliCompress",
      test: /\.(js|jsx|css|html|svg|png|jpg|jpeg)$/,
      compressionOptions: {
        params: {
          [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
        },
      },
      threshold: 10240,
      minRatio: 0.8,
      deleteOriginalAssets: true,
    })

install the zlib library also

Cananau Cristian
  • 436
  • 2
  • 6
  • 30
Piyali
  • 162
  • 1
  • 4
0

Add this to your webpack.config.js. It should work.

performance: {
  hints: false,
  maxEntrypointSize: 512000,
  maxAssetSize: 512000
},
Tyler2P
  • 2,324
  • 26
  • 22
  • 31