Files
w4rpservices/node_modules/webpack-dev-server/client/index.js
2019-05-20 20:43:45 -05:00

337 lines
9.3 KiB
JavaScript
Vendored

'use strict';
/* global __resourceQuery WorkerGlobalScope self */
/* eslint prefer-destructuring: off */
var querystring = require('querystring');
var url = require('url');
var stripAnsi = require('strip-ansi');
var log = require('loglevel').getLogger('webpack-dev-server');
var socket = require('./socket');
var overlay = require('./overlay');
function getCurrentScriptSource() {
// `document.currentScript` is the most accurate way to find the current script,
// but is not supported in all browsers.
if (document.currentScript) {
return document.currentScript.getAttribute('src');
} // Fall back to getting all scripts in the document.
var scriptElements = document.scripts || [];
var currentScript = scriptElements[scriptElements.length - 1];
if (currentScript) {
return currentScript.getAttribute('src');
} // Fail as there was no script to use.
throw new Error('[WDS] Failed to get current script source.');
}
var urlParts;
var hotReload = true;
if (typeof window !== 'undefined') {
var qs = window.location.search.toLowerCase();
hotReload = qs.indexOf('hotreload=false') === -1;
}
if (typeof __resourceQuery === 'string' && __resourceQuery) {
// If this bundle is inlined, use the resource query to get the correct url.
urlParts = url.parse(__resourceQuery.substr(1));
} else {
// Else, get the url from the <script> this file was called with.
var scriptHost = getCurrentScriptSource(); // eslint-disable-next-line no-useless-escape
scriptHost = scriptHost.replace(/\/[^\/]+$/, '');
urlParts = url.parse(scriptHost || '/', false, true);
}
if (!urlParts.port || urlParts.port === '0') {
urlParts.port = self.location.port;
}
var _hot = false;
var _liveReload = false;
var initial = true;
var currentHash = '';
var useWarningOverlay = false;
var useErrorOverlay = false;
var useProgress = false;
var INFO = 'info';
var WARN = 'warn';
var ERROR = 'error';
var DEBUG = 'debug';
var TRACE = 'trace';
var SILENT = 'silent'; // deprecated
// TODO: remove these at major released
// https://github.com/webpack/webpack-dev-server/pull/1825
var WARNING = 'warning';
var NONE = 'none'; // Set the default log level
log.setDefaultLevel(INFO); // Send messages to the outside, so plugins can consume it.
function sendMsg(type, data) {
if (typeof self !== 'undefined' && (typeof WorkerGlobalScope === 'undefined' || !(self instanceof WorkerGlobalScope))) {
self.postMessage({
type: "webpack".concat(type),
data: data
}, '*');
}
}
var onSocketMsg = {
hot: function hot() {
_hot = true;
log.info('[WDS] Hot Module Replacement enabled.');
},
liveReload: function liveReload() {
_liveReload = true;
log.info('[WDS] Live Reloading enabled.');
},
invalid: function invalid() {
log.info('[WDS] App updated. Recompiling...'); // fixes #1042. overlay doesn't clear if errors are fixed but warnings remain.
if (useWarningOverlay || useErrorOverlay) {
overlay.clear();
}
sendMsg('Invalid');
},
hash: function hash(_hash) {
currentHash = _hash;
},
'still-ok': function stillOk() {
log.info('[WDS] Nothing changed.');
if (useWarningOverlay || useErrorOverlay) {
overlay.clear();
}
sendMsg('StillOk');
},
'log-level': function logLevel(level) {
var hotCtx = require.context('webpack/hot', false, /^\.\/log$/);
if (hotCtx.keys().indexOf('./log') !== -1) {
hotCtx('./log').setLogLevel(level);
}
switch (level) {
case INFO:
case WARN:
case DEBUG:
case TRACE:
case ERROR:
log.setLevel(level);
break;
// deprecated
case WARNING:
// loglevel's warning name is different from webpack's
log.setLevel('warn');
break;
// deprecated
case NONE:
case SILENT:
log.disableAll();
break;
default:
log.error("[WDS] Unknown clientLogLevel '".concat(level, "'"));
}
},
overlay: function overlay(value) {
if (typeof document !== 'undefined') {
if (typeof value === 'boolean') {
useWarningOverlay = false;
useErrorOverlay = value;
} else if (value) {
useWarningOverlay = value.warnings;
useErrorOverlay = value.errors;
}
}
},
progress: function progress(_progress) {
if (typeof document !== 'undefined') {
useProgress = _progress;
}
},
'progress-update': function progressUpdate(data) {
if (useProgress) {
log.info("[WDS] ".concat(data.percent, "% - ").concat(data.msg, "."));
}
sendMsg('Progress', data);
},
ok: function ok() {
sendMsg('Ok');
if (useWarningOverlay || useErrorOverlay) {
overlay.clear();
}
if (initial) {
return initial = false;
} // eslint-disable-line no-return-assign
reloadApp();
},
'content-changed': function contentChanged() {
log.info('[WDS] Content base changed. Reloading...');
self.location.reload();
},
warnings: function warnings(_warnings) {
log.warn('[WDS] Warnings while compiling.');
var strippedWarnings = _warnings.map(function (warning) {
return stripAnsi(warning);
});
sendMsg('Warnings', strippedWarnings);
for (var i = 0; i < strippedWarnings.length; i++) {
log.warn(strippedWarnings[i]);
}
if (useWarningOverlay) {
overlay.showMessage(_warnings);
}
if (initial) {
return initial = false;
} // eslint-disable-line no-return-assign
reloadApp();
},
errors: function errors(_errors) {
log.error('[WDS] Errors while compiling. Reload prevented.');
var strippedErrors = _errors.map(function (error) {
return stripAnsi(error);
});
sendMsg('Errors', strippedErrors);
for (var i = 0; i < strippedErrors.length; i++) {
log.error(strippedErrors[i]);
}
if (useErrorOverlay) {
overlay.showMessage(_errors);
}
initial = false;
},
error: function error(_error) {
log.error(_error);
},
close: function close() {
log.error('[WDS] Disconnected!');
sendMsg('Close');
}
};
var hostname = urlParts.hostname;
var protocol = urlParts.protocol; // check ipv4 and ipv6 `all hostname`
if (hostname === '0.0.0.0' || hostname === '::') {
// why do we need this check?
// hostname n/a for file protocol (example, when using electron, ionic)
// see: https://github.com/webpack/webpack-dev-server/pull/384
// eslint-disable-next-line no-bitwise
if (self.location.hostname && !!~self.location.protocol.indexOf('http')) {
hostname = self.location.hostname;
}
} // `hostname` can be empty when the script path is relative. In that case, specifying
// a protocol would result in an invalid URL.
// When https is used in the app, secure websockets are always necessary
// because the browser doesn't accept non-secure websockets.
if (hostname && (self.location.protocol === 'https:' || urlParts.hostname === '0.0.0.0')) {
protocol = self.location.protocol;
} // default values of the sock url if they are not provided
var sockHost = hostname;
var sockPath = '/sockjs-node';
var sockPort = urlParts.port;
if (urlParts.path !== null && // eslint-disable-next-line no-undefined
urlParts.path !== undefined && urlParts.path !== '/') {
var parsedQuery = querystring.parse(urlParts.path); // all of these sock url params are optionally passed in through
// __resourceQuery, so we need to fall back to the default if
// they are not provided
sockHost = parsedQuery.sockHost || sockHost;
sockPath = parsedQuery.sockPath || sockPath;
sockPort = parsedQuery.sockPort || sockPort;
}
var socketUrl = url.format({
protocol: protocol,
auth: urlParts.auth,
hostname: sockHost,
port: sockPort,
// If sockPath is provided it'll be passed in via the __resourceQuery as a
// query param so it has to be parsed out of the querystring in order for the
// client to open the socket to the correct location.
pathname: sockPath
});
socket(socketUrl, onSocketMsg);
var isUnloading = false;
self.addEventListener('beforeunload', function () {
isUnloading = true;
});
function reloadApp() {
if (isUnloading || !hotReload) {
return;
}
if (_hot) {
log.info('[WDS] App hot update...'); // eslint-disable-next-line global-require
var hotEmitter = require('webpack/hot/emitter');
hotEmitter.emit('webpackHotUpdate', currentHash);
if (typeof self !== 'undefined' && self.window) {
// broadcast update to window
self.postMessage("webpackHotUpdate".concat(currentHash), '*');
}
} // allow refreshing the page only if liveReload isn't disabled
else if (_liveReload) {
var rootWindow = self; // use parent window for reload (in case we're in an iframe with no valid src)
var intervalId = self.setInterval(function () {
if (rootWindow.location.protocol !== 'about:') {
// reload immediately if protocol is valid
applyReload(rootWindow, intervalId);
} else {
rootWindow = rootWindow.parent;
if (rootWindow.parent === rootWindow) {
// if parent equals current window we've reached the root which would continue forever, so trigger a reload anyways
applyReload(rootWindow, intervalId);
}
}
});
}
function applyReload(rootWindow, intervalId) {
clearInterval(intervalId);
log.info('[WDS] App updated. Reloading...');
rootWindow.location.reload();
}
}