Skip to content

Commit cadee8b

Browse files
EslamHikohiroppy
authored andcommitted
feat: add liveReload option to enable/disable refreshing the page
1 parent c535bb2 commit cadee8b

File tree

8 files changed

+188
-4
lines changed

8 files changed

+188
-4
lines changed

bin/options.js

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ const options = {
1717
type: 'boolean',
1818
describe: 'Broadcasts the server via ZeroConf networking on start',
1919
},
20+
liveReload: {
21+
type: 'boolean',
22+
describe: 'Enables/Disables live reloading on changing files',
23+
default: true,
24+
},
2025
lazy: {
2126
type: 'boolean',
2227
describe: 'Lazy',

client-src/default/index.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ if (!urlParts.port || urlParts.port === '0') {
4747
}
4848

4949
let hot = false;
50+
let liveReload = false;
5051
let initial = true;
5152
let currentHash = '';
5253
let useWarningOverlay = false;
@@ -85,6 +86,10 @@ const onSocketMsg = {
8586
hot = true;
8687
log.info('[WDS] Hot Module Replacement enabled.');
8788
},
89+
liveReload() {
90+
liveReload = true;
91+
log.info('[WDS] Live Reloading enabled.');
92+
},
8893
invalid() {
8994
log.info('[WDS] App updated. Recompiling...');
9095
// fixes #1042. overlay doesn't clear if errors are fixed but warnings remain.
@@ -271,7 +276,9 @@ function reloadApp() {
271276
// broadcast update to window
272277
self.postMessage(`webpackHotUpdate${currentHash}`, '*');
273278
}
274-
} else {
279+
}
280+
// allow refreshing the page only if liveReload isn't disabled
281+
if (liveReload) {
275282
let rootWindow = self;
276283
// use parent window for reload (in case we're in an iframe with no valid src)
277284
const intervalId = self.setInterval(() => {

lib/Server.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,10 @@ class Server {
869869
this.sockWrite([connection], 'progress', this.progress);
870870
}
871871

872+
if (this.options.liveReload !== false) {
873+
this.sockWrite([connection], 'liveReload', this.options.liveReload);
874+
}
875+
872876
if (this.clientOverlay) {
873877
this.sockWrite([connection], 'overlay', this.clientOverlay);
874878
}
@@ -997,9 +1001,12 @@ class Server {
9971001

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

1000-
watcher.on('change', () => {
1001-
this.sockWrite(this.sockets, 'content-changed');
1002-
});
1004+
// disabling refreshing on changing the content
1005+
if (this.options.liveReload !== false) {
1006+
watcher.on('change', () => {
1007+
this.sockWrite(this.sockets, 'content-changed');
1008+
});
1009+
}
10031010

10041011
this.contentBaseWatchers.push(watcher);
10051012
}

lib/options.json

+4
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@
168168
"lazy": {
169169
"type": "boolean"
170170
},
171+
"liveReload": {
172+
"type": "boolean"
173+
},
171174
"log": {
172175
"instanceof": "Function"
173176
},
@@ -377,6 +380,7 @@
377380
"inline": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverinline)",
378381
"key": "should be {String|Buffer}",
379382
"lazy": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverlazy-)",
383+
"liveReload": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#livereload-)",
380384
"log": "should be {Function}",
381385
"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)",
382386
"logTime": "should be {Boolean} (https://github.com/webpack/webpack-dev-middleware#logtime)",

lib/utils/createConfig.js

+4
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ function createConfig(config, argv, { port }) {
8888
options.hotOnly = argv.hotOnly;
8989
}
9090

91+
if (argv.liveReload === false) {
92+
options.liveReload = false;
93+
}
94+
9195
// TODO https://github.com/webpack/webpack-dev-server/issues/616 (v4)
9296
// We should prefer CLI arg under config, now we always prefer `clientLogLevel` from `devServer`
9397
if (!options.clientLogLevel && argv.clientLogLevel) {

test/ContentBase.test.js

+104
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,110 @@ describe('ContentBase', () => {
1919
let server;
2020
let req;
2121

22+
describe('Test disabling live reloading', () => {
23+
const nestedFile = path.join(contentBasePublic, 'assets/example.txt');
24+
25+
jest.setTimeout(30000);
26+
27+
beforeAll((done) => {
28+
server = helper.start(
29+
config,
30+
{
31+
contentBase: contentBasePublic,
32+
watchContentBase: true,
33+
liveReload: false,
34+
},
35+
done
36+
);
37+
req = request(server.app);
38+
});
39+
40+
afterAll((done) => {
41+
helper.close(() => {
42+
done();
43+
});
44+
fs.truncateSync(nestedFile);
45+
});
46+
47+
it('Should not reload on changing files', (done) => {
48+
let reloaded = false;
49+
50+
server.contentBaseWatchers[0].on('change', () => {
51+
// it means that file has changed
52+
53+
// simulating server behaviour
54+
if (server.options.liveReload !== false) {
55+
Object.defineProperty(window.location, 'reload', {
56+
configurable: true,
57+
});
58+
window.location.reload = jest.fn();
59+
window.location.reload();
60+
reloaded = true;
61+
}
62+
expect(reloaded).toBe(false);
63+
64+
done();
65+
});
66+
67+
// change file content
68+
setTimeout(() => {
69+
fs.writeFileSync(nestedFile, 'Heyo', 'utf8');
70+
}, 1000);
71+
});
72+
});
73+
74+
describe('Testing live reloading', () => {
75+
const nestedFile = path.join(contentBasePublic, 'assets/example.txt');
76+
77+
jest.setTimeout(30000);
78+
79+
beforeAll((done) => {
80+
server = helper.start(
81+
config,
82+
{
83+
contentBase: contentBasePublic,
84+
watchContentBase: true,
85+
liveReload: true,
86+
},
87+
done
88+
);
89+
req = request(server.app);
90+
});
91+
92+
afterAll((done) => {
93+
helper.close(() => {
94+
done();
95+
});
96+
fs.truncateSync(nestedFile);
97+
});
98+
99+
it('Should reload on changing files', (done) => {
100+
let reloaded = false;
101+
102+
server.contentBaseWatchers[0].on('change', () => {
103+
// it means that files has changed
104+
105+
// simulating server behaviour
106+
if (server.options.liveReload !== false) {
107+
Object.defineProperty(window.location, 'reload', {
108+
configurable: true,
109+
});
110+
window.location.reload = jest.fn();
111+
window.location.reload();
112+
reloaded = true;
113+
}
114+
expect(reloaded).toBe(true);
115+
116+
done();
117+
});
118+
119+
// change file content
120+
setTimeout(() => {
121+
fs.writeFileSync(nestedFile, 'Heyo', 'utf8');
122+
}, 1000);
123+
});
124+
});
125+
22126
describe('to directory', () => {
23127
const nestedFile = path.join(contentBasePublic, 'assets/example.txt');
24128

test/CreateConfig.test.js

+24
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ const argv = {
1111
hot: true,
1212
// Can be `--no-hot-only` in CLI (misleading and undocumented)
1313
hotOnly: false,
14+
// Can be `--live-reload` in CLI (misleading and undocumented)
15+
liveReload: true,
1416
};
1517

1618
describe('createConfig', () => {
@@ -346,6 +348,28 @@ describe('createConfig', () => {
346348
expect(config).toMatchSnapshot();
347349
});
348350

351+
it('liveReload option', () => {
352+
const config = createConfig(
353+
webpackConfig,
354+
Object.assign({}, argv, { liveReload: true }),
355+
{ port: 8080 }
356+
);
357+
358+
expect(config).toMatchSnapshot();
359+
});
360+
361+
it('liveReload option (in devServer config)', () => {
362+
const config = createConfig(
363+
Object.assign({}, webpackConfig, {
364+
devServer: { liveReload: true },
365+
}),
366+
argv,
367+
{ port: 8080 }
368+
);
369+
370+
expect(config).toMatchSnapshot();
371+
});
372+
349373
it('hot option (in devServer config)', () => {
350374
const config = createConfig(
351375
Object.assign({}, webpackConfig, {

test/__snapshots__/CreateConfig.test.js.snap

+29
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,35 @@ Object {
699699
}
700700
`;
701701

702+
exports[`createConfig liveReload option (in devServer config) 1`] = `
703+
Object {
704+
"hot": true,
705+
"hotOnly": false,
706+
"liveReload": true,
707+
"noInfo": true,
708+
"port": 8080,
709+
"publicPath": "/",
710+
"stats": Object {
711+
"cached": false,
712+
"cachedAssets": false,
713+
},
714+
}
715+
`;
716+
717+
exports[`createConfig liveReload option 1`] = `
718+
Object {
719+
"hot": true,
720+
"hotOnly": false,
721+
"noInfo": true,
722+
"port": 8080,
723+
"publicPath": "/",
724+
"stats": Object {
725+
"cached": false,
726+
"cachedAssets": false,
727+
},
728+
}
729+
`;
730+
702731
exports[`createConfig mimeTypes option - with force 1`] = `
703732
Object {
704733
"hot": true,

0 commit comments

Comments
 (0)