Skip to content

Commit

Permalink
Merge branch 'add-live-reload-option' of https://github.com/EslamHiko…
Browse files Browse the repository at this point in the history
…/webpack-dev-server into add-live-reload-option
  • Loading branch information
EslamHiko committed May 13, 2019
2 parents 47e592b + 211f37f commit 7f47bb7
Show file tree
Hide file tree
Showing 14 changed files with 199 additions and 63 deletions.
51 changes: 9 additions & 42 deletions bin/webpack-dev-server.js
Expand Up @@ -22,13 +22,10 @@ const Server = require('../lib/Server');

const colors = require('../lib/utils/colors');
const createConfig = require('../lib/utils/createConfig');
const createDomain = require('../lib/utils/createDomain');
const createLogger = require('../lib/utils/createLogger');
const defaultTo = require('../lib/utils/defaultTo');
const findPort = require('../lib/utils/findPort');
const getVersions = require('../lib/utils/getVersions');
const runBonjour = require('../lib/utils/runBonjour');
const status = require('../lib/utils/status');
const tryParseInt = require('../lib/utils/tryParseInt');

let server;
Expand Down Expand Up @@ -159,11 +156,6 @@ function startDevServer(config, options) {
}).apply(compiler);
}

const suffix =
options.inline !== false || options.lazy === true
? '/'
: '/webpack-dev-server/';

try {
server = new Server(compiler, options, log);
} catch (err) {
Expand Down Expand Up @@ -200,52 +192,27 @@ function startDevServer(config, options) {
}
});

