无法使webpack缩小捆绑

时间:2017-06-21 20:26:54

标签: javascript reactjs webpack minify

我正在尝试缩小我的webpack捆绑包,因为现在第一次加载网站大约需要25秒。 app.bundle.js是11,989KB,vendor.bundle.js是1,842KB 我自己的代码只有几KB。 当我检查app.bundle.js的内容时,大部分空间都被外部库占用(react-dom,moment,react-bootstrap ......)

所以我试图缩小它们,但出于某种原因,我尝试的一切都没有用。

我不是webpack的专家,所以非常欢迎更多知识渊博的人的帮助。

注意:我使用的webpack文件来自我用过的另一个项目。所以它可能没有完美配置。

这是我的package.json:

{
  "name": "myproject",
  "version": "0.1.0",
  "description": "a description.",
  "private": true,
  "devDependencies": {
    "babel-plugin-react-html-attrs": "^2.0.0",
    "babel-plugin-transform-runtime": "^6.15.0",
    "babel-polyfill": "^6.16.0",
    "babel-preset-stage-2": "^6.18.0",
    "babili-webpack-plugin": "^0.1.1",
    "compression-webpack-plugin": "^0.4.0",
    "react-hot-loader": "^1.3.1",
    "react-scripts": "0.9.2",
    "serve-favicon": "^2.3.2",
    "webpack-dev-server": "^2.4.1",
    "webpack-hot-middleware": "^2.13.2"
  },
  "dependencies": {
    "axios": "^0.15.2",
    "babel-core": "^6.2.1",
    "babel-loader": "^6.2.0",
    "babel-plugin-transform-class-properties": "^6.18.0",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-plugin-transform-runtime": "^6.15.0",
    "babel-polyfill": "^6.16.0",
    "babel-preset-es2015": "^6.1.18",
    "babel-preset-react": "^6.1.18",
    "babel-preset-stage-0": "^6.3.13",
    "babel-preset-stage-2": "^6.3.13",
    "circular-dependency-plugin": "^2.0.0",
    "classnames": "^2.2.1",
    "clean-webpack-plugin": "^0.1.9",
    "copy-webpack-plugin": "^4.0.1",
    "css-loader": "^0.26.2",
    "dotenv": "^4.0.0",
    "es6-promise": "^4.0.5",
    "file-loader": "^0.10.1",
    "firebase": "^3.6.0",
    "history": "^4.5.1",
    "immutable": "^3.8.1",
    "invariant": "^2.2.0",
    "isomorphic-fetch": "^2.2.1",
    "jsonwebtoken": "^7.2.1",
    "less-loader": "^2.2.0",
    "moment": "^2.11.1",
    "react": "^15.4.2",
    "react-addons-css-transition-group": "^15.4.2",
    "react-async-script": "^0.7.0",
    "react-bootstrap": "^0.30.7",
    "react-dnd": "^2.0.2",
    "react-dnd-html5-backend": "^2.0.2",
    "react-dom": "^15.4.2",
    "react-fontawesome": "^1.5.0",
    "react-google-recaptcha": "^0.6.0",
    "react-gravatar": "^2.2.2",
    "react-helmet": "^4.0.0",
    "react-input-range": "^1.0.2",
    "react-modal": "^1.5.2",
    "react-page-click": "^3.0.0",
    "react-recaptcha": "^2.2.6",
    "react-redux": "^5.0.3",
    "react-router": "^3.0.2",
    "react-router-redux": "^4.0.0",
    "redux": "^3.0.4",
    "redux-form": "^6.2.0",
    "redux-logger": "^2.3.2",
    "redux-thunk": "^2.2.0",
    "rimraf": "^2.5.4",
    "single-module-instance-webpack-plugin": "0.0.4",
    "style-loader": "^0.13.2",
    "superagent": "^3.5.0",
    "webpack": "^2.2.1",
    "xml2js": "^0.4.17",
    "xmldom": "^0.1.27",
    "xpath": "0.0.23"
  },
  "scripts": {
    "start": "node devServer.js --progress --verbose",
    "clean": "rimraf ./dist",
    "dev": "webpack -d --watch --progress --display-error-details --display-reasons",
    "start1": "webpack-dev-server  --config ./webpack.config.comphotdeploy -d --progress --colors --host localhost --port 28080 --hot --inline --content-base src",
    "builddev": "webpack -d --progress --display-error-details --display-reasons",
    "build": "webpack -p --progress --verbose",
    "dist": "rimraf ./dist&&webpack -d --display-error-details --display-reasons",
    "start-react": "SET PORT=9999&&SET DEVTOOL=source-map&&react-scripts start",
    "build-react": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "./node_modules/react-scripts/config/eslint.js"
  }
}

我的网站:

var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

