1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
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 |
|
14 |
|
15 | if (document.currentScript) {
|
16 | return document.currentScript.getAttribute('src');
|
17 | }
|
18 |
|
19 | var scriptElements = document.scripts || [];
|
20 | var currentScript = scriptElements[scriptElements.length - 1];
|
21 | if (currentScript) {
|
22 | return currentScript.getAttribute('src');
|
23 | }
|
24 |
|
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 |
|
36 | urlParts = url.parse(__resourceQuery.substr(1));
|
37 | } else {
|
38 |
|
39 | var scriptHost = getCurrentScriptSource();
|
40 |
|
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 |
|
62 | log.setDefaultLevel(INFO);
|
63 |
|
64 |
|
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 |
|
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 |
|
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;
|
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;
|
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 |
|
185 | if (hostname === '0.0.0.0' || hostname === '::') {
|
186 |
|
187 |
|
188 |
|
189 |
|
190 | if (self.location.hostname && !!~self.location.protocol.indexOf('http')) {
|
191 | hostname = self.location.hostname;
|
192 | }
|
193 | }
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
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 |
|
225 | var hotEmitter = require('webpack/hot/emitter');
|
226 | hotEmitter.emit('webpackHotUpdate', currentHash);
|
227 | if (typeof self !== 'undefined' && self.window) {
|
228 |
|
229 | self.postMessage('webpackHotUpdate' + currentHash, '*');
|
230 | }
|
231 | } else {
|
232 | var rootWindow = self;
|
233 |
|
234 | var intervalId = self.setInterval(function () {
|
235 | if (rootWindow.location.protocol !== 'about:') {
|
236 |
|
237 | applyReload(rootWindow, intervalId);
|
238 | } else {
|
239 | rootWindow = rootWindow.parent;
|
240 | if (rootWindow.parent === rootWindow) {
|
241 |
|
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 | } |
\ | No newline at end of file |