server.listen(options.socket, options.host, (err) => {
runServer();
} else if (options.port) {
runServer();
} else {
// only run port finder if no port as been specified
findPort(server, DEFAULT_PORT, defaultPortRetry, (err, port) => {
if (err) {
throw err;
}
// chmod 666 (rw rw rw)
const READ_WRITE = 438;

fs.chmod(options.socket, READ_WRITE, (err) => {
if (err) {
throw err;
}

const uri = createDomain(options, server.listeningApp) + suffix;

status(uri, options, log, argv.color);
});
options.port = port;
runServer();
});
return;
}

const startServer = () => {
function runServer() {
server.listen(options.port, options.host, (err) => {
if (err) {
throw err;
}
if (options.bonjour) {
runBonjour(options);
}
const uri = createDomain(options, server.listeningApp) + suffix;
status(uri, options, log, argv.color);
});
};

if (options.port) {
startServer();
return;
}

// only run port finder if no port as been specified
findPort(server, DEFAULT_PORT, defaultPortRetry, (err, port) => {
if (err) {
throw err;
}
options.port = port;
startServer();
});
}

processOptions(config);
32 changes: 23 additions & 9 deletions client-src/default/index.js
Expand Up @@ -225,21 +225,35 @@ if (
) {
protocol = self.location.protocol;
}

// default values of the sock url if they are not provided
let sockHost = hostname;
let sockPath = '/sockjs-node';
let sockPort = urlParts.port;
if (
urlParts.path !== null &&
// eslint-disable-next-line no-undefined
urlParts.path !== undefined &&
urlParts.path !== '/'
) {
const parsedQuery = querystring.parse(urlParts.path);
// all of these sock url params are optionally passed in through
// __resourceQuery, so we need to fall back to the default if
// they are not provided
sockHost = parsedQuery.sockHost || sockHost;
sockPath = parsedQuery.sockPath || sockPath;
sockPort = parsedQuery.sockPort || sockPort;
}

const socketUrl = url.format({
protocol,
auth: urlParts.auth,
hostname,
port:
urlParts.path == null || urlParts.path === '/'
? urlParts.port
: querystring.parse(urlParts.path).sockPort || urlParts.port,
hostname: sockHost,
port: sockPort,
// If sockPath is provided it'll be passed in via the __resourceQuery as a
// query param so it has to be parsed out of the querystring in order for the
// client to open the socket to the correct location.
pathname:
urlParts.path == null || urlParts.path === '/'
? '/sockjs-node'
: querystring.parse(urlParts.path).sockPath || urlParts.path,
pathname: sockPath,
});

socket(socketUrl, onSocketMsg);
Expand Down
1 change: 1 addition & 0 deletions examples/api/simple/server.js
Expand Up @@ -6,6 +6,7 @@ const webpackConfig = require('./webpack.config');

const compiler = Webpack(webpackConfig);
const devServerOptions = Object.assign({}, webpackConfig.devServer, {
open: true,
stats: {
colors: true,
},
Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Expand Up @@ -2,7 +2,7 @@

module.exports = {
testURL: 'http://localhost/',
collectCoverage: true,
collectCoverage: false,
coveragePathIgnorePatterns: ['test'],
moduleFileExtensions: ['js', 'json'],
testMatch: ['**/test/**/*.test.js'],
Expand Down
38 changes: 38 additions & 0 deletions lib/Server.js
Expand Up @@ -27,6 +27,9 @@ const validateOptions = require('schema-utils');
const updateCompiler = require('./utils/updateCompiler');
const createLogger = require('./utils/createLogger');
const getCertificate = require('./utils/getCertificate');
const status = require('./utils/status');
const createDomain = require('./utils/createDomain');
const runBonjour = require('./utils/runBonjour');
const routes = require('./utils/routes');
const schema = require('./options.json');

Expand Down Expand Up @@ -813,6 +816,41 @@ class Server {
prefix: this.sockPath,
});

if (this.options.bonjour) {
runBonjour(this.options);
}

const showStatus = () => {
const suffix =
this.options.inline !== false || this.options.lazy === true
? '/'
: '/webpack-dev-server/';

const uri = `${createDomain(this.options, this.listeningApp)}${suffix}`;

status(
uri,
this.options,
this.log,
this.options.stats && this.options.stats.colors
);
};

if (this.options.socket) {
// chmod 666 (rw rw rw)
const READ_WRITE = 438;

fs.chmod(this.options.socket, READ_WRITE, (err) => {
if (err) {
throw err;
}

showStatus();
});
} else {
showStatus();
}

if (fn) {
fn.call(this.listeningApp, err);
}
Expand Down
6 changes: 5 additions & 1 deletion lib/options.json
Expand Up @@ -291,6 +291,9 @@
"setup": {
"instanceof": "Function"
},
"sockHost": {
"type": "string"
},
"sockPath": {
"type": "string"
},
Expand Down Expand Up @@ -399,8 +402,9 @@
"serveIndex": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverserveindex)",
"serverSideRender": "should be {Boolean} (https://github.com/webpack/webpack-dev-middleware#serversiderender)",
"setup": "should be {Function} (https://webpack.js.org/configuration/dev-server/#devserversetup)",
"sockHost": "should be {String|Null} (https://webpack.js.org/configuration/dev-server/#devserversockhost)",
"sockPath": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserversockpath)",
"sockPort": "should be {Number|String|Null}",
"sockPort": "should be {Number|String|Null} (https://webpack.js.org/configuration/dev-server/#devserversockport)",
"socket": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserversocket)",
"staticOptions": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devserverstaticoptions)",
"stats": "should be {Object|Boolean} (https://webpack.js.org/configuration/dev-server/#devserverstats-)",
Expand Down
3 changes: 2 additions & 1 deletion lib/utils/addEntries.js
Expand Up @@ -16,11 +16,12 @@ function addEntries(config, options, server) {
};

