1

我需要一些帮助来改善我的构建时间。我将我的 webpack 配置文件升级到版本 2,但构建时间比以前更糟。完成构建至少需要 3 分钟。

这是我的 webpack 文件

/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

require('dotenv').config();
import path from 'path';
import webpack from 'webpack';
import extend from 'extend';
import AssetsPlugin from 'assets-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import bundles from '../src/bundles'
import merge from 'lodash/merge'
import fs from 'fs'

const DEBUG = !process.argv.includes('--release');
const VERBOSE = process.argv.includes('--verbose');
const GLOBALS = {
  'process.env.NODE_ENV': DEBUG ? '"development"' : '"production"',
  'process.env.MORTGAGE_CALCULATOR_API': process.env.MORTGAGE_CALCULATOR_API ? `"${process.env.MORTGAGE_CALCULATOR_API}"` : null,
  'process.env.API_HOST': process.env.BROWSER_API_HOST ? `"${process.env.BROWSER_API_HOST}"` : process.env.API_HOST ? `"${process.env.API_HOST}"` : null,
  'process.env.GOOGLE_ANALYTICS_ID': process.env.GOOGLE_ANALYTICS_ID ? `"${process.env.GOOGLE_ANALYTICS_ID}"` : null,
  'process.env.OMNITURE_SUITE_ID': process.env.OMNITURE_SUITE_ID ? `"${process.env.OMNITURE_SUITE_ID}"` : null,
  'process.env.COOKIE_DOMAIN': process.env.COOKIE_DOMAIN ? `"${process.env.COOKIE_DOMAIN}"` : null,
  'process.env.FEATURE_FLAG_BAZAAR_VOICE': process.env.FEATURE_FLAG_BAZAAR_VOICE ? `"${process.env.FEATURE_FLAG_BAZAAR_VOICE}"` : null,
  'process.env.FEATURE_FLAG_REALTIME_RATING': process.env.FEATURE_FLAG_REALTIME_RATING ? `"${process.env.FEATURE_FLAG_REALTIME_RATING}"` : null,
  'process.env.SALE_RESULTS_PAGE_FLAG': process.env.SALE_RESULTS_PAGE_FLAG ? `"${process.env.SALE_RESULTS_PAGE_FLAG}"` : null,
  'process.env.SALE_RELOADED_RESULTS_PAGE_FLAG': process.env.SALE_RELOADED_RESULTS_PAGE_FLAG ? `"${process.env.SALE_RELOADED_RESULTS_PAGE_FLAG}"` : null,
  'process.env.TRACKER_DOMAIN': process.env.TRACKER_DOMAIN ? `"${process.env.TRACKER_DOMAIN}"` : null,
  'process.env.USER_SERVICE_ENDPOINT': process.env.USER_SERVICE_ENDPOINT ? `"${process.env.USER_SERVICE_ENDPOINT}"` : null,
  __DEV__: DEBUG
};

//
// Common configuration chunk to be used for both
// client-side (client.js) and server-side (server.js) bundles
// -----------------------------------------------------------------------------

const config = {
  output: {
    publicPath: '/blaze-assets/',
    sourcePrefix: '  ',
  },

  cache: DEBUG,

  stats: {
    colors: true,
    reasons: DEBUG,
    hash: VERBOSE,
    version: VERBOSE,
    timings: true,
    chunks: VERBOSE,
    chunkModules: VERBOSE,
    cached: VERBOSE,
    cachedAssets: VERBOSE,
  },

  plugins: [
    new ExtractTextPlugin({
      filename: DEBUG ? '[name].css' : '[name].[chunkhash].css',
      allChunks: true,
    }),
    new webpack.LoaderOptionsPlugin({
      debug: DEBUG,
    })
  ],

  resolve: {
    extensions: ['.webpack.js', '.web.js', '.js', '.jsx', '.json'],
    modules: [
      './src',
      'node_modules',
    ]
  },

  module: {
    rules: [
      {
        test: /\.jsx?$/,
        include: [
          path.resolve(__dirname, '../src'),
        ],
        loader: 'babel-loader',
      }, {
        test: /\.(scss|css)$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            'css-loader',
            'sass-loader',
          ]
        })
      }, {
        test: /\.txt$/,
        loader: 'raw-loader',
      }, {
        test: /\.(otf|png|jpg|jpeg|gif|svg|woff|woff2)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: 'url-loader?limit=10000',
      }, {
        test: /\.(eot|ttf|wav|mp3)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: 'file-loader',
      }, {
        test: /\.jade$/,
        loader: 'jade-loader',
      }
    ],
  },
};

//
// Configuration for the client-side bundles
// -----------------------------------------------------------------------------
let clientBundles = {}
Object.keys(bundles).forEach(function (bundle) {
  clientBundles[bundle] = [
    'bootstrap-loader',
    `./src/bundles/${bundle}/index.js`
  ]
})

merge(
  clientBundles,
  {
    'embedWidget': ['./src/components/Widgets/EmbedWidget/widgetLoader.js']
  }
)

const clientConfig = extend(true, {}, config, {
  entry: clientBundles,
  output: {
    path: path.join(__dirname, '../build/public/blaze-assets/'),
    filename: DEBUG ? '[name].js' : '[name].[chunkhash].js',
    chunkFilename: DEBUG ? '[name].chunk.js' : '[name].[chunkhash:8].chunk.js',
  },
  node: {
    fs: "empty"
  },
  // Choose a developer tool to enhance debugging
  // http://webpack.github.io/docs/configuration.html#devtool
  devtool: DEBUG ? 'cheap-module-source-map' : false,
  plugins: [
    ...config.plugins,
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new webpack.DefinePlugin({
      ...GLOBALS,
      'process.env.BROWSER': true
    }),
    ...(!DEBUG ? [
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
          screw_ie8: true,

          // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
          warnings: VERBOSE,
        },
      }),
      new webpack.optimize.AggressiveMergingPlugin(),
    ] : []),
    new AssetsPlugin({
      path: path.join(__dirname, '../build'),
      filename: 'assets.js',
      processOutput: x => `module.exports = ${JSON.stringify(x)};`,
    }),
  ],
});

