diff --git a/client-src/default/index.js b/client-src/default/index.js
index 23c8e2fd8f..f1c111bcb8 100644
--- a/client-src/default/index.js
+++ b/client-src/default/index.js
@@ -2,7 +2,7 @@
/* global __resourceQuery WorkerGlobalScope self */
/* eslint prefer-destructuring: off */
-
+const qs = require('querystring');
const url = require('url');
const stripAnsi = require('strip-ansi');
const log = require('loglevel').getLogger('webpack-dev-server');
@@ -194,7 +194,7 @@ const socketUrl = url.format({
auth: urlParts.auth,
hostname,
port: urlParts.port,
- pathname: urlParts.path == null || urlParts.path === '/' ? '/sockjs-node' : urlParts.path
+ pathname: urlParts.path == null || urlParts.path === '/' ? '/sockjs-node' : (qs.parse(urlParts.path).sockPath || urlParts.path)
});
socket(socketUrl, onSocketMsg);
diff --git a/examples/node-api-sock-path/README.md b/examples/node-api-sock-path/README.md
new file mode 100644
index 0000000000..48e44e1ed0
--- /dev/null
+++ b/examples/node-api-sock-path/README.md
@@ -0,0 +1,15 @@
+# Node.js API - Simple
+
+```shell
+node server.js
+```
+
+Starts a simple webpack-dev-server setup via the Node API. Open `http://localhost:8080/` to go the app.
+
+## What should happen
+
+In the app you should see "It's working."
+
+In `app.js`, uncomment the code that results in an error and save. This error should be visible in the CLI and devtools.
+
+Then, in `app.js`, uncomment the code that results in a warning. This warning should be visible in the CLI and devtools.
\ No newline at end of file
diff --git a/examples/node-api-sock-path/app.js b/examples/node-api-sock-path/app.js
new file mode 100644
index 0000000000..ccd81d08ca
--- /dev/null
+++ b/examples/node-api-sock-path/app.js
@@ -0,0 +1,3 @@
+'use strict';
+
+document.write('It\'s working under a subapp');
diff --git a/examples/node-api-sock-path/index.html b/examples/node-api-sock-path/index.html
new file mode 100644
index 0000000000..1f527bff03
--- /dev/null
+++ b/examples/node-api-sock-path/index.html
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+ Example: Node.js API - Simple
+
+
\ No newline at end of file
diff --git a/examples/node-api-sock-path/server.js b/examples/node-api-sock-path/server.js
new file mode 100644
index 0000000000..501f048fcc
--- /dev/null
+++ b/examples/node-api-sock-path/server.js
@@ -0,0 +1,25 @@
+'use strict';
+
+const path = require('path');
+const Webpack = require('webpack');
+const WebpackDevServer = require('../../lib/Server');
+const webpackConfig = require('./webpack.config');
+
+const compiler = Webpack(webpackConfig);
+const server = new WebpackDevServer(compiler, {
+ stats: {
+ colors: true
+ },
+ contentBase: path.resolve(__dirname),
+ watchContentBase: true,
+ sockPath: '/subapp/sockjs-node',
+ publicPath: '/subapp/',
+ historyApiFallback: {
+ disableDotRule: true,
+ index: '/subapp/'
+ }
+});
+
+server.listen(8080, '127.0.0.1', () => {
+ console.log('Starting server on http://localhost:8080');
+});
diff --git a/examples/node-api-sock-path/webpack.config.js b/examples/node-api-sock-path/webpack.config.js
new file mode 100644
index 0000000000..1292359194
--- /dev/null
+++ b/examples/node-api-sock-path/webpack.config.js
@@ -0,0 +1,10 @@
+'use strict';
+
+module.exports = {
+ context: __dirname,
+ entry: ['./app.js', '../../client/index.js?http://localhost:8080/&sockPath=subapp/sockjs-node'],
+ output: {
+ filename: 'bundle.js',
+ publicPath: '/subapp/'
+ }
+};
diff --git a/lib/Server.js b/lib/Server.js
index 3250722f5f..19a0d2d5bf 100644
--- a/lib/Server.js
+++ b/lib/Server.js
@@ -51,6 +51,7 @@ function Server(compiler, options) {
this.sockets = [];
this.contentBaseWatchers = [];
this.watchOptions = options.watchOptions || {};
+ this.sockPath = `/${options.sockPath ? options.sockPath.replace(/^\/|\/$/, '') : 'sockjs-node'}`;
// Listening for events
const invalidPlugin = () => {
@@ -608,7 +609,7 @@ Server.prototype.listen = function (port, hostname, fn) {
});
sockServer.installHandlers(this.listeningApp, {
- prefix: '/sockjs-node'
+ prefix: this.sockPath
});
if (fn) {
diff --git a/lib/optionsSchema.json b/lib/optionsSchema.json
index 32ceb8d7bd..e27a5e2edf 100644
--- a/lib/optionsSchema.json
+++ b/lib/optionsSchema.json
@@ -58,6 +58,10 @@
"description": "The Unix socket to listen to (instead of on a host).",
"type": "string"
},
+ "sockPath": {
+ "description": "URL path where the sockjs-node is served from (default is sockjs-node).",
+ "type": "string"
+ },
"watchOptions": {
"description": "Options for changing the watch behavior.",
"type": "object"
diff --git a/lib/util/addDevServerEntrypoints.js b/lib/util/addDevServerEntrypoints.js
index d3d95b3a32..c4ddcc67ac 100644
--- a/lib/util/addDevServerEntrypoints.js
+++ b/lib/util/addDevServerEntrypoints.js
@@ -15,7 +15,8 @@ module.exports = function addDevServerEntrypoints(webpackOptions, devServerOptio
}
};
const domain = createDomain(devServerOptions, app);
- const devClient = [`${require.resolve('../../client/')}?${domain}`];
+ const sockPath = devServerOptions.sockPath ? `&sockPath=${devServerOptions.sockPath}` : '';
+ const devClient = [`${require.resolve('../../client/')}?${domain}${sockPath}`];
if (devServerOptions.hotOnly) { devClient.push('webpack/hot/only-dev-server'); } else if (devServerOptions.hot) { devClient.push('webpack/hot/dev-server'); }
diff --git a/test/Validation.test.js b/test/Validation.test.js
index b4284a5e59..055bea5c32 100644
--- a/test/Validation.test.js
+++ b/test/Validation.test.js
@@ -48,7 +48,7 @@ describe('Validation', () => {
config: { asdf: true },
message: [
" - configuration has an unknown property 'asdf'. These properties are valid:",
- ' object { hot?, hotOnly?, lazy?, bonjour?, host?, allowedHosts?, filename?, publicPath?, port?, socket?, ' +
+ ' object { hot?, hotOnly?, lazy?, bonjour?, host?, allowedHosts?, filename?, publicPath?, port?, socket?, sockPath?, ' +
'watchOptions?, headers?, clientLogLevel?, overlay?, progress?, key?, cert?, ca?, pfx?, pfxPassphrase?, requestCert?, ' +
'inline?, disableHostCheck?, public?, https?, contentBase?, watchContentBase?, open?, useLocalIp?, openPage?, features?, ' +
'compress?, proxy?, historyApiFallback?, staticOptions?, setup?, before?, after?, stats?, reporter?, reportTime?, ' +
diff --git a/test/addDevServerEntrypoints.test.js b/test/addDevServerEntrypoints.test.js
new file mode 100644
index 0000000000..42f9f5ca06
--- /dev/null
+++ b/test/addDevServerEntrypoints.test.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const assert = require('assert');
+const addDevServerEntrypoints = require('../lib/util/addDevServerEntrypoints');
+const config = require('./fixtures/simple-config/webpack.config');
+
+describe('addDevServerEntrypoints', () => {
+ it('Entrypoints that are a single file will become an array', () => {
+ addDevServerEntrypoints(Object.assign({}, config), {});
+ assert(config.entry.length);
+ });
+
+ it('Entrypoints that are an array will become a longer array', () => {
+ addDevServerEntrypoints(
+ Object.assign({}, config, { entry: [config.entry] }),
+ {}
+ );
+ assert(config.entry.length > 1);
+ });
+
+ it('Entrypoints that are objects will have more keys', () => {
+ addDevServerEntrypoints(
+ Object.assign({}, config, { entry: { app: config.entry } }),
+ {}
+ );
+ assert(Object.keys(config.entry).length > 1);
+ });
+});