UNPKG

j-gallery

Version:
205 lines (188 loc) 5.83 kB
/* global __resourceQuery WorkerGlobalScope */ var url = require("url"); var stripAnsi = require("strip-ansi"); var log = require("loglevel") 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; 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(); scriptHost = scriptHost.replace(/\/[^\/]+$/, ""); urlParts = url.parse((scriptHost ? scriptHost : "/"), false, true); } var hot = false; var initial = true; var currentHash = ""; var useWarningOverlay = false; var useErrorOverlay = false; var INFO = "info"; var WARNING = "warning"; var ERROR = "error"; 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" + type, data: data }, "*"); } } var onSocketMsg = { hot: function() { hot = true; log.info("[WDS] Hot Module Replacement enabled."); }, invalid: function() { log.info("[WDS] App updated. Recompiling..."); sendMsg("Invalid"); }, hash: function(hash) { currentHash = hash; }, "still-ok": function() { log.info("[WDS] Nothing changed.") if(useWarningOverlay || useErrorOverlay) overlay.clear(); sendMsg("StillOk"); }, "log-level": function(level) { var hotCtx = require.context("webpack/hot", false, /^\.\/log$/); if(hotCtx.keys().length > 0) { hotCtx("./log").setLogLevel(level); } switch(level) { case INFO: case ERROR: log.setLevel(level); break; case WARNING: log.setLevel("warn"); // loglevel's warning name is different from webpack's break; case NONE: log.disableAll(); break; default: log.error("[WDS] Unknown clientLogLevel '" + level + "'"); } }, "overlay": function(overlay) { if(typeof document !== "undefined") { if(typeof(overlay) === "boolean") { useWarningOverlay = false; useErrorOverlay = overlay; } else if(overlay) { useWarningOverlay = overlay.warnings; useErrorOverlay = overlay.errors; } } }, ok: function() { sendMsg("Ok"); if(useWarningOverlay || useErrorOverlay) overlay.clear(); if(initial) return initial = false; reloadApp(); }, "content-changed": function() { log.info("[WDS] Content base changed. Reloading...") self.location.reload(); }, warnings: function(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; reloadApp(); }, errors: function(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); }, error: function(error) { log.error(error); }, close: function() { 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 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; } var socketUrl = url.format({ protocol: protocol, auth: urlParts.auth, hostname: hostname, port: (urlParts.port === "0") ? self.location.port : urlParts.port, pathname: urlParts.path == null || urlParts.path === "/" ? "/sockjs-node" : urlParts.path }); socket(socketUrl, onSocketMsg); var isUnloading = false; self.addEventListener("beforeunload", function() { isUnloading = true; }); function reloadApp() { if(isUnloading) { return; } if(hot) { log.info("[WDS] App hot update..."); var hotEmitter = require("webpack/hot/emitter"); hotEmitter.emit("webpackHotUpdate", currentHash); if(typeof self !== "undefined" && self.window) { // broadcast update to window self.postMessage("webpackHotUpdate" + currentHash, "*"); } } else { log.info("[WDS] App updated. Reloading..."); self.location.reload(); } }