webpack-dev-server 3.3.1 → 3.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ // const ws = require('ws');
4
+ const BaseServer = require('./BaseServer');
5
+
6
+ // ws server implementation under construction
7
+ // will need changes in the client as well to function
8
+ module.exports = class WebsocketServer extends BaseServer {};
@@ -16,28 +16,34 @@ function addEntries(config, options, server) {
16
16
  };
17
17
 
18
18
  const domain = createDomain(options, app);
19
+ const sockHost = options.sockHost ? `&sockHost=${options.sockHost}` : '';
19
20
  const sockPath = options.sockPath ? `&sockPath=${options.sockPath}` : '';
20
- const entries = [
21
- `${require.resolve('../../client/')}?${domain}${sockPath}`,
22
- ];
21
+ const sockPort = options.sockPort ? `&sockPort=${options.sockPort}` : '';
22
+ const clientEntry = `${require.resolve(
23
+ '../../client/'
24
+ )}?${domain}${sockHost}${sockPath}${sockPort}`;
25
+ let hotEntry;
23
26
 
24
27
  if (options.hotOnly) {
25
- entries.push(require.resolve('webpack/hot/only-dev-server'));
28
+ hotEntry = require.resolve('webpack/hot/only-dev-server');
26
29
  } else if (options.hot) {
27
- entries.push(require.resolve('webpack/hot/dev-server'));
30
+ hotEntry = require.resolve('webpack/hot/dev-server');
28
31
  }
29
32
 