var webpack = require('webpack');
var path = require('path');

var ProvidePlugin = require("webpack/lib/ProvidePlugin");
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
var LimitChunkCountPlugin = require("webpack/lib/optimize/LimitChunkCountPlugin");
var DedupePlugin = require("webpack/lib/optimize/DedupePlugin");
var SingleModuleInstancePlugin = require('single-module-instance-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var CircularDependencyPlugin = require('circular-dependency-plugin');

var BUILD_DIR =  path.resolve(__dirname,'dist');

var APP_DIR = path.resolve(__dirname, 'src');

const BabiliPlugin = require('babili-webpack-plugin');

// http://dev.topheman.com/make-your-react-production-minified-version-with-webpack/
// https://medium.com/@rajaraodv/two-quick-ways-to-reduce-react-apps-size-in-production-82226605771a
// https://hackernoon.com/tricks-to-minimize-react-js-build-file-size-a35e355b8c64
var CompressionPlugin = require('compression-webpack-plugin');

// Load environment variables from .env file. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set.
// https://github.com/motdotla/dotenv
require('dotenv').config({silent: true});

var PrintChunksPlugin = function() {};
PrintChunksPlugin.prototype.apply = function(compiler) {
    compiler.plugin('compilation', function(compilation, params) {
        compilation.plugin('after-optimize-chunk-assets', function(chunks) {
            console.log(chunks.map(function(c) {
                return {
                    id: c.id,
                    name: c.name
/*,
                    includes: c.modules.map(function(m) {
                        return m.request;
                    })
*/
                };
            }));
        });
    });
};

var config = {
    devtool: 'cheap-module-source-map',
    entry: {
        app: APP_DIR + '/index.js',
        vendor: [
            'react',
            'react-dom'
        ]
    },

    output: {
        path:BUILD_DIR,
        filename: "[name].bundle.js",
        chunkFilename: "[name]-chunk.js",
        publicPath: BUILD_DIR
    },

  watch: false,
  watchOptions: {
    poll: true,
    aggregateTimeout: 300,
    number: 1000
  },
  module : {
      loaders : [
          {
              test : /\.jsx?/,
              include : APP_DIR,
              exclude: /node_modules/,
              loaders: ['react-hot-loader', 'babel-loader?' + JSON.stringify({
                cacheDirectory: true,
                plugins: [
                  'transform-runtime',
                  'react-html-attrs',
                  'transform-class-properties',
                  'transform-decorators-legacy'
                ],
                presets: [
                    [
                        "es2015",
                        {
                            "modules": false
                        }
                    ],
                    'react',
                    'stage-2']
              })]
          },

          // CSS
          // "css" loader resolves paths in CSS and adds assets as dependencies.
          // "style" loader turns CSS into JS modules that inject <style> tags.
          // In production, we use a plugin to extract that CSS to a file, but
          // in development "style" loader enables hot editing of CSS.
          {
              test: /\.css$/,
              include: path.join(__dirname, 'src/style'),
              loader: 'style-loader!css-loader'
          },
          // "file" loader makes sure those assets get served by WebpackDevServer.
          // When you `import` an asset, you get its (virtual) filename.
          // In production, they would get copied to the `build` folder.
          {
              test: /\.(ico|jpg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/,
              exclude: /\/favicon.ico$/,
              loader: 'file-loader',
              query: {
                name: '[path][name][hash].[ext]',
                publicPath: '/'
              }
          },
          {
              test: /\.(ico)(\?.*)?$/,
              exclude: /node_modules/,
              loader: 'file-loader',
              query: {
                  name: './images/[name].[ext]'
              }
          }
      ]
  },

     // use EnableCircularDependencyPlugin=true|false to check the option
  plugins: [
      new webpack.DefinePlugin({
          // A common mistake is not stringifying the "production" string.
          'process.env': { 'NODE_ENV': JSON.stringify('production') },

          // DISABLE redux-devtools HERE
          __DEVTOOLS__: false 
      }),

      // minify everything
      new webpack.optimize.UglifyJsPlugin({
          compressor: {
              warnings: false
          }
      }),

      // Merge chunks
      new webpack.optimize.AggressiveMergingPlugin(),

      /*
      new CompressionPlugin({
          asset: "[path].gz[query]",
          algorithm: "gzip",
          test: /\.js$|\.css$|\.html$/,
          threshold: 10240,
          minRatio: 0.8
      }),
      */

      // new BabiliPlugin(),

      new CopyWebpackPlugin([
          { from: APP_DIR + '/index.html', to: BUILD_DIR + '/index.html' },
          { from: APP_DIR + '/images/favicon.ico', to: BUILD_DIR + '/images/favicon.ico' },
          { from: APP_DIR + '/images/favicon.png', to: BUILD_DIR + '/images/favicon.png' },
          { from: APP_DIR + '/images/favicon-16x16.png', to: BUILD_DIR + '/images/favicon-16x16.png' },
          { from: APP_DIR + '/images/favicon-32x32.png', to: BUILD_DIR + '/images/favicon-32x32.png' },
          { from: APP_DIR + '/images/favicon-48x48.png', to: BUILD_DIR + '/images/favicon-48x48.png' },
          { from: APP_DIR + '/images/favicon-57x57.png', to: BUILD_DIR + '/images/favicon-57x57.png' },
          { from: APP_DIR + '/images/favicon-60x60.png', to: BUILD_DIR + '/images/favicon-60x60.png' },
          { from: APP_DIR + '/images/favicon-72x72.png', to: BUILD_DIR + '/images/favicon-72x72.png' },
          { from: APP_DIR + '/images/favicon-76x76.png', to: BUILD_DIR + '/images/favicon-76x76.png' },
          { from: APP_DIR + '/images/favicon-96x96.png', to: BUILD_DIR + '/images/favicon-96x96.png' },
          { from: APP_DIR + '/images/favicon-114x114.png', to: BUILD_DIR + '/images/favicon-114x114.png' },
          { from: APP_DIR + '/images/favicon-120x120.png', to: BUILD_DIR + '/images/favicon-120x120.png' },
          { from: APP_DIR + '/images/favicon-144x144.png', to: BUILD_DIR + '/images/favicon-144x144.png' },
          { from: APP_DIR + '/images/favicon-152x152.png', to: BUILD_DIR + '/images/favicon-152x152.png' },
          { from: APP_DIR + '/images/favicon-160x160.png', to: BUILD_DIR + '/images/favicon-160x160.png' },
          { from: APP_DIR + '/images/favicon-180x180.png', to: BUILD_DIR + '/images/favicon-180x180.png' },
          { from: APP_DIR + '/images/favicon-192x192.png', to: BUILD_DIR + '/images/favicon-192x192.png' }
          ]),

      //new BundleAnalyzerPlugin({analyzerMode: 'static'}),
      //new PrintChunksPlugin()
    ],

      /*
            new webpack.HotModuleReplacementPlugin(),

            new webpack.NoEmitOnErrorsPlugin(),

            new webpack.optimize.CommonsChunkPlugin({
                name: 'permateam-core',
                minChunks(module, count) {
                    var context = module.context;
                    return context && context.indexOf('src\\') >= 0;
                },
            }),

            new webpack.optimize.CommonsChunkPlugin({
                name: 'react-build',
                minChunks(module, count) {
                    var context = module.context;
                    return context && (context.indexOf('node_modules\\react\\') >= 0 || context.indexOf('node_modules\\react-dom\\') >= 0);
                },
            }),

            new webpack.optimize.CommonsChunkPlugin({
                name: 'manifest'
            }),

            // uglfy / minify js
            new webpack.optimize.OccurrenceOrderPlugin(),
            new webpack.optimize.UglifyJsPlugin({
                mangle: true,
                compress: {
                    warnings: false, // Suppress uglification warnings
                    pure_getters: true,
                    unsafe: true,
                    unsafe_comps: true,
                    screw_ie8: true
                },
                output: {
                    comments: false,
                },
                exclude: [/\.min\.js$/gi] // skip pre-minified libs
            }),

            new BundleAnalyzerPlugin({analyzerMode: 'static'}),
            //new PrintChunksPlugin(),

        //*********************************** async chunks*************************

        //catch all - anything used in more than one place
        new webpack.optimize.CommonsChunkPlugin({
            async: 'used-twice',
            minChunks(module, count) {
                return count >= 2;
            },
        }),

        //specifically bundle these large things
       new webpack.optimize.CommonsChunkPlugin({
            async: 'react-dnd',
            minChunks(module, count) {
                var context = module.context;
                var targets = ['react-dnd', 'react-dnd-html5-backend', 'react-dnd-touch-backend', 'dnd-core']
                return context && context.indexOf('node_modules') >= 0 && targets.find(t => new RegExp('\\\\' + t + '\\\\', 'i').test(context));
            },
        }),

        return plugins;
    })(),
    */

    node: {
        net: 'empty',
        dns: 'empty'
    }
};

module.exports = config;

1 个答案:

答案 0 :(得分:0)

即使我不明白问题发生的原因,我也找到了解决问题的方法。

我在做

  

npm run dist

现在我在做

  

npm run build

现在app.bundle.js是1,765KB,vendor.bundle.js是151KB

我仍然需要做一些优化来进一步缩小app.bundle.js,但这已经是一个好的开始。

如果有人有想法的话,我仍然想知道为什么minify与dist不起作用。