Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): add liveReload option to enable/disable live reloading #1889

Merged
merged 9 commits into from May 16, 2019
5 changes: 5 additions & 0 deletions bin/options.js
Expand Up @@ -21,6 +21,11 @@ const options = {
type: 'boolean',
describe: 'Lazy',
},
liveReload: {
type: 'boolean',
describe: 'Enables/Disables live reloading on changing files',
default: true,
},
serveIndex: {
type: 'boolean',
describe: 'Enables/Disables serveIndex middleware',
Expand Down
9 changes: 8 additions & 1 deletion client-src/default/index.js
Expand Up @@ -47,6 +47,7 @@ if (!urlParts.port || urlParts.port === '0') {
}

let hot = false;
let liveReload = false;
let initial = true;
let currentHash = '';
let useWarningOverlay = false;
Expand Down Expand Up @@ -85,6 +86,10 @@ const onSocketMsg = {
hot = true;
log.info('[WDS] Hot Module Replacement enabled.');
},
liveReload() {
liveReload = true;
log.info('[WDS] Live Reloading enabled.');
},
invalid() {
log.info('[WDS] App updated. Recompiling...');
// fixes #1042. overlay doesn't clear if errors are fixed but warnings remain.
Expand Down Expand Up @@ -271,7 +276,9 @@ function reloadApp() {
// broadcast update to window
self.postMessage(`webpackHotUpdate${currentHash}`, '*');
}
} else {
}
// allow refreshing the page only if liveReload isn't disabled
if (liveReload) {
let rootWindow = self;
// use parent window for reload (in case we're in an iframe with no valid src)
const intervalId = self.setInterval(() => {
Expand Down
15 changes: 10 additions & 5 deletions lib/Server.js
Expand Up @@ -717,6 +717,10 @@ class Server {
this.sockWrite([connection], 'hot');
}

if (this.options.liveReload !== false) {
this.sockWrite([connection], 'liveReload', this.options.liveReload);
}

if (this.progress) {
this.sockWrite([connection], 'progress', this.progress);
}
Expand Down Expand Up @@ -997,11 +1001,12 @@ class Server {
};

const watcher = chokidar.watch(watchPath, watchOptions);

watcher.on('change', () => {
this.sockWrite(this.sockets, 'content-changed');
});

// disabling refreshing on changing the content
if (this.options.liveReload !== false) {
watcher.on('change', () => {
this.sockWrite(this.sockets, 'content-changed');
});
}
this.contentBaseWatchers.push(watcher);
}

Expand Down
4 changes: 4 additions & 0 deletions lib/options.json
Expand Up @@ -168,6 +168,9 @@
"lazy": {
"type": "boolean"
},
"liveReload": {
"type": "boolean"
},
"log": {
"instanceof": "Function"
},
Expand Down Expand Up @@ -377,6 +380,7 @@
"inline": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverinline)",
"key": "should be {String|Buffer}",
"lazy": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverlazy-)",
"liveReload": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverlivereload-)",
"log": "should be {Function}",
"logLevel": "should be {String} and equal to one of the allowed values\n\n [ 'info', 'warn', 'error', 'debug', 'trace', 'silent' ]\n\n (https://github.com/webpack/webpack-dev-middleware#loglevel)",
"logTime": "should be {Boolean} (https://github.com/webpack/webpack-dev-middleware#logtime)",
Expand Down
4 changes: 4 additions & 0 deletions lib/utils/createConfig.js
Expand Up @@ -42,6 +42,10 @@ function createConfig(config, argv, { port }) {
options.sockPort = argv.sockPort;
}

if (argv.liveReload === false) {
options.liveReload = false;
}

if (argv.progress) {
options.progress = argv.progress;
}
Expand Down
116 changes: 116 additions & 0 deletions test/LiveReload.test.js
@@ -0,0 +1,116 @@
'use strict';

const path = require('path');
const fs = require('fs');
const helper = require('./helper');
const config = require('./fixtures/contentbase-config/webpack.config');

const contentBasePublic = path.join(
__dirname,
'fixtures/contentbase-config/public'
);

describe('liveReload', () => {
let server;
describe('Test disabling live reloading', () => {
const nestedFile = path.join(contentBasePublic, 'assets/example.txt');

jest.setTimeout(30000);

beforeAll((done) => {
server = helper.start(
config,
{
contentBase: contentBasePublic,
watchContentBase: true,
liveReload: false,
},
done
);
});

afterAll((done) => {
helper.close(() => {
done();
});
fs.truncateSync(nestedFile);
});

it('Should not reload on changing files', (done) => {
let reloaded = false;

server.contentBaseWatchers[0].on('change', () => {
// it means that file has changed

// simulating server behaviour
if (server.options.liveReload !== false) {
Object.defineProperty(window.location, 'reload', {
configurable: true,
});
window.location.reload = jest.fn();
window.location.reload();
reloaded = true;
}
expect(reloaded).toBe(false);

done();
});

// change file content
setTimeout(() => {
fs.writeFileSync(nestedFile, 'Heyo', 'utf8');
}, 1000);
});
});

describe('Testing live reloading', () => {
const nestedFile = path.join(contentBasePublic, 'assets/example.txt');

jest.setTimeout(30000);

beforeAll((done) => {
server = helper.start(
config,
{
contentBase: contentBasePublic,
watchContentBase: true,
liveReload: true,
},
done
);
});

afterAll((done) => {
helper.close(() => {
done();
});
fs.truncateSync(nestedFile);
});

it('Should reload on changing files', (done) => {
let reloaded = false;

server.contentBaseWatchers[0].on('change', () => {
// it means that files has changed

// simulating server behaviour
if (server.options.liveReload !== false) {
Object.defineProperty(window.location, 'reload', {
configurable: true,
});
window.location.reload = jest.fn();
window.location.reload();
reloaded = true;
}
expect(reloaded).toBe(true);

done();
});

// change file content
setTimeout(() => {
fs.writeFileSync(nestedFile, 'Heyo', 'utf8');
}, 1000);
});
});
});
2 changes: 1 addition & 1 deletion test/__snapshots__/Routes.test.js.snap

Large diffs are not rendered by default.