Skip to content

Commit 5757663

Browse files
author
Rohan Bhanderi
committed
Add built client
Add transpiled client from client-src so that git+https or github: remote works while installing package.
1 parent 7cdfb74 commit 5757663

File tree

9 files changed

+454
-2
lines changed

9 files changed

+454
-2
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
npm-debug.log
22
node_modules
3-
/client
43
/coverage
54
/ssl/*.pem
65
.idea/

client/index.bundle.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/index.js

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
'use strict';
2+
3+
/* global __resourceQuery WorkerGlobalScope self */
4+
/* eslint prefer-destructuring: off */
5+
6+
var url = require('url');
7+
var stripAnsi = require('strip-ansi');
8+
var log = require('loglevel').getLogger('webpack-dev-server');
9+
var socket = require('./socket');
10+
var overlay = require('./overlay');
11+
12+
function getCurrentScriptSource() {
13+
// `document.currentScript` is the most accurate way to find the current script,
14+
// but is not supported in all browsers.
15+
if (document.currentScript) {
16+
return document.currentScript.getAttribute('src');
17+
}
18+
// Fall back to getting all scripts in the document.
19+
var scriptElements = document.scripts || [];
20+
var currentScript = scriptElements[scriptElements.length - 1];
21+
if (currentScript) {
22+
return currentScript.getAttribute('src');
23+
}
24+
// Fail as there was no script to use.
25+
throw new Error('[WDS] Failed to get current script source.');
26+
}
27+
28+
var urlParts = void 0;
29+
var hotReload = true;
30+
if (typeof window !== 'undefined') {
31+
var qs = window.location.search.toLowerCase();
32+
hotReload = qs.indexOf('hotreload=false') === -1;
33+
}
34+
if (typeof __resourceQuery === 'string' && __resourceQuery) {
35+
// If this bundle is inlined, use the resource query to get the correct url.
36+
urlParts = url.parse(__resourceQuery.substr(1));
37+
} else {
38+
// Else, get the url from the <script> this file was called with.
39+
var scriptHost = getCurrentScriptSource();
40+
// eslint-disable-next-line no-useless-escape
41+
scriptHost = scriptHost.replace(/\/[^\/]+$/, '');
42+
urlParts = url.parse(scriptHost || '/', false, true);
43+
}
44+
45+
if (!urlParts.port || urlParts.port === '0') {
46+
urlParts.port = self.location.port;
47+
}
48+
49+
var _hot = false;
50+
var initial = true;
51+
var currentHash = '';
52+
var useWarningOverlay = false;
53+
var useErrorOverlay = false;
54+
var useProgress = false;
55+
56+
var INFO = 'info';
57+
var WARNING = 'warning';
58+
var ERROR = 'error';
59+
var NONE = 'none';
60+
61+
// Set the default log level
62+
log.setDefaultLevel(INFO);
63+
64+
// Send messages to the outside, so plugins can consume it.
65+
function sendMsg(type, data) {
66+
if (typeof self !== 'undefined' && (typeof WorkerGlobalScope === 'undefined' || !(self instanceof WorkerGlobalScope))) {
67+
self.postMessage({
68+
type: 'webpack' + type,
69+
data: data
70+
}, '*');
71+
}
72+
}
73+
74+
var onSocketMsg = {
75+
hot: function hot() {
76+
_hot = true;
77+
log.info('[WDS] Hot Module Replacement enabled.');
78+
},
79+
invalid: function invalid() {
80+
log.info('[WDS] App updated. Recompiling...');
81+
// fixes #1042. overlay doesn't clear if errors are fixed but warnings remain.
82+
if (useWarningOverlay || useErrorOverlay) overlay.clear();
83+
sendMsg('Invalid');
84+
},
85+
hash: function hash(_hash) {
86+
currentHash = _hash;
87+
},
88+
89+
'still-ok': function stillOk() {
90+
log.info('[WDS] Nothing changed.');
91+
if (useWarningOverlay || useErrorOverlay) overlay.clear();
92+
sendMsg('StillOk');
93+
},
94+
'log-level': function logLevel(level) {
95+
var hotCtx = require.context('webpack/hot', false, /^\.\/log$/);
96+
if (hotCtx.keys().indexOf('./log') !== -1) {
97+
hotCtx('./log').setLogLevel(level);
98+
}
99+
switch (level) {
100+
case INFO:
101+
case ERROR:
102+
log.setLevel(level);
103+
break;
104+
case WARNING:
105+
// loglevel's warning name is different from webpack's
106+
log.setLevel('warn');
107+
break;
108+
case NONE:
109+
log.disableAll();
110+
break;
111+
default:
112+
log.error('[WDS] Unknown clientLogLevel \'' + level + '\'');
113+
}
114+
},
115+
overlay: function overlay(value) {
116+
if (typeof document !== 'undefined') {
117+
if (typeof value === 'boolean') {
118+
useWarningOverlay = false;
119+
useErrorOverlay = value;
120+
} else if (value) {
121+
useWarningOverlay = value.warnings;
122+
useErrorOverlay = value.errors;
123+
}
124+
}
125+
},
126+
progress: function progress(_progress) {
127+
if (typeof document !== 'undefined') {
128+
useProgress = _progress;
129+
}
130+
},
131+
132+
'progress-update': function progressUpdate(data) {
133+
if (useProgress) log.info('[WDS] ' + data.percent + '% - ' + data.msg + '.');
134+
},
135+
ok: function ok() {
136+
sendMsg('Ok');
137+
if (useWarningOverlay || useErrorOverlay) overlay.clear();
138+
if (initial) return initial = false; // eslint-disable-line no-return-assign
139+
reloadApp();
140+
},
141+
142+
'content-changed': function contentChanged() {
143+
log.info('[WDS] Content base changed. Reloading...');
144+
self.location.reload();
145+
},
146+
warnings: function warnings(_warnings) {
147+
log.warn('[WDS] Warnings while compiling.');
148+
var strippedWarnings = _warnings.map(function (warning) {
149+
return stripAnsi(warning);
150+
});
151+
sendMsg('Warnings', strippedWarnings);
152+
for (var i = 0; i < strippedWarnings.length; i++) {
153+
log.warn(strippedWarnings[i]);
154+
}
155+
if (useWarningOverlay) overlay.showMessage(_warnings);
156+
157+
if (initial) return initial = false; // eslint-disable-line no-return-assign
158+
reloadApp();
159+
},
160+
errors: function errors(_errors) {
161+
log.error('[WDS] Errors while compiling. Reload prevented.');
162+
var strippedErrors = _errors.map(function (error) {
163+
return stripAnsi(error);
164+
});
165+
sendMsg('Errors', strippedErrors);
166+
for (var i = 0; i < strippedErrors.length; i++) {
167+
log.error(strippedErrors[i]);
168+
}
169+
if (useErrorOverlay) overlay.showMessage(_errors);
170+
initial = false;
171+
},
172+
error: function error(_error) {
173+
log.error(_error);
174+
},
175+
close: function close() {
176+
log.error('[WDS] Disconnected!');
177+
sendMsg('Close');
178+
}
179+
};
180+
181+
var hostname = urlParts.hostname;
182+
var protocol = urlParts.protocol;
183+
184+
// check ipv4 and ipv6 `all hostname`
185+
if (hostname === '0.0.0.0' || hostname === '::') {
186+
// why do we need this check?
187+
// hostname n/a for file protocol (example, when using electron, ionic)
188+
// see: https://github.com/webpack/webpack-dev-server/pull/384
189+
// eslint-disable-next-line no-bitwise
190+
if (self.location.hostname && !!~self.location.protocol.indexOf('http')) {
191+
hostname = self.location.hostname;
192+
}
193+
}
194+
195+
// `hostname` can be empty when the script path is relative. In that case, specifying
196+
// a protocol would result in an invalid URL.
197+
// When https is used in the app, secure websockets are always necessary
198+
// because the browser doesn't accept non-secure websockets.
199+
if (hostname && (self.location.protocol === 'https:' || urlParts.hostname === '0.0.0.0')) {
200+
protocol = self.location.protocol;
201+
}
202+
203+
var socketUrl = url.format({
204+
protocol: protocol,
205+
auth: urlParts.auth,
206+
hostname: hostname,
207+
port: urlParts.port,
208+
pathname: urlParts.path == null || urlParts.path === '/' ? '/sockjs-node' : urlParts.path
209+
});
210+
211+
socket(socketUrl, onSocketMsg);
212+
213+
var isUnloading = false;
214+
self.addEventListener('beforeunload', function () {
215+
isUnloading = true;
216+
});
217+
218+
function reloadApp() {
219+
if (isUnloading || !hotReload) {
220+
return;
221+
}
222+
if (_hot) {
223+
log.info('[WDS] App hot update...');
224+
// eslint-disable-next-line global-require
225+
var hotEmitter = require('webpack/hot/emitter');
226+
hotEmitter.emit('webpackHotUpdate', currentHash);
227+
if (typeof self !== 'undefined' && self.window) {
228+
// broadcast update to window
229+
self.postMessage('webpackHotUpdate' + currentHash, '*');
230+
}
231+
} else {
232+
var rootWindow = self;
233+
// use parent window for reload (in case we're in an iframe with no valid src)
234+
var intervalId = self.setInterval(function () {
235+
if (rootWindow.location.protocol !== 'about:') {
236+
// reload immediately if protocol is valid
237+
applyReload(rootWindow, intervalId);
238+
} else {
239+
rootWindow = rootWindow.parent;
240+
if (rootWindow.parent === rootWindow) {
241+
// if parent equals current window we've reached the root which would continue forever, so trigger a reload anyways
242+
applyReload(rootWindow, intervalId);
243+
}
244+
}
245+
});
246+
}
247+
248+
function applyReload(rootWindow, intervalId) {
249+
clearInterval(intervalId);
250+
log.info('[WDS] App updated. Reloading...');
251+
rootWindow.location.reload();
252+
}
253+
}

