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
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("*");
|
|
});
|
|
});
|
|
};
|