10
10
// This alternative WebpackDevServer combines the functionality of:
11
11
// https://github.com/webpack/webpack-dev-server/blob/webpack-1/client/index.js
12
12
// https://github.com/webpack/webpack/blob/webpack-1/hot/dev-server.js
13
+
13
14
// It only supports their simplest configuration (hot updates on same server).
14
15
// It makes some opinionated choices on top, like adding a syntax error overlay
15
- // The error overlay is inspired by:
16
+ // that looks similar to our console output. The error overlay is inspired by:
16
17
// https://github.com/glenjamin/webpack-hot-middleware
17
- // The error overlay is provided by:
18
- // https://github.com/pmmmwh/react-refresh-webpack-plugin/tree/master/src/overlay
19
18
19
+ var stripAnsi = require ( 'strip-ansi' ) ;
20
20
var url = require ( 'url' ) ;
21
+ var launchEditorEndpoint = require ( './launchEditorEndpoint' ) ;
22
+ var formatWebpackMessages = require ( './formatWebpackMessages' ) ;
23
+ var ErrorOverlay = require ( 'react-error-overlay' ) ;
24
+
25
+ ErrorOverlay . setEditorHandler ( function editorHandler ( errorLocation ) {
26
+ // Keep this sync with errorOverlayMiddleware.js
27
+ fetch (
28
+ launchEditorEndpoint +
29
+ '?fileName=' +
30
+ window . encodeURIComponent ( errorLocation . fileName ) +
31
+ '&lineNumber=' +
32
+ window . encodeURIComponent ( errorLocation . lineNumber || 1 ) +
33
+ '&colNumber=' +
34
+ window . encodeURIComponent ( errorLocation . colNumber || 1 )
35
+ ) ;
36
+ } ) ;
37
+
38
+ // We need to keep track of if there has been a runtime error.
39
+ // Essentially, we cannot guarantee application state was not corrupted by the
40
+ // runtime error. To prevent confusing behavior, we forcibly reload the entire
41
+ // application. This is handled below when we are notified of a compile (code
42
+ // change).
43
+ // See https://github.com/facebook/create-react-app/issues/3096
44
+ var hadRuntimeError = false ;
45
+ ErrorOverlay . startReportingRuntimeErrors ( {
46
+ onError : function ( ) {
47
+ hadRuntimeError = true ;
48
+ } ,
49
+ filename : '/static/js/bundle.js' ,
50
+ } ) ;
51
+
52
+ if ( module . hot && typeof module . hot . dispose === 'function' ) {
53
+ module . hot . dispose ( function ( ) {
54
+ // TODO: why do we need this?
55
+ ErrorOverlay . stopReportingRuntimeErrors ( ) ;
56
+ } ) ;
57
+ }
21
58
22
59
// Connect to WebpackDevServer via a socket.
23
60
var connection = new WebSocket (
@@ -45,15 +82,106 @@ connection.onclose = function() {
45
82
// Remember some state related to hot module replacement.
46
83
var isFirstCompilation = true ;
47
84
var mostRecentCompilationHash = null ;
85
+ var hasCompileErrors = false ;
86
+
87
+ function clearOutdatedErrors ( ) {
88
+ // Clean up outdated compile errors, if any.
89
+ if ( typeof console !== 'undefined' && typeof console . clear === 'function' ) {
90
+ if ( hasCompileErrors ) {
91
+ console . clear ( ) ;
92
+ }
93
+ }
94
+ }
48
95
49
96
// Successful compilation.
50
97
function handleSuccess ( ) {
98
+ clearOutdatedErrors ( ) ;
99
+
51
100
var isHotUpdate = ! isFirstCompilation ;
52
101
isFirstCompilation = false ;
102
+ hasCompileErrors = false ;
53
103
54
104
// Attempt to apply hot updates or reload.
55
105
if ( isHotUpdate ) {
56
- tryApplyUpdates ( ) ;
106
+ tryApplyUpdates ( function onHotUpdateSuccess ( ) {
107
+ // Only dismiss it when we're sure it's a hot update.
108
+ // Otherwise it would flicker right before the reload.
109
+ tryDismissErrorOverlay ( ) ;
110
+ } ) ;
111
+ }
112
+ }
113
+
114
+ // Compilation with warnings (e.g. ESLint).
115
+ function handleWarnings ( warnings ) {
116
+ clearOutdatedErrors ( ) ;
117
+
118
+ var isHotUpdate = ! isFirstCompilation ;
119
+ isFirstCompilation = false ;
120
+ hasCompileErrors = false ;
121
+
122
+ function printWarnings ( ) {
123
+ // Print warnings to the console.
124
+ var formatted = formatWebpackMessages ( {
125
+ warnings : warnings ,
126
+ errors : [ ] ,
127
+ } ) ;
128
+
129
+ if ( typeof console !== 'undefined' && typeof console . warn === 'function' ) {
130
+ for ( var i = 0 ; i < formatted . warnings . length ; i ++ ) {
131
+ if ( i === 5 ) {
132
+ console . warn (
133
+ 'There were more warnings in other files.\n' +
134
+ 'You can find a complete log in the terminal.'
135
+ ) ;
136
+ break ;
137
+ }
138
+ console . warn ( stripAnsi ( formatted . warnings [ i ] ) ) ;
139
+ }
140
+ }
141
+ }
142
+
143
+ printWarnings ( ) ;
144
+
145
+ // Attempt to apply hot updates or reload.
146
+ if ( isHotUpdate ) {
147
+ tryApplyUpdates ( function onSuccessfulHotUpdate ( ) {
148
+ // Only dismiss it when we're sure it's a hot update.
149
+ // Otherwise it would flicker right before the reload.
150
+ tryDismissErrorOverlay ( ) ;
151
+ } ) ;
152
+ }
153
+ }
154
+
155
+ // Compilation with errors (e.g. syntax error or missing modules).
156
+ function handleErrors ( errors ) {
157
+ clearOutdatedErrors ( ) ;
158
+
159
+ isFirstCompilation = false ;
160
+ hasCompileErrors = true ;
161
+
162
+ // "Massage" webpack messages.
163
+ var formatted = formatWebpackMessages ( {
164
+ errors : errors ,
165
+ warnings : [ ] ,
166
+ } ) ;
167
+
168
+ // Only show the first error.
169
+ ErrorOverlay . reportBuildError ( formatted . errors [ 0 ] ) ;
170
+
171
+ // Also log them to the console.
172
+ if ( typeof console !== 'undefined' && typeof console . error === 'function' ) {
173
+ for ( var i = 0 ; i < formatted . errors . length ; i ++ ) {
174
+ console . error ( stripAnsi ( formatted . errors [ i ] ) ) ;
175
+ }
176
+ }
177
+
178
+ // Do not attempt to reload now.
179
+ // We will reload on next success instead.
180
+ }
181
+
182
+ function tryDismissErrorOverlay ( ) {
183
+ if ( ! hasCompileErrors ) {
184
+ ErrorOverlay . dismissBuildError ( ) ;
57
185
}
58
186
}
59
187
@@ -78,6 +206,12 @@ connection.onmessage = function(e) {
78
206
// Triggered when a file from `contentBase` changed.
79
207
window . location . reload ( ) ;
80
208
break ;
209
+ case 'warnings' :
210
+ handleWarnings ( message . data ) ;
211
+ break ;
212
+ case 'errors' :
213
+ handleErrors ( message . data ) ;
214
+ break ;
81
215
default :
82
216
// Do nothing.
83
217
}
@@ -108,7 +242,12 @@ function tryApplyUpdates(onHotUpdateSuccess) {
108
242
return ;
109
243
}
110
244
111
- function handleApplyUpdates ( ) {
245
+ function handleApplyUpdates ( err , updatedModules ) {
246
+ if ( err || ! updatedModules || hadRuntimeError ) {
247
+ window . location . reload ( ) ;
248
+ return ;
249
+ }
250
+
112
251
if ( typeof onHotUpdateSuccess === 'function' ) {
113
252
// Maybe we want to do something.
114
253
onHotUpdateSuccess ( ) ;
0 commit comments