UNPKG

fuse-box

Version:

Fuse-Box a bundler that does it right

220 lines (203 loc) • 7.41 kB
/** * @module listens to `source-changed` socket events and actions hot reload */ import { SocketClient } from '../fusebox-websocket'; const Client: typeof SocketClient = require('fusebox-websocket').SocketClient, bundleErrors: { [bundleName: string]: string[] } = {}, outputElement: HTMLDivElement = document.createElement('div'), styleElement = document.createElement('style'), minimizeToggleId = 'fuse-box-toggle-minimized', hideButtonId = 'fuse-box-hide', expandedOutputClass = 'fuse-box-expanded-output', localStoragePrefix = '__fuse-box_' function storeSetting (key: string, value: boolean) { localStorage[localStoragePrefix + key] = value } function getSetting (key: string) { return localStorage[localStoragePrefix + key] === 'true' ? true : false } let outputInBody = false, outputMinimized = getSetting(minimizeToggleId), outputHidden = false outputElement.id = 'fuse-box-output' styleElement.innerHTML = ` #${outputElement.id}, #${outputElement.id} * { box-sizing: border-box; } #${outputElement.id} { z-index: 999999999999; position: fixed; top: 10px; right: 10px; width: 400px; overflow: auto; background: #fdf3f1; border: 1px solid #eca494; border-radius: 5px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; box-shadow: 0px 3px 6px 1px rgba(0,0,0,.15); } #${outputElement.id}.${expandedOutputClass} { height: auto; width: auto; left: 10px; max-height: calc(100vh - 50px); } #${outputElement.id} .fuse-box-errors { display: none; } #${outputElement.id}.${expandedOutputClass} .fuse-box-errors { display: block; border-top: 1px solid #eca494; padding: 0 10px; } #${outputElement.id} button { border: 1px solid #eca494; padding: 5px 10px; border-radius: 4px; margin-left: 5px; background-color: white; color: black; box-shadow: 0px 2px 2px 0px rgba(0,0,0,.05); } #${outputElement.id} .fuse-box-header { padding: 10px; } #${outputElement.id} .fuse-box-header h4 { display: inline-block; margin: 4px; }` styleElement.type = 'text/css' document.getElementsByTagName('head')[0].appendChild(styleElement) function displayBundleErrors() { const errorMessages = Object.keys(bundleErrors).reduce((allMessages, bundleName) => { const bundleMessages = bundleErrors[bundleName] return allMessages.concat(bundleMessages.map(message => { const messageOutput = message .replace(/\n/g, '<br>') .replace(/\t/g, '&nbsp;&nbps;&npbs;&nbps;') .replace(/ /g, '&nbsp;') return `<pre>${messageOutput}</pre>` })) }, []), errorOutput = errorMessages.join('') if (errorOutput && !outputHidden) { outputElement.innerHTML = ` <div class="fuse-box-header" style=""> <h4 style="">Fuse Box Bundle Errors (${errorMessages.length}):</h4> <div style="float: right;"> <button id="${minimizeToggleId}">${outputMinimized ? 'Expand' : 'Minimize'}</button> <button id="${hideButtonId}">Hide</button> </div> </div> <div class="fuse-box-errors"> ${errorOutput} </div> ` document.body.appendChild(outputElement) outputElement.className = outputMinimized ? '' : expandedOutputClass outputInBody = true document.getElementById(minimizeToggleId).onclick = () => { outputMinimized = !outputMinimized storeSetting(minimizeToggleId, outputMinimized) displayBundleErrors() } document.getElementById(hideButtonId).onclick = () => { outputHidden = true displayBundleErrors() } } else if (outputInBody) { document.body.removeChild(outputElement) outputInBody = false } } export const connect = (port: string, uri: string, reloadFullPage : boolean) => { if (FuseBox.isServer) { return; } port = port || window.location.port; let client = new Client({ port, uri, }); client.connect(); client.on('page-reload', (data) => { return window.location.reload(); }); client.on('page-hmr', (data) => { FuseBox.flush(); FuseBox.dynamic(data.path, data.content); if (FuseBox.mainFile) { try { FuseBox.import(FuseBox.mainFile); } catch (e) { if (typeof e === 'string') { if (/not found/.test(e)) { return window.location.reload(); } } console.error(e); } } }); client.on('source-changed', (data) => { console.info(`%cupdate "${data.path}"`, 'color: #237abe'); if(reloadFullPage){ return window.location.reload(); } /** * If a plugin handles this request then we don't have to do anything **/ for (var index = 0; index < FuseBox.plugins.length; index++) { var plugin = FuseBox.plugins[index]; if (plugin.hmrUpdate && plugin.hmrUpdate(data)) { return; } } if (data.type === "hosted-css") { var fileId = data.path.replace(/^\//, '').replace(/[\.\/]+/g, '-'); var existing = document.getElementById(fileId); if (existing) { existing.setAttribute("href", data.path + "?" + new Date().getTime()); } else { var node = document.createElement('link'); node.id = fileId; node.type = 'text/css'; node.rel = 'stylesheet'; node.href = data.path; document.getElementsByTagName('head')[0].appendChild(node); } } if (data.type === 'js' || data.type === "css") { FuseBox.flush(); FuseBox.dynamic(data.path, data.content); if (FuseBox.mainFile) { try { FuseBox.import(FuseBox.mainFile); } catch (e) { if (typeof e === 'string') { if (/not found/.test(e)) { return window.location.reload(); } } console.error(e); } } } }); client.on('error', (error) => { console.log(error); }); client.on('bundle-error', ({ bundleName, message }: { bundleName: string, message: string }) => { console.error(`Bundle error in ${bundleName}: ${message}`) const errorsForBundle = bundleErrors[bundleName] || [] errorsForBundle.push(message) bundleErrors[bundleName] = errorsForBundle displayBundleErrors() }) client.on('update-bundle-errors', ({ bundleName, messages }: { bundleName: string, messages: string[] }) => { messages.forEach(message => console.error(`Bundle error in ${bundleName}: ${message}`)) bundleErrors[bundleName] = messages displayBundleErrors() }) };