30
- const prependEntry = (entry) => {
31
- if (typeof entry === 'function') {
32
- return () => Promise.resolve(entry()).then(prependEntry);
33
+ const prependEntry = (originalEntry, additionalEntries) => {
34
+ if (typeof originalEntry === 'function') {
35
+ return () =>
36
+ Promise.resolve(originalEntry()).then((entry) =>
37
+ prependEntry(entry, additionalEntries)
38
+ );
33
39
  }
34
40
 
35
- if (typeof entry === 'object' && !Array.isArray(entry)) {
41
+ if (typeof originalEntry === 'object' && !Array.isArray(originalEntry)) {
36
42
  const clone = {};
37
43
 
38
- Object.keys(entry).forEach((key) => {
44
+ Object.keys(originalEntry).forEach((key) => {
39
45
  // entry[key] should be a string here
40
- clone[key] = prependEntry(entry[key]);
46
+ clone[key] = prependEntry(originalEntry[key], additionalEntries);
41
47
  });
42
48
 
43
49
  return clone;
@@ -45,8 +51,8 @@ function addEntries(config, options, server) {
45
51
 
46
52
  // in this case, entry is a string or an array.
47
53
  // make sure that we do not add duplicates.
48
- const entriesClone = entries.slice(0);
49
- [].concat(entry).forEach((newEntry) => {
54
+ const entriesClone = additionalEntries.slice(0);
55
+ [].concat(originalEntry).forEach((newEntry) => {
50
56
  if (!entriesClone.includes(newEntry)) {
51
57
  entriesClone.push(newEntry);
52
58
  }
@@ -54,9 +60,34 @@ function addEntries(config, options, server) {
54
60
  return entriesClone;
55
61
  };
56
62
 
63
+ // eslint-disable-next-line no-shadow
64
+ const checkInject = (option, config, defaultValue) => {
65
+ if (typeof option === 'boolean') return option;
66
+ if (typeof option === 'function') return option(config);
67
+ return defaultValue;
68
+ };
69
+
57
70
  // eslint-disable-next-line no-shadow
58
71
  [].concat(config).forEach((config) => {
59
- config.entry = prependEntry(config.entry || './src');
72
+ const webTarget =
73
+ config.target === 'web' ||
74
+ config.target === 'webworker' ||
75
+ config.target === 'electron-renderer' ||
76
+ config.target === 'node-webkit' ||
77
+ config.target == null;
78
+ const additionalEntries = checkInject(
79
+ options.injectClient,
80
+ config,
81
+ webTarget
82
+ )
83
+ ? [clientEntry]
84
+ : [];
85
+
86
+ if (hotEntry && checkInject(options.injectHot, config, true)) {
87
+ additionalEntries.push(hotEntry);
88
+ }
89
+
90
+ config.entry = prependEntry(config.entry || './src', additionalEntries);
60
91
 
61
92
  if (options.hot || options.hotOnly) {
62
93
  config.plugins = config.plugins || [];
@@ -2,8 +2,8 @@
2
2
 
3
3
  const selfsigned = require('selfsigned');
4
4
 
5
- function createCertificate(attrs) {
6
- return selfsigned.generate(attrs, {
5
+ function createCertificate(attributes) {
6
+ return selfsigned.generate(attributes, {
7
7
  algorithm: 'sha256',
8
8
  days: 30,
9
9
  keySize: 2048,
@@ -30,6 +30,22 @@ function createConfig(config, argv, { port }) {
30
30
  options.socket = argv.socket;
31
31
  }
32
32
 
33
+ if (argv.sockHost) {
34
+ options.sockHost = argv.sockHost;
35
+ }
36
+
37
+ if (argv.sockPath) {
38
+ options.sockPath = argv.sockPath;
39
+ }
40
+
41
+ if (argv.sockPort) {
42
+ options.sockPort = argv.sockPort;
43
+ }
44
+
45
+ if (argv.liveReload === false) {
46
+ options.liveReload = false;
47
+ }
48
+
33
49
  if (argv.progress) {
34
50
  options.progress = argv.progress;
35
51
  }
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+
3
+ module.exports = 8080;
@@ -1,35 +1,28 @@
1
1
  'use strict';
2
2
 
3
- const portfinder = require('portfinder');
4
-
5
- function runPortFinder(defaultPort, cb) {
6
- portfinder.basePort = defaultPort;
7
- portfinder.getPort((err, port) => {
8
- cb(err, port);
9
- });
10
- }
11
-
12
- function findPort(server, defaultPort, defaultPortRetry, fn) {
13
- let tryCount = 0;
14
- const portFinderRunCb = (err, port) => {
15
- tryCount += 1;
16
- fn(err, port);
17
- };
18
-
19
- server.listeningApp.on('error', (err) => {
20
- if (err && err.code !== 'EADDRINUSE') {
21
- throw err;
22
- }
23
-
24
- if (tryCount >= defaultPortRetry) {
25
- fn(err);
26
- return;
27
- }
28
-
29
- runPortFinder(defaultPort, portFinderRunCb);
3
+ const { getPortPromise } = require('portfinder');
4
+ const defaultPort = require('./defaultPort');
5
+ const defaultTo = require('./defaultTo');
6
+ const tryParseInt = require('./tryParseInt');
7
+
8
+ function findPort(port) {
9
+ if (typeof port !== 'undefined') {
10
+ return Promise.resolve(port);
11
+ }
12
+
13
+ // Try to find unused port and listen on it for 3 times,
14
+ // if port is not specified in options.
15
+ // Because NaN == null is false, defaultTo fails if parseInt returns NaN
16
+ // so the tryParseInt function is introduced to handle NaN
17
+ const defaultPortRetry = defaultTo(
18
+ tryParseInt(process.env.DEFAULT_PORT_RETRY),
19
+ 3
20
+ );
21
+
22
+ return getPortPromise({
23
+ port: defaultPort,
24
+ stopPort: defaultPort + defaultPortRetry,
30
25
  });
31
-
32
- runPortFinder(defaultPort, portFinderRunCb);
33
26
  }
34
27
 
35
28
  module.exports = findPort;
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+ const del = require('del');
6
+ const createCertificate = require('./createCertificate');
7
+
8
+ function getCertificate(logger) {
9
+ // Use a self-signed certificate if no certificate was configured.
10
+ // Cycle certs every 24 hours
11
+ const certificatePath = path.join(__dirname, '../../ssl/server.pem');
12
+
13
+ let certificateExists = fs.existsSync(certificatePath);
14
+
15
+ if (certificateExists) {
16
+ const certificateTtl = 1000 * 60 * 60 * 24;
17
+ const certificateStat = fs.statSync(certificatePath);
18
+
19
+ const now = new Date();
20
+
21
+ // cert is more than 30 days old, kill it with fire
22
+ if ((now - certificateStat.ctime) / certificateTtl > 30) {
23
+ logger.info('SSL Certificate is more than 30 days old. Removing.');
24
+
25
+ del.sync([certificatePath], { force: true });
26
+
27
+ certificateExists = false;
28
+ }
29
+ }
30
+
31
+ if (!certificateExists) {
32
+ logger.info('Generating SSL Certificate');
33
+
34
+ const attributes = [{ name: 'commonName', value: 'localhost' }];
35
+ const pems = createCertificate(attributes);
36
+
37
+ fs.writeFileSync(certificatePath, pems.private + pems.cert, {
38
+ encoding: 'utf8',
39
+ });
40
+ }
41
+
42
+ return fs.readFileSync(certificatePath);
43
+ }
44
+
45
+ module.exports = getCertificate;
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const createConfig = require('./createConfig');
4
+ const defaultPort = require('./defaultPort');
5
+
6
+ function processOptions(config, argv, callback) {
7
+ // processOptions {Promise}
8
+ if (typeof config.then === 'function') {
9
+ config
10
+ .then((conf) => processOptions(conf, argv, callback))
11
+ .catch((err) => {
12
+ // eslint-disable-next-line no-console
13
+ console.error(err.stack || err);
14
+ // eslint-disable-next-line no-process-exit
15
+ process.exit(1);
16
+ });
17
+
18
+ return;
19
+ }
20
+
21
+ // Taken out of yargs because we must know if
22
+ // it wasn't given by the user, in which case
23
+ // we should use portfinder.
24
+ const options = createConfig(config, argv, { port: defaultPort });
25
+
26
+ callback(config, options);
27
+ }
28
+
29
+ module.exports = processOptions;
@@ -0,0 +1,103 @@
1
+ 'use strict';
2
+
3
+ const { createReadStream } = require('fs');
4
+ const { join } = require('path');
5
+
6
+ function routes(app, middleware, options) {
7
+ app.get('/__webpack_dev_server__/live.bundle.js', (req, res) => {
8
+ res.setHeader('Content-Type', 'application/javascript');
9
+
10
+ createReadStream(
11
+ join(__dirname, '..', '..', 'client', 'live.bundle.js')
12
+ ).pipe(res);
13
+ });
14
+
15
+ app.get('/__webpack_dev_server__/sockjs.bundle.js', (req, res) => {
16
+ res.setHeader('Content-Type', 'application/javascript');
17
+
18
+ createReadStream(
19
+ join(__dirname, '..', '..', 'client', 'sockjs.bundle.js')
20
+ ).pipe(res);
21
+ });
22
+
23
+ app.get('/webpack-dev-server.js', (req, res) => {
24
+ res.setHeader('Content-Type', 'application/javascript');
25
+
26
+ createReadStream(
27
+ join(__dirname, '..', '..', 'client', 'index.bundle.js')
28
+ ).pipe(res);
29
+ });
30
+
31
+ app.get('/webpack-dev-server/*', (req, res) => {
32
+ res.setHeader('Content-Type', 'text/html');
33
+
34
+ createReadStream(join(__dirname, '..', '..', 'client', 'live.html')).pipe(
35
+ res
36
+ );
37
+ });
38
+
39
+ app.get('/webpack-dev-server', (req, res) => {
40
+ res.setHeader('Content-Type', 'text/html');
41
+
42
+ res.write(
43
+ '<!DOCTYPE html><html><head><meta charset="utf-8"/></head><body>'
44
+ );
45
+
46
+ const outputPath = middleware.getFilenameFromUrl(options.publicPath || '/');
47
+ const filesystem = middleware.fileSystem;
48
+
49
+ writeDirectory(options.publicPath || '/', outputPath);
50
+
51
+ res.end('</body></html>');
52
+
53
+ function writeDirectory(baseUrl, basePath) {
54
+ const content = filesystem.readdirSync(basePath);
55
+
56
+ res.write('<ul>');
57
+
58
+ content.forEach((item) => {
59
+ const p = `${basePath}/${item}`;
60
+
61
+ if (filesystem.statSync(p).isFile()) {
62
+ res.write('<li><a href="');
63
+ res.write(baseUrl + item);
64
+ res.write('">');
65
+ res.write(item);
66
+ res.write('</a></li>');
67
+
68
+ if (/\.js$/.test(item)) {
69
+ const html = item.substr(0, item.length - 3);
70
+
71
+ res.write('<li><a href="');
72
+ res.write(baseUrl + html);
73
+ res.write('">');
74
+ res.write(html);
75
+ res.write('</a> (magic html for ');
76
+ res.write(item);
77
+ res.write(') (<a href="');
78
+ res.write(
79
+ baseUrl.replace(
80
+ // eslint-disable-next-line
81
+ /(^(https?:\/\/[^\/]+)?\/)/,
82
+ '$1webpack-dev-server/'
83
+ ) + html
84
+ );
85
+ res.write('">webpack-dev-server</a>)</li>');
86
+ }
87
+ } else {
88
+ res.write('<li>');
89
+ res.write(item);
90
+ res.write('<br>');
91
+
92
+ writeDirectory(`${baseUrl + item}/`, p);
93
+
94
+ res.write('</li>');
95
+ }
96
+ });
97
+
98
+ res.write('</ul>');
99
+ }
100
+ });
101
+ }
102
+
103
+ module.exports = routes;
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ const open = require('opn');
4
+
5
+ function runOpen(uri, options, log) {
6
+ let openOptions = {};
7
+ let openMessage = 'Unable to open browser';
8
+
9
+ if (typeof options.open === 'string') {
10
+ openOptions = { app: options.open };
11
+ openMessage += `: ${options.open}`;
12
+ }
13
+
14
+ open(`${uri}${options.openPage || ''}`, openOptions).catch(() => {
15
+ log.warn(
16
+ `${openMessage}. If you are running in a headless environment, please do not use the --open flag`
17
+ );
18
+ });
19
+ }
20
+
21
+ module.exports = runOpen;
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ const signals = ['SIGINT', 'SIGTERM'];
4
+
5
+ function setupExitSignals(server) {
6
+ signals.forEach((signal) => {
7
+ process.on(signal, () => {
8
+ if (server) {
9
+ server.close(() => {
10
+ // eslint-disable-next-line no-process-exit
11
+ process.exit();
12
+ });
13
+ } else {
14
+ // eslint-disable-next-line no-process-exit
15
+ process.exit();
16
+ }
17
+ });
18
+ });
19
+ }
20
+
21
+ module.exports = setupExitSignals;
@@ -1,8 +1,9 @@
1
1
  'use strict';
2
2
 
3
- const open = require('opn');
4
3
  const colors = require('./colors');
4
+ const runOpen = require('./runOpen');
5
5
 
6
+ // TODO: don't emit logs when webpack-dev-server is used via Node.js API
6
7
  function status(uri, options, log, useColor) {
7
8
  const contentBase = Array.isArray(options.contentBase)
8
9
  ? options.contentBase.join(', ')
@@ -43,19 +44,7 @@ function status(uri, options, log, useColor) {
43
44
  }
44
45
 
45
46
  if (options.open) {
46
- let openOptions = {};
47
- let openMessage = 'Unable to open browser';
48
-
49
- if (typeof options.open === 'string') {
50
- openOptions = { app: options.open };
51
- openMessage += `: ${options.open}`;
52
- }
53
-
54
- open(uri + (options.openPage || ''), openOptions).catch(() => {
55
- log.warn(
56
- `${openMessage}. If you are running in a headless environment, please do not use the --open flag`
57
- );
58
- });
47
+ runOpen(uri, options, log);
59
48
  }
60
49
  }
61
50
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpack-dev-server",
3
- "version": "3.3.1",
3
+ "version": "3.5.1",
4
4
  "description": "Serves a webpack app. Updates the browser on changes.",
5
5
  "bin": "bin/webpack-dev-server.js",
6
6
  "main": "lib/Server.js",
@@ -14,11 +14,18 @@
14
14
  "node": ">= 6.11.5"
15
15
  },
16
16
  "scripts": {
17
- "lint": "eslint bin lib test examples client-src",
18
- "pretty": "prettier --loglevel warn --write \"**/*.{js,css,md,json,yml}\"",
19
- "test": "jest --runInBand",
17
+ "lint:prettier": "prettier \"{**/*,*}.{js,json,md,yml,css}\" --list-different",
18
+ "lint:js": "eslint . --cache",
19
+ "lint": "npm-run-all -l -p \"lint:**\"",
20
+ "commitlint": "commitlint --from=master",
21
+ "security": "npm audit",
22
+ "test:only": "jest --runInBand",
23
+ "test:coverage": "npm run test:only -- --coverage",
24
+ "test:watch": "npm run test:coverage --watch",
25
+ "test": "npm run test:coverage",
26
+ "pretest": "npm run lint",
20
27
  "prepare": "rimraf ./ssl/*.pem && npm run -s transpile:index && npm run -s build:live && npm run -s build:index && npm run -s build:sockjs",
21
- "transpile:index": "babel client-src/default --out-dir client --ignore *.config.js",
28
+ "transpile:index": "babel client-src/default --out-dir client --ignore \"./client-src/default/*.config.js\"",
22
29
  "build:index": "webpack ./client-src/default/index.js -o client/index.bundle.js --color --config client-src/default/webpack.config.js",
23
30
  "build:live": "webpack ./client-src/live/index.js -o client/live.bundle.js --color --config client-src/live/webpack.config.js",
24
31
  "build:sockjs": "webpack ./client-src/sockjs/index.js -o client/sockjs.bundle.js --color --config client-src/sockjs/webpack.config.js",
@@ -28,24 +35,24 @@
28
35
  "dependencies": {
29
36
  "ansi-html": "0.0.7",
30
37
  "bonjour": "^3.5.0",
31
- "chokidar": "^2.1.5",
38
+ "chokidar": "^2.1.6",
32
39
  "compression": "^1.7.4",
33
40
  "connect-history-api-fallback": "^1.6.0",
34
41
  "debug": "^4.1.1",
35
- "del": "^4.1.0",
36
- "express": "^4.16.4",
42
+ "del": "^4.1.1",
43
+ "express": "^4.17.1",
37
44
  "html-entities": "^1.2.1",
38
45
  "http-proxy-middleware": "^0.19.1",
39
46
  "import-local": "^2.0.0",
40
- "internal-ip": "^4.2.0",
47
+ "internal-ip": "^4.3.0",
41
48
  "ip": "^1.1.5",
42
49
  "killable": "^1.0.1",
43
- "loglevel": "^1.6.1",
50
+ "loglevel": "^1.6.2",
44
51
  "opn": "^5.5.0",
45
52
  "portfinder": "^1.0.20",
46
53
  "schema-utils": "^1.0.0",
47
54
  "selfsigned": "^1.10.4",
48
- "semver": "^6.0.0",
55
+ "semver": "^6.1.1",
49
56
  "serve-index": "^1.9.1",
50
57
  "sockjs": "0.3.19",
51
58
  "sockjs-client": "1.3.0",
@@ -53,64 +60,54 @@
53
60
  "strip-ansi": "^3.0.1",
54
61
  "supports-color": "^6.1.0",
55
62
  "url": "^0.11.0",
56
- "webpack-dev-middleware": "^3.6.2",
63
+ "webpack-dev-middleware": "^3.7.0",
57
64
  "webpack-log": "^2.0.0",
58
65
  "yargs": "12.0.5"
59
66
  },
60
67
  "devDependencies": {
61
- "@babel/cli": "7.4.3",
62
- "@babel/core": "7.4.3",
63
- "@babel/preset-env": "7.4.3",
64
- "babel-loader": "8.0.5",
65
- "copy-webpack-plugin": "5.0.2",
66
- "css-loader": "2.1.1",
67
- "eslint": "5.16.0",
68
- "eslint-config-prettier": "4.1.0",
69
- "eslint-config-webpack": "1.2.5",
70
- "eslint-plugin-import": "2.16.0",
71
- "eslint-plugin-prettier": "3.0.1",
72
- "execa": "1.0.0",
73
- "file-loader": "3.0.1",
74
- "html-loader": "0.5.5",
75
- "html-webpack-plugin": "3.2.0",
76
- "husky": "1.3.1",
77
- "jest": "24.7.1",
78
- "jquery": "3.3.1",
79
- "less": "3.9.0",
80
- "less-loader": "4.1.0",
81
- "lint-staged": "8.1.5",
82
- "marked": "0.6.2",
83
- "nyc": "13.3.0",
84
- "prettier": "1.16.4",
85
- "puppeteer": "1.14.0",
86
- "rimraf": "2.6.3",
87
- "standard-version": "5.0.2",
88
- "style-loader": "0.23.1",
89
- "supertest": "4.0.2",
90
- "url-loader": "1.1.2",
91
- "webpack": "4.29.6",
92
- "webpack-cli": "3.3.0",
93
- "ws": "6.2.1"
68
+ "@babel/cli": "^7.4.4",
69
+ "@babel/core": "^7.4.5",
70
+ "@babel/preset-env": "^7.4.5",
71
+ "@commitlint/cli": "^7.6.1",
72
+ "@commitlint/config-conventional": "^7.6.0",
73
+ "babel-loader": "^8.0.6",
74
+ "body-parser": "^1.19.0",
75
+ "commitlint-azure-pipelines-cli": "^1.0.1",
76
+ "copy-webpack-plugin": "^5.0.3",
77
+ "css-loader": "^2.1.1",
78
+ "eslint": "^5.16.0",
79
+ "eslint-config-prettier": "^4.3.0",
80
+ "eslint-config-webpack": "^1.2.5",
81
+ "eslint-plugin-import": "^2.17.3",
82
+ "execa": "^1.0.0",
83
+ "file-loader": "^3.0.1",
84
+ "html-loader": "^0.5.5",
85
+ "html-webpack-plugin": "^3.2.0",
86
+ "husky": "^2.3.0",
87
+ "jest": "^24.8.0",
88
+ "jest-junit": "^6.4.0",
89
+ "jquery": "^3.4.1",
90
+ "less": "^3.9.0",
91
+ "less-loader": "^5.0.0",
92
+ "lint-staged": "^8.1.7",
93
+ "marked": "^0.6.2",
94
+ "memfs": "^2.15.4",
95
+ "npm-run-all": "^4.1.5",
96
+ "nyc": "^14.1.1",
97
+ "prettier": "^1.17.1",
98
+ "puppeteer": "^1.17.0",
99
+ "rimraf": "^2.6.3",
100
+ "standard-version": "^6.0.1",
101
+ "style-loader": "^0.23.1",
102
+ "supertest": "^4.0.2",
103
+ "url-loader": "^1.1.2",
104
+ "webpack": "^4.32.2",
105
+ "webpack-cli": "^3.3.2",
106
+ "ws": "^6.2.1"
94
107
  },
95
108
  "peerDependencies": {
96
109
  "webpack": "^4.0.0"
97
110
  },
98
- "husky": {
99
- "hooks": {
100
- "pre-commit": "lint-staged"
101
- }
102
- },
103
- "lint-staged": {
104
- "*.js": [
105
- "eslint --fix",
106
- "prettier --write",
107
- "git add"
108
- ],
109
- "*.{css,md,json,yml}": [
110
- "prettier --write",
111
- "git add"
112
- ]
113
- },
114
111
  "author": "Tobias Koppers @sokra",
115
112
  "bugs": "https://github.com/webpack/webpack-dev-server/issues",
116
113
  "homepage": "https://github.com/webpack/webpack-dev-server#readme",
@@ -1,14 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = {
4
- mode: 'production',
5
- module: {
6
- rules: [{
7
- test: /\.js$/,
8
- exclude: /node_modules|web_modules/,
9
- use: [{
10
- loader: 'babel-loader'
11
- }]
12
- }]
13
- }
14
- };