//
// Configuration for the server-side bundle (server.js)
// -----------------------------------------------------------------------------

var srcDirs = {};
fs.readdirSync('src').forEach(function(path) {
  srcDirs[path] = true
});

function isExternalFile(context, request, callback) {
  var isExternal = request.match(/^[@a-z][a-z\/\.\-0-9]*$/i) && !srcDirs[request.split("/")[0]]
  callback(null, Boolean(isExternal));
}

const serverConfig = extend(true, {}, config, {
  entry: './src/server.js',
  output: {
    path: path.join(__dirname, '../build/public/blaze-assets/'),
    filename: '../../server.js',
    libraryTarget: 'commonjs2',
  },
  target: 'node',
  externals: [
    /^\.\/assets$/,
    isExternalFile
  ],
  node: {
    console: false,
    global: false,
    process: false,
    Buffer: false,
    __filename: false,
    __dirname: false,
  },
  devtool: DEBUG ? 'cheap-module-source-map' : 'source-map',
  plugins: [
    ...config.plugins,
    new webpack.DefinePlugin({
      ...GLOBALS,
      'process.env.BROWSER': false,
      'process.env.API_HOST': process.env.API_HOST ? `"${process.env.API_HOST}"` : null
    }),
    new webpack.NormalModuleReplacementPlugin(/\.(scss|css|eot|ttf|woff|woff2)$/, 'node-noop'),
    new webpack.BannerPlugin({
      banner: `require('dotenv').config(); require('newrelic'); require('source-map-support').install();`,
      raw: true,
      entryOnly: false
    })
  ],
});

export default [clientConfig, serverConfig];

这是我的 start.js 文件

    /**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import Browsersync from 'browser-sync'
import webpack from 'webpack'
import webpackMiddleware from 'webpack-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import run from './run'
import runServer from './runServer'
import webpackConfig from './webpack.config'
import clean from './clean'
import copy from './copy'

const DEBUG = !process.argv.includes('--release')

/**
 * Launches a development web server with "live reload" functionality -
 * synchronizing URLs, interactions and code changes across multiple devices.
 */
async function start () {
  await run(clean)
  await run(copy.bind(undefined, { watch: true }))
  await new Promise((resolve) => {
    // Patch the client-side bundle configurations
    // to enable Hot Module Replacement (HMR) and React Transform
    webpackConfig.filter((x) => x.target !== 'node').forEach((config) => {
      /* eslint-disable no-param-reassign */
      Object.keys(config.entry).forEach((entryKey) => {
        if (!Array.isArray(config.entry[entryKey])) {
          config.entry[entryKey] = [config.entry[entryKey]]
        }
        config.entry[entryKey].unshift('webpack-hot-middleware/client')
      })
      if (config.output.filename) {
        config.output.filename = config.output.filename.replace('[chunkhash]', '[hash]')
      }
      if (config.output.chunkFilename) {
        config.output.chunkFilename = config.output.chunkFilename.replace('[chunkhash]', '[hash]')
      }
      config.plugins.push(new webpack.HotModuleReplacementPlugin())
      config.plugins.push(new webpack.NoEmitOnErrorsPlugin())
      config
        .module
        .rules
        .filter((x) => x.loader === 'babel-loader')
        .forEach((x) => (x.query = {
          ...x.query,
          // Wraps all React components into arbitrary transforms
          // https://github.com/gaearon/babel-plugin-react-transform
          plugins: [
            ...(x.query ? x.query.plugins : []),
            ['react-transform', {
              transforms: [
                {
                  transform: 'react-transform-hmr',
                  imports: ['react'],
                  locals: ['module'],
                }, {
                  transform: 'react-transform-catch-errors',
                  imports: ['react', 'redbox-react'],
                },
              ],
            },
            ],
          ],
        }))
      /* eslint-enable no-param-reassign */
    })

    const bundler = webpack(webpackConfig)
    const wpMiddleware = webpackMiddleware(bundler, {

      // IMPORTANT: webpack middleware can't access config,
      // so we should provide publicPath by ourselves
      publicPath: webpackConfig[0].output.publicPath,

      // Pretty colored output
      stats: webpackConfig[0].stats,

      // For other settings see
      // https://webpack.github.io/docs/webpack-dev-middleware
    })
    const hotMiddlewares = bundler
      .compilers
      .filter((compiler) => compiler.options.target !== 'node')
      .map((compiler) => webpackHotMiddleware(compiler))

    let handleServerBundleComplete = () => {
      runServer((err, host) => {
        if (!err) {
          const bs = Browsersync.create()
          bs.init({
            ...(DEBUG ? {} : { notify: false, ui: false }),

            proxy: {
              target: host,
              middleware: [wpMiddleware, ...hotMiddlewares],
            },
            open: false,

            // no need to watch '*.js' here, webpack will take care of it for us,
            // including full page reloads if HMR won't work
            files: ['build/content/**/*.*'],
          }, resolve)
          handleServerBundleComplete = runServer
        }
      })
    }

    bundler.plugin('done', () => handleServerBundleComplete())
  })
}

export default start

我正在使用 react-starter-kit 但它是原始版本的略微修改版本。我尝试将 css-loader 降级到 0.14.5 以查看改进但没有区别。此外,从 UglifyJSPlugin 中删除了 sourceMap。任何帮助都值得赞赏!

4

0 回答 0