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