const domain = createDomain(options, app);
const sockHost = options.sockHost ? `&sockHost=${options.sockHost}` : '';
const sockPath = options.sockPath ? `&sockPath=${options.sockPath}` : '';
const sockPort = options.sockPort ? `&sockPort=${options.sockPort}` : '';
const clientEntry = `${require.resolve(
'../../client/'
)}?${domain}${sockPath}${sockPort}`;
)}?${domain}${sockHost}${sockPath}${sockPort}`;
let hotEntry;

if (options.hotOnly) {
Expand Down
4 changes: 4 additions & 0 deletions lib/utils/createConfig.js
Expand Up @@ -30,6 +30,10 @@ function createConfig(config, argv, { port }) {
options.socket = argv.socket;
}

if (argv.sockHost) {
options.sockHost = argv.sockHost;
}

if (argv.sockPath) {
options.sockPath = argv.sockPath;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/utils/status.js
Expand Up @@ -3,6 +3,7 @@
const open = require('opn');
const colors = require('./colors');

// TODO: don't emit logs when webpack-dev-server is used via Node.js API
function status(uri, options, log, useColor) {
const contentBase = Array.isArray(options.contentBase)
? options.contentBase.join(', ')
Expand Down Expand Up @@ -51,7 +52,7 @@ function status(uri, options, log, useColor) {
openMessage += `: ${options.open}`;
}

open(uri + (options.openPage || ''), openOptions).catch(() => {
open(`${uri}${options.openPage || ''}`, openOptions).catch(() => {
log.warn(
`${openMessage}. If you are running in a headless environment, please do not use the --open flag`
);
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Expand Up @@ -17,10 +17,10 @@
"lint": "eslint bin lib test examples client-src",
"pretty": "prettier --loglevel warn --write \"**/*.{js,css,md,json,yml}\"",
"test:only": "jest --runInBand",
"test:watch": "jest --watch --runInBand",
"test:coverage": "jest --runInBand --collectCoverageFrom='src/**/*.js' --coverage",
"pretest": "npm run lint",
"test:coverage": "npm run test:only -- --coverage",
"test:watch": "npm run test:coverage --watch",
"test": "npm run test:coverage",
"pretest": "npm run lint",
"prepare": "rimraf ./ssl/*.pem && npm run -s transpile:index && npm run -s build:live && npm run -s build:index && npm run -s build:sockjs",
"transpile:index": "babel client-src/default --out-dir client --ignore *.config.js",
"build:index": "webpack ./client-src/default/index.js -o client/index.bundle.js --color --config client-src/default/webpack.config.js",
Expand Down Expand Up @@ -65,7 +65,7 @@
"@babel/cli": "7.4.4",
"@babel/core": "7.4.4",
"@babel/preset-env": "7.4.4",
"babel-loader": "8.0.5",
"babel-loader": "8.0.6",
"copy-webpack-plugin": "5.0.3",
"css-loader": "2.1.1",
"eslint": "5.16.0",
Expand Down
73 changes: 73 additions & 0 deletions test/Client.test.js
Expand Up @@ -156,3 +156,76 @@ describe('Client complex inline script path with sockPort', () => {
});
});
});

// previously, using sockPort without sockPath had the ability
// to alter the sockPath (based on a bug in client-src/index.js)
// so we need to make sure sockPath is not altered in this case
describe('Client complex inline script path with sockPort, no sockPath', () => {
beforeAll((done) => {
const options = {
port: 9000,
host: '0.0.0.0',
inline: true,
watchOptions: {
poll: true,
},
sockPort: 8080,
};
helper.startAwaitingCompilation(config, options, done);
});

afterAll(helper.close);

describe('browser client', () => {
jest.setTimeout(30000);

it('uses the correct sockPort and sockPath', (done) => {
runBrowser().then(({ page, browser }) => {
page
.waitForRequest((requestObj) => requestObj.url().match(/sockjs-node/))
.then((requestObj) => {
expect(requestObj.url()).toMatch(
/^http:\/\/localhost:8080\/sockjs-node/
);
browser.close().then(done);
});
page.goto('http://localhost:9000/main');
});
});
});
});

describe('Client complex inline script path with sockHost', () => {
beforeAll((done) => {
const options = {
port: 9000,
host: '0.0.0.0',
inline: true,
watchOptions: {
poll: true,
},
sockHost: 'myhost.test',
};
helper.startAwaitingCompilation(config, options, done);
});

afterAll(helper.close);

describe('browser client', () => {
jest.setTimeout(30000);

it('uses the correct sockHost', (done) => {
runBrowser().then(({ page, browser }) => {
page
.waitForRequest((requestObj) => requestObj.url().match(/sockjs-node/))
.then((requestObj) => {
expect(requestObj.url()).toMatch(
/^http:\/\/myhost\.test:9000\/sockjs-node/
);
browser.close().then(done);
});
page.goto('http://localhost:9000/main');
});
});
});
});

0 comments on commit 7f47bb7

Please sign in to comment.