Skip to content

Commit

Permalink
feat: add liveReload option to enable/disable refreshing the page
Browse files Browse the repository at this point in the history
  • Loading branch information
EslamHiko authored and hiroppy committed May 15, 2019
1 parent c535bb2 commit cadee8b
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 4 deletions.
5 changes: 5 additions & 0 deletions bin/options.js
Expand Up @@ -17,6 +17,11 @@ const options = {
type: 'boolean',
describe: 'Broadcasts the server via ZeroConf networking on start',
},
liveReload: {
type: 'boolean',
describe: 'Enables/Disables live reloading on changing files',
default: true,
},
lazy: {
type: 'boolean',
describe: 'Lazy',
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
13 changes: 10 additions & 3 deletions lib/Server.js
Expand Up @@ -869,6 +869,10 @@ class Server {
this.sockWrite([connection], 'progress', this.progress);
}

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

if (this.clientOverlay) {
this.sockWrite([connection], 'overlay', this.clientOverlay);
}
Expand Down Expand Up @@ -997,9 +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/#livereload-)",
"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 @@ -88,6 +88,10 @@ function createConfig(config, argv, { port }) {
options.hotOnly = argv.hotOnly;
}

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

// TODO https://github.com/webpack/webpack-dev-server/issues/616 (v4)
// We should prefer CLI arg under config, now we always prefer `clientLogLevel` from `devServer`
if (!options.clientLogLevel && argv.clientLogLevel) {
Expand Down
104 changes: 104 additions & 0 deletions test/ContentBase.test.js
Expand Up @@ -19,6 +19,110 @@ describe('ContentBase', () => {
let server;
let req;

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
);
req = request(server.app);
});

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
);
req = request(server.app);
});

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);
});
});

describe('to directory', () => {
const nestedFile = path.join(contentBasePublic, 'assets/example.txt');

Expand Down
24 changes: 24 additions & 0 deletions test/CreateConfig.test.js
Expand Up @@ -11,6 +11,8 @@ const argv = {
hot: true,
// Can be `--no-hot-only` in CLI (misleading and undocumented)
hotOnly: false,
// Can be `--live-reload` in CLI (misleading and undocumented)
liveReload: true,
};

describe('createConfig', () => {
Expand Down Expand Up @@ -346,6 +348,28 @@ describe('createConfig', () => {
expect(config).toMatchSnapshot();
});

it('liveReload option', () => {
const config = createConfig(
webpackConfig,
Object.assign({}, argv, { liveReload: true }),
{ port: 8080 }
);

expect(config).toMatchSnapshot();
});

it('liveReload option (in devServer config)', () => {
const config = createConfig(
Object.assign({}, webpackConfig, {
devServer: { liveReload: true },
}),
argv,
{ port: 8080 }
);

expect(config).toMatchSnapshot();
});

it('hot option (in devServer config)', () => {
const config = createConfig(
Object.assign({}, webpackConfig, {
Expand Down
29 changes: 29 additions & 0 deletions test/__snapshots__/CreateConfig.test.js.snap
Expand Up @@ -699,6 +699,35 @@ Object {
}
`;

exports[`createConfig liveReload option (in devServer config) 1`] = `
Object {
"hot": true,
"hotOnly": false,
"liveReload": true,
"noInfo": true,
"port": 8080,
"publicPath": "/",
"stats": Object {
"cached": false,
"cachedAssets": false,
},
}
`;

exports[`createConfig liveReload option 1`] = `
Object {
"hot": true,
"hotOnly": false,
"noInfo": true,
"port": 8080,
"publicPath": "/",
"stats": Object {
"cached": false,
"cachedAssets": false,
},
}
`;

exports[`createConfig mimeTypes option - with force 1`] = `
Object {
"hot": true,
Expand Down

0 comments on commit cadee8b

Please sign in to comment.