From 34e33f95c19bcff28092bf624ef56cad2f85cc83 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Thu, 7 Feb 2019 21:03:59 +0900 Subject: [PATCH 1/3] refactor(webpack-dev-server): separate createSchema from webpack-dev-server.js --- bin/webpack-dev-server.js | 175 +---------------- lib/utils/createSchema.js | 176 ++++++++++++++++++ test/CreateSchema.test.js | 43 +++++ test/__snapshots__/CreateSchema.test.js.snap | 74 ++++++++ test/fixtures/schema/webpack.config.simple.js | 36 ++++ 5 files changed, 334 insertions(+), 170 deletions(-) create mode 100644 lib/utils/createSchema.js create mode 100644 test/CreateSchema.test.js create mode 100644 test/__snapshots__/CreateSchema.test.js.snap create mode 100644 test/fixtures/schema/webpack.config.simple.js diff --git a/bin/webpack-dev-server.js b/bin/webpack-dev-server.js index db56eee948..f0c4e5073c 100755 --- a/bin/webpack-dev-server.js +++ b/bin/webpack-dev-server.js @@ -17,7 +17,6 @@ const debug = require('debug')('webpack-dev-server'); const fs = require('fs'); const net = require('net'); -const path = require('path'); const portfinder = require('portfinder'); const importLocal = require('import-local'); @@ -27,13 +26,14 @@ const webpack = require('webpack'); const options = require('./options'); -const { colors, status, version, bonjour, defaultTo } = require('./utils'); +const { colors, status, version, bonjour } = require('./utils'); const Server = require('../lib/Server'); const addEntries = require('../lib/utils/addEntries'); const createDomain = require('../lib/utils/createDomain'); const createLogger = require('../lib/utils/createLogger'); +const createSchema = require('../lib/utils/createSchema'); let server; @@ -88,6 +88,7 @@ const argv = yargs.argv; const config = require('webpack-cli/bin/convert-argv')(yargs, argv, { outputFilename: '/bundle.js', }); + // Taken out of yargs because we must know if // it wasn't given by the user, in which case // we should use portfinder. @@ -105,173 +106,9 @@ function processOptions(config) { return; } - const firstWpOpt = Array.isArray(config) ? config[0] : config; - - const options = config.devServer || firstWpOpt.devServer || {}; - - if (argv.bonjour) { - options.bonjour = true; - } - - if (argv.host !== 'localhost' || !options.host) { - options.host = argv.host; - } - - if (argv['allowed-hosts']) { - options.allowedHosts = argv['allowed-hosts'].split(','); - } - - if (argv.public) { - options.public = argv.public; - } - - if (argv.socket) { - options.socket = argv.socket; - } - - if (argv.progress) { - options.progress = argv.progress; - } - - if (!options.publicPath) { - // eslint-disable-next-line - options.publicPath = - (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; - - if ( - !/^(https?:)?\/\//.test(options.publicPath) && - options.publicPath[0] !== '/' - ) { - options.publicPath = `/${options.publicPath}`; - } - } - - if (!options.filename) { - options.filename = firstWpOpt.output && firstWpOpt.output.filename; - } - - if (!options.watchOptions) { - options.watchOptions = firstWpOpt.watchOptions; - } - - if (argv.stdin) { - process.stdin.on('end', () => { - // eslint-disable-next-line no-process-exit - process.exit(0); - }); - - process.stdin.resume(); - } - - if (!options.hot) { - options.hot = argv.hot; - } + const options = createSchema(config, argv, { port: DEFAULT_PORT }); - if (!options.hotOnly) { - options.hotOnly = argv['hot-only']; - } - - if (!options.clientLogLevel) { - options.clientLogLevel = argv['client-log-level']; - } - - // eslint-disable-next-line - if (options.contentBase === undefined) { - if (argv['content-base']) { - options.contentBase = argv['content-base']; - - if (Array.isArray(options.contentBase)) { - options.contentBase = options.contentBase.map((p) => path.resolve(p)); - } else if (/^[0-9]$/.test(options.contentBase)) { - options.contentBase = +options.contentBase; - } else if (!/^(https?:)?\/\//.test(options.contentBase)) { - options.contentBase = path.resolve(options.contentBase); - } - // It is possible to disable the contentBase by using - // `--no-content-base`, which results in arg["content-base"] = false - } else if (argv['content-base'] === false) { - options.contentBase = false; - } - } - - if (argv['watch-content-base']) { - options.watchContentBase = true; - } - - if (!options.stats) { - options.stats = { - cached: false, - cachedAssets: false, - }; - } - - if ( - typeof options.stats === 'object' && - typeof options.stats.colors === 'undefined' - ) { - options.stats = Object.assign({}, options.stats, { colors: argv.color }); - } - - if (argv.lazy) { - options.lazy = true; - } - - if (!argv.info) { - options.noInfo = true; - } - - if (argv.quiet) { - options.quiet = true; - } - - if (argv.https) { - options.https = true; - } - - if (argv['pfx-passphrase']) { - options.pfxPassphrase = argv['pfx-passphrase']; - } - - if (argv.inline === false) { - options.inline = false; - } - - if (argv['history-api-fallback']) { - options.historyApiFallback = true; - } - - if (argv.compress) { - options.compress = true; - } - - if (argv['disable-host-check']) { - options.disableHostCheck = true; - } - - if (argv['open-page']) { - options.open = true; - options.openPage = argv['open-page']; - } - - if (typeof argv.open !== 'undefined') { - options.open = argv.open !== '' ? argv.open : true; - } - - if (options.open && !options.openPage) { - options.openPage = ''; - } - - if (argv.useLocalIp) { - options.useLocalIp = true; - } - // Kind of weird, but ensures prior behavior isn't broken in cases - // that wouldn't throw errors. E.g. both argv.port and options.port - // were specified, but since argv.port is 8080, options.port will be - // tried first instead. - options.port = - argv.port === DEFAULT_PORT - ? defaultTo(options.port, argv.port) - : defaultTo(argv.port, options.port); + portfinder.basePort = DEFAULT_PORT; if (options.port != null) { startDevServer(config, options); @@ -279,8 +116,6 @@ function processOptions(config) { return; } - portfinder.basePort = DEFAULT_PORT; - portfinder.getPort((err, port) => { if (err) { throw err; diff --git a/lib/utils/createSchema.js b/lib/utils/createSchema.js new file mode 100644 index 0000000000..75f8c83471 --- /dev/null +++ b/lib/utils/createSchema.js @@ -0,0 +1,176 @@ +'use strict'; + +const path = require('path'); +const { defaultTo } = require('../../bin/utils'); + +module.exports = function processOptions(config, argv, { port }) { + const firstWpOpt = Array.isArray(config) ? config[0] : config; + const options = firstWpOpt.devServer || {}; + + if (argv.bonjour) { + options.bonjour = true; + } + + if (argv.host !== 'localhost' || !options.host) { + options.host = argv.host; + } + + if (argv['allowed-hosts']) { + options.allowedHosts = argv['allowed-hosts'].split(','); + } + + if (argv.public) { + options.public = argv.public; + } + + if (argv.socket) { + options.socket = argv.socket; + } + + if (argv.progress) { + options.progress = argv.progress; + } + + if (!options.publicPath) { + // eslint-disable-next-line + options.publicPath = + (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; + + if ( + !/^(https?:)?\/\//.test(options.publicPath) && + options.publicPath[0] !== '/' + ) { + options.publicPath = `/${options.publicPath}`; + } + } + + if (!options.filename) { + options.filename = firstWpOpt.output && firstWpOpt.output.filename; + } + + if (!options.watchOptions) { + options.watchOptions = firstWpOpt.watchOptions; + } + + if (argv.stdin) { + process.stdin.on('end', () => { + // eslint-disable-next-line no-process-exit + process.exit(0); + }); + + process.stdin.resume(); + } + + if (!options.hot) { + options.hot = argv.hot; + } + + if (!options.hotOnly) { + options.hotOnly = argv['hot-only']; + } + + if (!options.clientLogLevel) { + options.clientLogLevel = argv['client-log-level']; + } + + // eslint-disable-next-line + if (options.contentBase === undefined) { + if (argv['content-base']) { + options.contentBase = argv['content-base']; + + if (Array.isArray(options.contentBase)) { + options.contentBase = options.contentBase.map((p) => path.resolve(p)); + } else if (/^[0-9]$/.test(options.contentBase)) { + options.contentBase = +options.contentBase; + } else if (!/^(https?:)?\/\//.test(options.contentBase)) { + options.contentBase = path.resolve(options.contentBase); + } + // It is possible to disable the contentBase by using + // `--no-content-base`, which results in arg["content-base"] = false + } else if (argv['content-base'] === false) { + options.contentBase = false; + } + } + + if (argv['watch-content-base']) { + options.watchContentBase = true; + } + + if (!options.stats) { + options.stats = { + cached: false, + cachedAssets: false, + }; + } + + if ( + typeof options.stats === 'object' && + typeof options.stats.colors === 'undefined' + ) { + options.stats = Object.assign({}, options.stats, { colors: argv.color }); + } + + if (argv.lazy) { + options.lazy = true; + } + + if (!argv.info) { + options.noInfo = true; + } + + if (argv.quiet) { + options.quiet = true; + } + + if (argv.https) { + options.https = true; + } + + if (argv['pfx-passphrase']) { + options.pfxPassphrase = argv['pfx-passphrase']; + } + + if (argv.inline === false) { + options.inline = false; + } + + if (argv['history-api-fallback']) { + options.historyApiFallback = true; + } + + if (argv.compress) { + options.compress = true; + } + + if (argv['disable-host-check']) { + options.disableHostCheck = true; + } + + if (argv['open-page']) { + options.open = true; + options.openPage = argv['open-page']; + } + + if (typeof argv.open !== 'undefined') { + options.open = argv.open !== '' ? argv.open : true; + } + + if (options.open && !options.openPage) { + options.openPage = ''; + } + + if (argv.useLocalIp) { + options.useLocalIp = true; + } + + // Kind of weird, but ensures prior behavior isn't broken in cases + // that wouldn't throw errors. E.g. both argv.port and options.port + // were specified, but since argv.port is 8080, options.port will be + // tried first instead. + options.port = + argv.port === port + ? defaultTo(options.port, argv.port) + : defaultTo(argv.port, options.port); + + return options; +}; diff --git a/test/CreateSchema.test.js b/test/CreateSchema.test.js new file mode 100644 index 0000000000..6979d29220 --- /dev/null +++ b/test/CreateSchema.test.js @@ -0,0 +1,43 @@ +'use strict'; + +const createSchema = require('../lib/utils/createSchema'); +const webpackConfig = require('./fixtures/schema/webpack.config.simple'); + +const argv = { + host: 'foo', + public: 'public', + socket: 'socket', + progress: 'progress', + publicPath: 'publicPath', + filename: 'filename', + hot: 'hot', + hotOnly: 'hotOnly', + clientLogLevel: 'clientLogLevel', + contentBase: 'contentBase', + watchContentBase: 'watchContentBase', + stats: { + cached: 'cached', + cachedAssets: 'cachedAssets', + colors: 'colors', + }, + lazy: 'lazy', + noInfo: 'noInfo', + quiet: 'quiet', + https: 'https', + pfxPassphrase: 'pfxPassphrase', + inline: 'inline', + historyApiFallback: 'historyApiFallback', + compress: 'compress', + disableHostCheck: 'disableHostCheck', + open: 'open', + openPage: 'openPage', + useLocalIp: 'useLocalIp', + port: 'port', +}; + +describe('createSchema', () => { + it('simple', () => { + expect(createSchema(webpackConfig, argv, { port: 8080 })).toMatchSnapshot(); + expect(webpackConfig).toMatchSnapshot(); + }); +}); diff --git a/test/__snapshots__/CreateSchema.test.js.snap b/test/__snapshots__/CreateSchema.test.js.snap new file mode 100644 index 0000000000..72c4d21134 --- /dev/null +++ b/test/__snapshots__/CreateSchema.test.js.snap @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`createSchema simple 1`] = ` +Object { + "clientLogLevel": "_clientLogLevel", + "compress": true, + "contentBase": "_contentBase", + "disableHostCheck": "_disableHostCheck", + "filename": "_filename", + "historyApiFallback": "_historyApiFallback", + "host": "foo", + "hot": "_hot", + "hotOnly": "_hotOnly", + "https": true, + "inline": "_inline", + "lazy": true, + "noInfo": true, + "open": "open", + "openPage": "_openPage", + "pfxPassphrase": "_pfxPassphrase", + "port": "port", + "progress": "progress", + "public": "public", + "publicPath": "_publicPath", + "quiet": true, + "socket": "socket", + "stats": Object { + "cached": "_cached", + "cachedAssets": "_cachedAssets", + "colors": "_colors", + }, + "useLocalIp": true, + "watchContentBase": "_watchContentBase", + "watchOptions": undefined, +} +`; + +exports[`createSchema simple 2`] = ` +Object { + "devServer": Object { + "clientLogLevel": "_clientLogLevel", + "compress": true, + "contentBase": "_contentBase", + "disableHostCheck": "_disableHostCheck", + "filename": "_filename", + "historyApiFallback": "_historyApiFallback", + "host": "foo", + "hot": "_hot", + "hotOnly": "_hotOnly", + "https": true, + "inline": "_inline", + "lazy": true, + "noInfo": true, + "open": "open", + "openPage": "_openPage", + "pfxPassphrase": "_pfxPassphrase", + "port": "port", + "progress": "progress", + "public": "public", + "publicPath": "_publicPath", + "quiet": true, + "socket": "socket", + "stats": Object { + "cached": "_cached", + "cachedAssets": "_cachedAssets", + "colors": "_colors", + }, + "useLocalIp": true, + "watchContentBase": "_watchContentBase", + "watchOptions": undefined, + }, + "entry": "./app.js", +} +`; diff --git a/test/fixtures/schema/webpack.config.simple.js b/test/fixtures/schema/webpack.config.simple.js new file mode 100644 index 0000000000..b50102ea4c --- /dev/null +++ b/test/fixtures/schema/webpack.config.simple.js @@ -0,0 +1,36 @@ +'use strict'; + +module.exports = { + entry: './app.js', + devServer: { + host: '_foo', + public: '_public', + socket: '_socket', + progress: '_progress', + publicPath: '_publicPath', + filename: '_filename', + hot: '_hot', + hotOnly: '_hotOnly', + clientLogLevel: '_clientLogLevel', + contentBase: '_contentBase', + watchContentBase: '_watchContentBase', + stats: { + cached: '_cached', + cachedAssets: '_cachedAssets', + colors: '_colors', + }, + lazy: '_lazy', + noInfo: '_noInfo', + quiet: '_quiet', + https: '_https', + pfxPassphrase: '_pfxPassphrase', + inline: '_inline', + historyApiFallback: '_historyApiFallback', + compress: '_compress', + disableHostCheck: '_disableHostCheck', + open: '_open', + openPage: '_openPage', + useLocalIp: '_useLocalIp', + port: '_port', + }, +}; From f23b144cb22e24c53b3a3846e8d95dd49e50d6ad Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Thu, 7 Feb 2019 23:36:32 +0900 Subject: [PATCH 2/3] feat: add mode as development ISSUE: https://github.com/webpack/webpack-dev-server/issues/1560 PR: https://github.com/webpack/webpack-dev-server/pull/1562 --- lib/utils/createSchema.js | 3 +++ test/__snapshots__/CreateSchema.test.js.snap | 1 + 2 files changed, 4 insertions(+) diff --git a/lib/utils/createSchema.js b/lib/utils/createSchema.js index 75f8c83471..aee7fd79f8 100644 --- a/lib/utils/createSchema.js +++ b/lib/utils/createSchema.js @@ -7,6 +7,9 @@ module.exports = function processOptions(config, argv, { port }) { const firstWpOpt = Array.isArray(config) ? config[0] : config; const options = firstWpOpt.devServer || {}; + // This updates both config and firstWpOpt + firstWpOpt.mode = defaultTo(firstWpOpt.mode, 'development'); + if (argv.bonjour) { options.bonjour = true; } diff --git a/test/__snapshots__/CreateSchema.test.js.snap b/test/__snapshots__/CreateSchema.test.js.snap index 72c4d21134..48fc408fb3 100644 --- a/test/__snapshots__/CreateSchema.test.js.snap +++ b/test/__snapshots__/CreateSchema.test.js.snap @@ -70,5 +70,6 @@ Object { "watchOptions": undefined, }, "entry": "./app.js", + "mode": "development", } `; From 65956e1173840ed33c6d3716a2615e733a2c6973 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Fri, 8 Feb 2019 00:10:21 +0900 Subject: [PATCH 3/3] refactor: rename createSchema to createConfig --- bin/webpack-dev-server.js | 4 ++-- lib/utils/{createSchema.js => createConfig.js} | 6 ++++-- test/{CreateSchema.test.js => CreateConfig.test.js} | 6 +++--- ...{CreateSchema.test.js.snap => CreateConfig.test.js.snap} | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) rename lib/utils/{createSchema.js => createConfig.js} (98%) rename test/{CreateSchema.test.js => CreateConfig.test.js} (85%) rename test/__snapshots__/{CreateSchema.test.js.snap => CreateConfig.test.js.snap} (95%) diff --git a/bin/webpack-dev-server.js b/bin/webpack-dev-server.js index f0c4e5073c..7113687121 100755 --- a/bin/webpack-dev-server.js +++ b/bin/webpack-dev-server.js @@ -33,7 +33,7 @@ const Server = require('../lib/Server'); const addEntries = require('../lib/utils/addEntries'); const createDomain = require('../lib/utils/createDomain'); const createLogger = require('../lib/utils/createLogger'); -const createSchema = require('../lib/utils/createSchema'); +const createConfig = require('../lib/utils/createConfig'); let server; @@ -106,7 +106,7 @@ function processOptions(config) { return; } - const options = createSchema(config, argv, { port: DEFAULT_PORT }); + const options = createConfig(config, argv, { port: DEFAULT_PORT }); portfinder.basePort = DEFAULT_PORT; diff --git a/lib/utils/createSchema.js b/lib/utils/createConfig.js similarity index 98% rename from lib/utils/createSchema.js rename to lib/utils/createConfig.js index aee7fd79f8..a43eb84a08 100644 --- a/lib/utils/createSchema.js +++ b/lib/utils/createConfig.js @@ -3,7 +3,7 @@ const path = require('path'); const { defaultTo } = require('../../bin/utils'); -module.exports = function processOptions(config, argv, { port }) { +function createConfig(config, argv, { port }) { const firstWpOpt = Array.isArray(config) ? config[0] : config; const options = firstWpOpt.devServer || {}; @@ -176,4 +176,6 @@ module.exports = function processOptions(config, argv, { port }) { : defaultTo(argv.port, options.port); return options; -}; +} + +module.exports = createConfig; diff --git a/test/CreateSchema.test.js b/test/CreateConfig.test.js similarity index 85% rename from test/CreateSchema.test.js rename to test/CreateConfig.test.js index 6979d29220..b7da21f35e 100644 --- a/test/CreateSchema.test.js +++ b/test/CreateConfig.test.js @@ -1,6 +1,6 @@ 'use strict'; -const createSchema = require('../lib/utils/createSchema'); +const createConfig = require('../lib/utils/createConfig'); const webpackConfig = require('./fixtures/schema/webpack.config.simple'); const argv = { @@ -35,9 +35,9 @@ const argv = { port: 'port', }; -describe('createSchema', () => { +describe('createConfig', () => { it('simple', () => { - expect(createSchema(webpackConfig, argv, { port: 8080 })).toMatchSnapshot(); + expect(createConfig(webpackConfig, argv, { port: 8080 })).toMatchSnapshot(); expect(webpackConfig).toMatchSnapshot(); }); }); diff --git a/test/__snapshots__/CreateSchema.test.js.snap b/test/__snapshots__/CreateConfig.test.js.snap similarity index 95% rename from test/__snapshots__/CreateSchema.test.js.snap rename to test/__snapshots__/CreateConfig.test.js.snap index 48fc408fb3..1c86c5ed35 100644 --- a/test/__snapshots__/CreateSchema.test.js.snap +++ b/test/__snapshots__/CreateConfig.test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`createSchema simple 1`] = ` +exports[`createConfig simple 1`] = ` Object { "clientLogLevel": "_clientLogLevel", "compress": true, @@ -35,7 +35,7 @@ Object { } `; -exports[`createSchema simple 2`] = ` +exports[`createConfig simple 2`] = ` Object { "devServer": Object { "clientLogLevel": "_clientLogLevel",