You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
3.0 KiB
JavaScript

"use strict";
const budo = require("budo");
const defaultValue = require("default-value");
const assureArray = require("assure-array");
const path = require("path");
const entities = require("entities");
const stacked = require("stacked");
const injectLRScript = require("inject-lr-script");
function createExpressMiddleware(app, fullBundlePath) {
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)
.set("content-type", "text/html")
.send(`<pre>${entities.escape(err.stack)}</pre>`);
} else {
next(err);
}
});
} else {
next();
}
});
return handler;
}
module.exports = function ({ options, staticPath, staticBasePath, entryPaths, host }) {
let middlewareList;
let fullBundlePath = (options.staticPrefix != null)
? path.join(options.staticPrefix, options.bundlePath)
: options.bundlePath;
if (options.middleware != null) {
middlewareList = assureArray(options.middleware).concat([
createExpressMiddleware(options.expressApp, fullBundlePath)
]);
} else {
middlewareList = [
createExpressMiddleware(options.expressApp, fullBundlePath)
];
}
let budoOptions = {
livePort: defaultValue(options.livereloadPort, 35729),
stream: defaultValue(options.stream, process.stdout),
port: options.port,
host: host,
dir: staticBasePath,
serve: fullBundlePath,
browserify: options.browserify,
middleware: middlewareList,
debug: defaultValue(options.sourceMaps, true),
verbose: true
};
let devServer = budo(entryPaths, budoOptions)
.watch(staticPath(options.livereloadPattern), {
awaitWriteFinish: {
// NOTE: This is mostly just a hack to make sure that the process has time to get restarted (by eg. nodemon) before sending out a LiveReload update. Need to investigate whether there's a less hacky way to do this.
stabilityThreshold: 130
}
})
.live()
.on("watch", (event, file) => {
if (event === "change" || event === "add") {
devServer.reload(file);
}
})
.on("pending", () => {
// This event is called when the bundle is being regenerated, ie. after watchify has detected a change in the input files
devServer.reload(fullBundlePath);
})
.on("connect", (event) => {
let reloadServer = event.webSocketServer;
reloadServer.once("connection", (_socket) => {
// This is to make sure the browser also reloads after the process has auto-restarted (eg. using `nodemon`)
console.log("Triggering initial page refresh for new client...");
devServer.reload("*");
});
});
};