Use inject-lr-script instead of custom monkypatching for livereload injection

master
Sven Slootweg 4 years ago
parent 640b0aeaa5
commit be4cb973b4

@ -5,75 +5,23 @@ const defaultValue = require("default-value");
const assureArray = require("assure-array");
const path = require("path");
const entities = require("entities");
const util = require("util");
let reloadClientTag = Buffer.from("<script src=\"/budo/livereload.js\"></script>");
function monkeyPatchEnd(res) {
// NOTE: This is a hack, to auto-inject the Budo livereload client in any outgoing HTML response (but only in development mode).
let end = res.end.bind(res);
res.end = function monkeyPatchedEnd(... args) {
let originalChunk = args[0];
let prefix;
if (originalChunk == null || typeof originalChunk === "string" || Buffer.isBuffer(originalChunk)) {
if (!res.headersSent) {
// If headers have already been sent, we'll just have to hope that the browser will still look at our appended tag, as we can't change the response size anymore...
// TODO: Make this more robust in the future
let typeHeader = res.getHeader("content-type");
if (typeHeader != null && typeHeader.startsWith("text/html")) {
let contentLength = res.getHeader("content-length");
if (contentLength != null) {
// Compensate for the additional bytes introduced by our injected script tag
res.setHeader("content-length", parseInt(contentLength) + reloadClientTag.length);
}
prefix = reloadClientTag;
}
}
// Reset the `end` method back to the original method; we don't need to get in the way anymore
res.end = end;
let originalChunkAsBuffer = (typeof originalChunk === "string")
? Buffer.from(originalChunk)
: originalChunk;
if (prefix != null) {
let chunk = (originalChunkAsBuffer == null)
? reloadClientTag
: Buffer.concat([ originalChunkAsBuffer, reloadClientTag ]);
end(chunk, ... args.slice(1));
} else {
end(... args);
}
} else {
throw new Error(`Expected a buffer or string in 'end', but got something else: ${util.inspect(args[0])}`);
}
};
}
const stacked = require("stacked");
const injectLRScript = require("inject-lr-script");
function createExpressMiddleware(app, fullBundlePath) {
return function expressMiddleware(req, res, next) {
try {
monkeyPatchEnd(res);
} catch (error) {
process.nextTick(() => {
throw error;
});
}
let handler = stacked();
handler.use(injectLRScript({ local: true, path: "/budo/livereload.js" }));
handler.use((req, res, next) => {
// Ensure that we never intercept budo-served resources. Otherwise, the Express app might have something like a 404 handler or "always require login" middleware that stops requests for budo assets from ever coming out the other end of the Express app.
if (req.url !== "/budo/livereload.js" && req.url !== `/${fullBundlePath}`) {
app.handle(req, res, (err) => {
if (err != null && err instanceof Error) {
res
.status(500)
.send(`${reloadClientTag}<pre>${entities.escape(err.stack)}</pre>`);
.set("content-type", "text/html")
.send(`<pre>${entities.escape(err.stack)}</pre>`);
} else {
next(err);
}
@ -81,7 +29,7 @@ function createExpressMiddleware(app, fullBundlePath) {
} else {
next();
}
};
});
}
module.exports = function ({ options, staticPath, staticBasePath, entryPaths, host }) {

@ -17,7 +17,9 @@
"chalk": "^3.0.0",
"default-value": "^1.0.0",
"entities": "^2.0.0",
"inject-lr-script": "^2.2.0",
"is-stream": "^2.0.0",
"stacked": "^1.1.1",
"validatem": "^0.2.0"
},
"devDependencies": {

@ -1492,7 +1492,7 @@ inherits@2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
inject-lr-script@^2.1.0:
inject-lr-script@^2.1.0, inject-lr-script@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/inject-lr-script/-/inject-lr-script-2.2.0.tgz#58d91cd99e5de1a3f172aa076f7db8651ee72db2"
integrity sha512-lFLjCOg2XP8233AiET5vFePo910vhNIkKHDzUptNhc+4Y7dsp/TNBiusUUpaxzaGd6UDHy0Lozfl9AwmteK6DQ==

Loading…
Cancel
Save