Search code examples
reactjsrequirejswebpackumd

Creating React component for distribution results in much larger build than expected


I've loosely followed this link to create my react components for distribution. My webpack production build is below.

However my build comes out much larger than I would expect it to considering that the individual file sizes combined are somewhere around 1/10th the size. Specifically my file sizes for the source js and less files, combined is only 1.6kb. However the build is ~10x more at 13kb.

My components are extremely simple and similar. I have a FlexTable, a FlexTableRow and a FlexTableCell file. All of them have the same signature as below but with a different style.less. In my style.less it is basically a few lines of css that say display: flex; flex: 0 etc etc. So to summarize, very minimal js and very minimal amounts of css.

So the question is, why does the production build balloon to 13kb from 1.6kb? What am I doing wrong?

my-flex-table.js

var React = require('react');

const styles = require('./my-flex-table.less')

const FlexTable = (props) => (
  <section {...props} className={styles['my-flex-table'] + " " + props.customStyles}>{props.children}</section>
)

module.exports = FlexTable;

(Replace FlexTable with FlexTableRow or FlexTableCell in the above and you have my other files)

My package.json points to an index file that simply exports all 3 of these with module.exports = {FlexTable, FlexTableCell, FlexTableRow}

The webpack production script is run with:

NODE_ENV=production node_modules/webpack/bin/webpack.js --config webpack.config.prod.js

Webpack production script

var autoprefixer = require('autoprefixer');
var postcssImport = require('postcss-import');
var webpack = require('webpack');

module.exports = {
  entry: './src/index.jsx',
  output: {
    filename: './dist/my-flex-table.js',
    library: 'MyFlexTable',
    libraryTarget: 'umd',
  },
  resolve: {
    extensions: ['', '.js', '.jsx', '.less']
  },
  module: {
    loaders: [
      { test: /.jsx?$/,
        loader: 'babel',
        exclude: /node_modules/,
        query: {
          cacheDirectory: true,
          plugins: ['transform-runtime'],
          presets: ['es2015', 'stage-0','react']
        },
        "env": {
          "production": {
            "presets": ["react-optimize"]
          }
        }
      },
      { test: /.less$/, loader: 'style-loader!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader!less-loader' },
      { test: /\.(png|woff|woff2|eot|ttf|svg|jpg)$/, loader: 'url-loader?limit=100000' }
    ]
  },
  postcss: function (wp) {
      return [postcssImport({
                addDependencyTo: wp
      }),autoprefixer];
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production')
      }
    }),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        unused: true,
        dead_code: true,
        drop_console: true,
        warnings: false
      }
    })

  ],
  externals: [
    {
      react: {
        root: 'React',
        commonjs2: 'react',
        commonjs: 'react',
        amd: 'react',
      },
    },
    {
      'react-dom': {
        root: 'ReactDOM',
        commonjs2: 'react-dom',
        commonjs: 'react-dom',
        amd: 'react-dom',
      },
    },
  ]
};

Solution

  • The webpack visualizer is a good tool to troubleshoot bundle sizes. Follow the instructions there and it might help you see what extra is getting bundled in that you might not be intending.