Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 57 additions & 18 deletions lib/dev-middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ let chokidar = require('chokidar');
let expressws = require('express-ws');
let fs = require('fs');
let url = require('url');
let crypto = require('crypto');

const MIME_TYPES = {
'mjs': 'application/javascript',
Expand All @@ -13,6 +14,7 @@ const MIME_TYPES = {
module.exports = function (app, config, options) {
expressws(app);
let files = {};
const fileHashes = {};
let sockets = [];

if (options.hot) {
Expand Down Expand Up @@ -105,28 +107,65 @@ module.exports = function (app, config, options) {
console.log('\x1b[32m%s\x1b[0m', `Compiled in ${response.stats.time}ms.`);
}

async function compiler () {
let bundle = await nollup(config);
let watcher = chokidar.watch(options.watch);
let watcherTimeout;
function debounceLeadingAndTrailing(func, wait) {
let timeout;
let needsCalling = false;

return function executedFunction() {
let context = this;
let args = arguments;

let later = function() {
timeout = null;
if (needsCalling) {
func.apply(context, args)
needsCalling = false;
};
};

let callNow = !timeout;

clearTimeout(timeout);

timeout = setTimeout(later, wait);

if (callNow) {
func.apply(context, args)
} else {
needsCalling = true;
}
};
};

const onChange = async (path) => {
if (fs.lstatSync(path).isFile()) {
files = {};
bundle.invalidate(path);
const onChange = async (path, bundle) => {
if (fs.lstatSync(path).isFile()) {
// read out the file and generate a hash
const file = fs.readFileSync(path);
const hash = crypto.createHash('md5').update(file).digest("hex");

// if the hash is the same as it was last time, bail and don't recompile
if (fileHashes[path] === hash) {
return
}

if (watcherTimeout) {
clearTimeout(watcherTimeout);
}
// set the hash so that next time we can bail early
fileHashes[path] = hash;

files = {};
bundle.invalidate(path);

watcherTimeout = setTimeout(async () => {
handleGeneratedBundle(await bundle.generate());
}, 100);
}
};
handleGeneratedBundle(await bundle.generate());
}
};

async function compiler () {
let bundle = await nollup(config);
let watcher = chokidar.watch(options.watch, { ignoreInitial: true });

const debouncedOnChange = debounceLeadingAndTrailing(path => onChange(path, bundle), 300);

watcher.on('add', onChange);
watcher.on('change', onChange);
watcher.on('add', debouncedOnChange);
watcher.on('change', debouncedOnChange);

handleGeneratedBundle(await bundle.generate());
};
Expand Down