Search code examples
reactjswebpackwebpack-2

Webpack 2.X Not Minifying React App During Production Bundling


I'm having a similar issue to this question which did not seem to get resolved there.

I've finished V1 of my React app and I ran webpack -p to bundle it up for production. The dev version of the bundle is ~2MB and the prod version is the same size. The React dev tools extension confirms I'm still in dev mode and the webpack-bundle-analyzer graphs that React, Chart, and Moment are all > 400kb.

The console output has no errors that I can see.

Anyone run into this issue or know what I'm doing wrong?

webpack.config.js

const path = require('path');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const extractSass = new ExtractTextPlugin({
  filename: 'bundle.css'
});

module.exports = {
  context: __dirname,
  entry: './client/src/js/App.jsx',
  devtool: 'eval',
  output: {
    path: path.join(__dirname, '/client/dist'),
    filename: 'bundle.js'
  },
  resolve: {
    extensions: ['.js', '.jsx', '.json', '.scss', 'css']
  },
  stats: {
    colors: true,
    reasons: true,
    chunks: true
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'eslint-loader',
        include: path.join(__dirname, '/client/src/js'),
        enforce: 'pre'
      },
      {
        test: /\.json$/,
        loader: 'json-loader'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: path.join(__dirname, '/client/src/js')
      },
      {
        test: /\.jsx$/,
        loader: 'babel-loader',
        include: path.join(__dirname, '/client/src/js')
      },
      {
        test: /\.scss$/,
        loader: extractSass.extract({
            loader: [
              {
                loader: 'css-loader'
              },
              {
                loader: 'sass-loader'
              }
            ]
        })
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader'
          }
        ]
      }
    ]
  },
  plugins: [
    extractSass,
    new BundleAnalyzerPlugin()
  ]
};

webpack -p console output

Hash: 8bdf532dc582e2609c1a
Version: webpack 2.6.1
Time: 4904ms
     Asset     Size  Chunks                    Chunk Names
 bundle.js  2.07 MB       0  [emitted]  [big]  main
bundle.css  8.22 kB       0  [emitted]         main
   [4] ./~/react/react.js 56 bytes {0} [built]
  [18] ./~/react-router-dom/es/index.js 925 bytes {0} [built]
  [69] ./~/react-dom/index.js 59 bytes {0} [built]
 [230] ./client/src/js/Footer.jsx 324 bytes {0} [built]
 [231] ./client/src/js/Home.jsx 431 bytes {0} [built]
 [232] ./client/src/js/Hub.jsx 11.4 kB {0} [built]
 [233] ./client/src/js/Hubs.jsx 806 bytes {0} [built]
 [234] ./client/src/js/Nav.jsx 1.06 kB {0} [built]
 [235] ./client/src/js/News.jsx 3.54 kB {0} [built]
 [236] ./client/src/js/Overview.jsx 13.8 kB {0} [built]
 [237] ./client/src/js/Privacy.jsx 263 bytes {0} [built]
 [238] ./client/src/js/Ranks.jsx 6.65 kB {0} [built]
 [239] ./client/src/js/TermsConditions.jsx 305 bytes {0} [built]
 [240] ./client/src/scss/bundle.scss 41 bytes {0} [built]
 [258] ./client/src/js/App.jsx 3.6 kB {0} [built]
    + 422 hidden modules
Child extract-text-webpack-plugin:
       [0] ./~/css-loader/lib/css-base.js 1.51 kB {0} [built]
       [1] ./~/css-loader!./~/sass-loader/lib/loader.js!./client/src/scss/bundle.scss 8.72 kB {0} [built]

package.json

{
  "name": "",
  "version": "1.0.0",
  "description": "",
  "repository": "",
  "main": "server.js",
  "private": true,
  "engines": {
    "node": "6.9.5"
  },
  "scripts": {
    "prod": "webpack -p",
    "dev": "webpack --watch",
    "serve": "nodemon server.js"
  },
  "author": "",
  "dependencies": {
    "async": "^2.4.1",
    "axios": "^0.16.1",
    "body-parser": "^1.15.2",
    "dotenv": "^4.0.0",
    "express": "^4.14.0",
    "mongoose": "^4.8.0",
    "nodemon": "^1.11.0",
    "path": "^0.12.7"
  },
  "devDependencies": {
    "babel-core": "6.16.0",
    "babel-loader": "6.2.7",
    "babel-plugin-transform-es2015-modules-commonjs": "^6.18.0",
    "babel-polyfill": "^6.16.0",
    "babel-preset-es2015": "6.18.0",
    "babel-preset-es2017": "6.16.0",
    "babel-preset-react": "6.16.0",
    "babel-register": "6.16.0",
    "chart.js": "^2.6.0",
    "css-loader": "0.25.0",
    "eslint": "^3.15.0",
    "eslint-loader": "1.7.0",
    "eslint-plugin-promise": "2.0.1",
    "eslint-plugin-react": "6.3.0",
    "extract-text-webpack-plugin": "2.1.0",
    "jsdom": "9.5.0",
    "json-loader": "0.5.4",
    "lodash": "4.16.2",
    "node-sass": "^4.5.0",
    "react": "15.5.4",
    "react-chartjs-2": "^2.1.0",
    "react-dom": "15.5.4",
    "react-router-dom": "^4.1.1",
    "sass-loader": "^5.0.1",
    "style-loader": "0.13.1",
    "webpack": "2.6.1",
    "webpack-bundle-analyzer": "^2.8.2",
    "yarn": "^0.24.6"
  }
}

example component header

import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
import axios from 'axios';

import Utilities from './Utilities.jsx';
import Header from './Header';
import ChartLine from './ChartLine';
import ChartDoughnut from './ChartDoughnut';

Solution

  • Your issue is devtool: 'eval' line in your Webpack config. Webpack does not automatically disable source maps for production builds; it's on you to check the process.env.NODE_ENV to see if it's in production and disable source maps. Source maps are extremely large (but very useful for development.)

    You'll want to change line to be something like devtool: process.env.NODE_ENV === 'production' ? false : 'eval' and set source maps to be false when doing production builds. This should cut 1.5MB+ off your final build.