client/live.bundle.js

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/live.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta charset="utf-8"/><meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"/><script type="text/javascript" charset="utf-8" src="/__webpack_dev_server__/live.bundle.js"></script></head><body></body></html>

client/overlay.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
'use strict';
2+
3+
// The error overlay is inspired (and mostly copied) from Create React App (https://github.com/facebookincubator/create-react-app)
4+
// They, in turn, got inspired by webpack-hot-middleware (https://github.com/glenjamin/webpack-hot-middleware).
5+
6+
var ansiHTML = require('ansi-html');
7+
var Entities = require('html-entities').AllHtmlEntities;
8+
9+
var entities = new Entities();
10+
11+
var colors = {
12+
reset: ['transparent', 'transparent'],
13+
black: '181818',
14+
red: 'E36049',
15+
green: 'B3CB74',
16+
yellow: 'FFD080',
17+
blue: '7CAFC2',
18+
magenta: '7FACCA',
19+
cyan: 'C3C2EF',
20+
lightgrey: 'EBE7E3',
21+
darkgrey: '6D7891'
22+
};
23+
ansiHTML.setColors(colors);
24+
25+
function createOverlayIframe(onIframeLoad) {
26+
var iframe = document.createElement('iframe');
27+
iframe.id = 'webpack-dev-server-client-overlay';
28+
iframe.src = 'about:blank';
29+
iframe.style.position = 'fixed';
30+
iframe.style.left = 0;
31+
iframe.style.top = 0;
32+
iframe.style.right = 0;
33+
iframe.style.bottom = 0;
34+
iframe.style.width = '100vw';
35+
iframe.style.height = '100vh';
36+
iframe.style.border = 'none';
37+
iframe.style.zIndex = 9999999999;
38+
iframe.onload = onIframeLoad;
39+
return iframe;
40+
}
41+
42+
function addOverlayDivTo(iframe) {
43+
var div = iframe.contentDocument.createElement('div');
44+
div.id = 'webpack-dev-server-client-overlay-div';
45+
div.style.position = 'fixed';
46+
div.style.boxSizing = 'border-box';
47+
div.style.left = 0;
48+
div.style.top = 0;
49+
div.style.right = 0;
50+
div.style.bottom = 0;
51+
div.style.width = '100vw';
52+
div.style.height = '100vh';
53+
div.style.backgroundColor = 'rgba(0, 0, 0, 0.85)';
54+
div.style.color = '#E8E8E8';
55+
div.style.fontFamily = 'Menlo, Consolas, monospace';
56+
div.style.fontSize = 'large';
57+
div.style.padding = '2rem';
58+
div.style.lineHeight = '1.2';
59+
div.style.whiteSpace = 'pre-wrap';
60+
div.style.overflow = 'auto';
61+
iframe.contentDocument.body.appendChild(div);
62+
return div;
63+
}
64+
65+
var overlayIframe = null;
66+
var overlayDiv = null;
67+
var lastOnOverlayDivReady = null;
68+
69+
function ensureOverlayDivExists(onOverlayDivReady) {
70+
if (overlayDiv) {
71+
// Everything is ready, call the callback right away.
72+
onOverlayDivReady(overlayDiv);
73+
return;
74+
}
75+
76+
// Creating an iframe may be asynchronous so we'll schedule the callback.
77+
// In case of multiple calls, last callback wins.
78+
lastOnOverlayDivReady = onOverlayDivReady;
79+
80+
if (overlayIframe) {
81+
// We're already creating it.
82+
return;
83+
}
84+
85+
// Create iframe and, when it is ready, a div inside it.
86+
overlayIframe = createOverlayIframe(function () {
87+
overlayDiv = addOverlayDivTo(overlayIframe);
88+
// Now we can talk!
89+
lastOnOverlayDivReady(overlayDiv);
90+
});
91+
92+
// Zalgo alert: onIframeLoad() will be called either synchronously
93+
// or asynchronously depending on the browser.
94+
// We delay adding it so `overlayIframe` is set when `onIframeLoad` fires.
95+
document.body.appendChild(overlayIframe);
96+
}
97+
98+
function showMessageOverlay(message) {
99+
ensureOverlayDivExists(function (div) {
100+
// Make it look similar to our terminal.
101+
div.innerHTML = '<span style="color: #' + colors.red + '">Failed to compile.</span><br><br>' + ansiHTML(entities.encode(message));
102+
});
103+
}
104+
105+
function destroyErrorOverlay() {
106+
if (!overlayDiv) {
107+
// It is not there in the first place.
108+
return;
109+
}
110+
111+
// Clean up and reset internal state.
112+
document.body.removeChild(overlayIframe);
113+
overlayDiv = null;
114+
overlayIframe = null;
115+
lastOnOverlayDivReady = null;
116+
}
117+
118+
// Successful compilation.
119+
exports.clear = function handleSuccess() {
120+
destroyErrorOverlay();
121+
};
122+
123+
// Compilation with errors (e.g. syntax error or missing modules).
124+
exports.showMessage = function handleMessage(messages) {
125+
showMessageOverlay(messages[0]);
126+
};

0 commit comments

Comments
 (0)