@@ -39,13 +39,10 @@ var colors = {
3939} ;
4040ansiHTML . setColors ( colors ) ;
4141
42- function showErrorOverlay ( message ) {
43- // Use an iframe so that document styles don't mess up the overlay.
44- var iframeID = 'react-dev-utils-webpack-hot-dev-client-overlay' ;
45- var iframe =
46- document . getElementById ( iframeID ) ||
47- document . createElement ( 'iframe' ) ;
48- iframe . id = iframeID ;
42+ function createOverlayIframe ( onIframeLoad ) {
43+ var iframe = document . createElement ( 'iframe' ) ;
44+ iframe . id = 'react-dev-utils-webpack-hot-dev-client-overlay' ;
45+ iframe . src = 'about:blank' ;
4946 iframe . style . position = 'fixed' ;
5047 iframe . style . left = 0 ;
5148 iframe . style . top = 0 ;
@@ -55,39 +52,74 @@ function showErrorOverlay(message) {
5552 iframe . style . height = '100vh' ;
5653 iframe . style . border = 'none' ;
5754 iframe . style . zIndex = 9999999999 ;
58- document . body . appendChild ( iframe ) ;
59-
60- // Inside, make a div.
61- var overlayID = 'react-dev-utils-webpack-hot-dev-client-overlay-div' ;
62- var overlay =
63- iframe . contentDocument . getElementById ( overlayID ) ||
64- iframe . contentDocument . createElement ( 'div' ) ;
65- overlay . id = overlayID ;
66- overlay . style . position = 'fixed' ;
67- overlay . style . left = 0 ;
68- overlay . style . top = 0 ;
69- overlay . style . right = 0 ;
70- overlay . style . bottom = 0 ;
71- overlay . style . width = '100vw' ;
72- overlay . style . height = '100vh' ;
73- overlay . style . backgroundColor = 'black' ;
74- overlay . style . color = '#E8E8E8' ;
75- overlay . style . fontFamily = 'Menlo, Consolas, monospace' ;
76- overlay . style . fontSize = 'large' ;
77- overlay . style . padding = '2rem' ;
78- overlay . style . lineHeight = '1.2' ;
79- overlay . style . whiteSpace = 'pre-wrap' ;
80- overlay . style . overflow = 'auto' ;
81-
82- // Make it look similar to our terminal.
83- overlay . innerHTML =
84- '<span style="color: #' +
85- colors . red +
86- '">Failed to compile.</span><br><br>' +
87- ansiHTML ( entities . encode ( message ) ) ;
88-
89- // Render!
90- iframe . contentDocument . body . appendChild ( overlay ) ;
55+ iframe . onload = onIframeLoad ;
56+ return iframe ;
57+ }
58+
59+ function addOverlayDivTo ( iframe ) {
60+ var div = iframe . contentDocument . createElement ( 'div' ) ;
61+ div . id = 'react-dev-utils-webpack-hot-dev-client-overlay-div' ;
62+ div . style . position = 'fixed' ;
63+ div . style . left = 0 ;
64+ div . style . top = 0 ;
65+ div . style . right = 0 ;
66+ div . style . bottom = 0 ;
67+ div . style . width = '100vw' ;
68+ div . style . height = '100vh' ;
69+ div . style . backgroundColor = 'black' ;
70+ div . style . color = '#E8E8E8' ;
71+ div . style . fontFamily = 'Menlo, Consolas, monospace' ;
72+ div . style . fontSize = 'large' ;
73+ div . style . padding = '2rem' ;
74+ div . style . lineHeight = '1.2' ;
75+ div . style . whiteSpace = 'pre-wrap' ;
76+ div . style . overflow = 'auto' ;
77+ iframe . contentDocument . body . appendChild ( div ) ;
78+ return div ;
79+ }
80+
81+ var overlayIframe = null ;
82+ var overlayDiv = null ;
83+ var lastOnOverlayDivReady = null ;
84+
85+ function ensureOverlayDivExists ( onOverlayDivReady ) {
86+ if ( overlayDiv ) {
87+ // Everything is ready, call the callback right away.
88+ onOverlayDivReady ( overlayDiv ) ;
89+ return ;
90+ }
91+
92+ // Creating an iframe may be asynchronous so we'll schedule the callback.
93+ // In case of multiple calls, last callback wins.
94+ lastOnOverlayDivReady = onOverlayDivReady ;
95+
96+ if ( overlayIframe ) {
97+ // We're already creating it.
98+ return ;
99+ }
100+
101+ // Create iframe and, when it is ready, a div inside it.
102+ overlayIframe = createOverlayIframe ( function onIframeLoad ( ) {
103+ overlayDiv = addOverlayDivTo ( overlayIframe ) ;
104+ // Now we can talk!
105+ lastOnOverlayDivReady ( overlayDiv ) ;
106+ } ) ;
107+
108+ // Zalgo alert: onIframeLoad() will be called either synchronouly
109+ // or asynchronously depending on the browser.
110+ // We delay adding it so `overlayIframe` is set when `onIframeLoad` fires.
111+ document . body . appendChild ( overlayIframe ) ;
112+ }
113+
114+ function showErrorOverlay ( message ) {
115+ ensureOverlayDivExists ( function onOverlayDivReady ( overlayDiv ) {
116+ // Make it look similar to our terminal.
117+ overlayDiv . innerHTML =
118+ '<span style="color: #' +
119+ colors . red +
120+ '">Failed to compile.</span><br><br>' +
121+ ansiHTML ( entities . encode ( message ) ) ;
122+ } ) ;
91123}
92124
93125// Connect to WebpackDevServer via a socket.
@@ -105,11 +137,22 @@ var connection = new SockJS(url.format({
105137// Remember some state related to hot module replacement.
106138var isFirstCompilation = true ;
107139var mostRecentCompilationHash = null ;
140+ var hasCompileErrors = false ;
141+
142+ function clearOutdatedErrors ( ) {
143+ // Clean up outdated compile errors, if any.
144+ if ( hasCompileErrors && typeof console . clear === 'function' ) {
145+ console . clear ( ) ;
146+ }
147+ }
108148
109149// Successful compilation.
110150function handleSuccess ( ) {
151+ clearOutdatedErrors ( ) ;
152+
111153 var isHotUpdate = ! isFirstCompilation ;
112154 isFirstCompilation = false ;
155+ hasCompileErrors = false ;
113156
114157 // Attempt to apply hot updates or reload.
115158 if ( isHotUpdate ) {
@@ -119,8 +162,11 @@ function handleSuccess() {
119162
120163// Compilation with warnings (e.g. ESLint).
121164function handleWarnings ( warnings ) {
165+ clearOutdatedErrors ( ) ;
166+
122167 var isHotUpdate = ! isFirstCompilation ;
123168 isFirstCompilation = false ;
169+ hasCompileErrors = false ;
124170
125171 function printWarnings ( ) {
126172 // Print warnings to the console.
@@ -144,7 +190,10 @@ function handleWarnings(warnings) {
144190
145191// Compilation with errors (e.g. syntax error or missing modules).
146192function handleErrors ( errors ) {
193+ clearOutdatedErrors ( ) ;
194+
147195 isFirstCompilation = false ;
196+ hasCompileErrors = true ;
148197
149198 // "Massage" webpack messages.
150199 var formatted = formatWebpackMessages ( {
@@ -154,6 +203,12 @@ function handleErrors(errors) {
154203
155204 // Only show the first error.
156205 showErrorOverlay ( formatted . errors [ 0 ] ) ;
206+
207+ // Also log them to the console.
208+ for ( var i = 0 ; i < formatted . errors . length ; i ++ ) {
209+ console . error ( stripAnsi ( formatted . errors [ i ] ) ) ;
210+ }
211+
157212 // Do not attempt to reload now.
158213 // We will reload on next success instead.
159214}
0 commit comments