createWebpackCompiler.js 3.62 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
// @remove-on-eject-begin
/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
// @remove-on-eject-end
'use strict';

13
14
15
16
const chalk = require('chalk');
const webpack = require('webpack');
const clearConsole = require('react-dev-utils/clearConsole');
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
Daniel Grant's avatar
Daniel Grant committed
17

18
19
const isInteractive = process.stdout.isTTY;
let handleCompile;
Daniel Grant's avatar
Daniel Grant committed
20
21
22

// You can safely remove this after ejecting.
// We only use this block for testing of Create React App itself:
23
const isSmokeTest = process.argv.some(arg => arg.indexOf('--smoke-test') > -1);
Daniel Grant's avatar
Daniel Grant committed
24
if (isSmokeTest) {
25
  handleCompile = (err, stats) => {
Daniel Grant's avatar
Daniel Grant committed
26
27
28
29
30
31
32
33
34
35
36
    if (err || stats.hasErrors() || stats.hasWarnings()) {
      process.exit(1);
    } else {
      process.exit(0);
    }
  };
}

module.exports = function createWebpackCompiler(config, onReadyCallback) {
  // "Compiler" is a low-level interface to Webpack.
  // It lets us listen to some events and provide our own custom messages.
37
  let compiler;
Daniel Grant's avatar
Daniel Grant committed
38
  try {
39
    compiler = webpack(config, handleCompile);
Daniel Grant's avatar
Daniel Grant committed
40
41
42
43
44
45
46
47
48
49
50
51
  } catch (err) {
    console.log(chalk.red('Failed to compile.'));
    console.log();
    console.log(err.message || err);
    console.log();
    process.exit(1);
  }

  // "invalid" event fires when you have changed a file, and Webpack is
  // recompiling a bundle. WebpackDevServer takes care to pause serving the
  // bundle, so if you refresh, it'll wait instead of serving the old one.
  // "invalid" is short for "bundle invalidated", it doesn't imply any errors.
52
  compiler.plugin('invalid', () => {
Daniel Grant's avatar
Daniel Grant committed
53
54
55
56
57
58
    if (isInteractive) {
      clearConsole();
    }
    console.log('Compiling...');
  });

59
  let isFirstCompile = true;
Daniel Grant's avatar
Daniel Grant committed
60
61
62

  // "done" event fires when Webpack has finished recompiling the bundle.
  // Whether or not you have warnings or errors, you will get this event.
63
  compiler.plugin('done', stats => {
Daniel Grant's avatar
Daniel Grant committed
64
65
66
67
68
69
70
    if (isInteractive) {
      clearConsole();
    }

    // We have switched off the default Webpack output in WebpackDevServer
    // options so we are going to "massage" the warnings and errors and present
    // them in a readable focused way.
71
72
73
    const messages = formatWebpackMessages(stats.toJson({}, true));
    const isSuccessful = !messages.errors.length && !messages.warnings.length;
    const showInstructions = isSuccessful && (isInteractive || isFirstCompile);
Daniel Grant's avatar
Daniel Grant committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

    if (isSuccessful) {
      console.log(chalk.green('Compiled successfully!'));
    }

    if (typeof onReadyCallback === 'function') {
      onReadyCallback(showInstructions);
    }
    isFirstCompile = false;

    // If errors exist, only show errors.
    if (messages.errors.length) {
      console.log(chalk.red('Failed to compile.'));
      console.log();
      messages.errors.forEach(message => {
        console.log(message);
        console.log();
      });
      return;
    }

    // Show warnings if no errors were found.
    if (messages.warnings.length) {
      console.log(chalk.yellow('Compiled with warnings.'));
      console.log();
      messages.warnings.forEach(message => {
        console.log(message);
        console.log();
      });
103

Daniel Grant's avatar
Daniel Grant committed
104
      // Teach some ESLint tricks.
105
      console.log(
106
107
108
        'Search the ' +
          chalk.dim('keywords') +
          ' from the right column to learn more.'
109
110
      );
      console.log(
111
112
113
        'To ignore, add ' +
          chalk.yellow('// eslint-disable-next-line') +
          ' to the line before.'
114
      );
Daniel Grant's avatar
Daniel Grant committed
115
116
117
118
119
    }
  });

  return compiler;
};