Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: webpack/webpack-dev-server
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.13.3
Choose a base ref
...
head repository: webpack/webpack-dev-server
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.14.0
Choose a head ref

Commits on Apr 17, 2023

  1. chore(deps): bump colorette from 2.0.19 to 2.0.20 (#4820)

    Bumps [colorette](https://github.com/jorgebucaran/colorette) from 2.0.19 to 2.0.20.
    - [Release notes](https://github.com/jorgebucaran/colorette/releases)
    - [Commits](jorgebucaran/colorette@2.0.19...2.0.20)
    
    ---
    updated-dependencies:
    - dependency-name: colorette
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 17, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f479dad View commit details
  2. chore(deps): bump schema-utils from 4.0.0 to 4.0.1 (#4819)

    Bumps [schema-utils](https://github.com/webpack/schema-utils) from 4.0.0 to 4.0.1.
    - [Release notes](https://github.com/webpack/schema-utils/releases)
    - [Changelog](https://github.com/webpack/schema-utils/blob/master/CHANGELOG.md)
    - [Commits](webpack/schema-utils@v4.0.0...v4.0.1)
    
    ---
    updated-dependencies:
    - dependency-name: schema-utils
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 17, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6f84d7b View commit details

Commits on Apr 21, 2023

  1. chore(deps-dev): bump memfs from 3.5.0 to 3.5.1 (#4824)

    Bumps [memfs](https://github.com/streamich/memfs) from 3.5.0 to 3.5.1.
    - [Release notes](https://github.com/streamich/memfs/releases)
    - [Changelog](https://github.com/streamich/memfs/blob/master/CHANGELOG.md)
    - [Commits](streamich/memfs@v3.5.0...v3.5.1)
    
    ---
    updated-dependencies:
    - dependency-name: memfs
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 21, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d0a2e48 View commit details
  2. chore(deps-dev): bump @types/node from 18.15.11 to 18.15.13 (#4825)

    Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.15.11 to 18.15.13.
    - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
    - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
    
    ---
    updated-dependencies:
    - dependency-name: "@types/node"
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 21, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ee68eab View commit details

Commits on Apr 22, 2023

  1. chore(deps-dev): bump webpack from 5.79.0 to 5.80.0 (#4823)

    Bumps [webpack](https://github.com/webpack/webpack) from 5.79.0 to 5.80.0.
    - [Release notes](https://github.com/webpack/webpack/releases)
    - [Commits](webpack/webpack@v5.79.0...v5.80.0)
    
    ---
    updated-dependencies:
    - dependency-name: webpack
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...
    dependabot[bot] authored Apr 22, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1e93404 View commit details

Commits on Apr 24, 2023

  1. chore(deps-dev): bump prettier from 2.8.7 to 2.8.8 (#4830)

    Bumps [prettier](https://github.com/prettier/prettier) from 2.8.7 to 2.8.8.
    - [Release notes](https://github.com/prettier/prettier/releases)
    - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
    - [Commits](prettier/prettier@2.8.7...2.8.8)
    
    ---
    updated-dependencies:
    - dependency-name: prettier
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 24, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7294675 View commit details
  2. chore(deps-dev): bump @types/node from 18.15.13 to 18.16.0 (#4829)

    Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.15.13 to 18.16.0.
    - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
    - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
    
    ---
    updated-dependencies:
    - dependency-name: "@types/node"
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 24, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6682bc2 View commit details

Commits on Apr 26, 2023

  1. chore(deps-dev): bump @types/node from 18.16.0 to 18.16.1 (#4832)

    Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.16.0 to 18.16.1.
    - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
    - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
    
    ---
    updated-dependencies:
    - dependency-name: "@types/node"
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 26, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ef7f6c5 View commit details

Commits on Apr 27, 2023

  1. chore(deps-dev): bump eslint from 8.38.0 to 8.39.0 (#4831)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.38.0 to 8.39.0.
    - [Release notes](https://github.com/eslint/eslint/releases)
    - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
    - [Commits](eslint/eslint@v8.38.0...v8.39.0)
    
    ---
    updated-dependencies:
    - dependency-name: eslint
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 27, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c908cc2 View commit details

Commits on Apr 28, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    273627b View commit details
  2. chore(deps-dev): bump @types/node from 18.16.1 to 18.16.2 (#4835)

    Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.16.1 to 18.16.2.
    - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
    - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
    
    ---
    updated-dependencies:
    - dependency-name: "@types/node"
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 28, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    53bb4d7 View commit details

Commits on Apr 29, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    bb4a5d9 View commit details

Commits on May 1, 2023

  1. chore(deps-dev): bump @types/node from 18.16.2 to 18.16.3 (#4838)

    Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 18.16.2 to 18.16.3.
    - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
    - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
    
    ---
    updated-dependencies:
    - dependency-name: "@types/node"
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored May 1, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3477ef3 View commit details

Commits on May 2, 2023

  1. chore(deps-dev): bump @babel/cli from 7.21.0 to 7.21.5 (#4839)

    Bumps [@babel/cli](https://github.com/babel/babel/tree/HEAD/packages/babel-cli) from 7.21.0 to 7.21.5.
    - [Release notes](https://github.com/babel/babel/releases)
    - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/babel/babel/commits/v7.21.5/packages/babel-cli)
    
    ---
    updated-dependencies:
    - dependency-name: "@babel/cli"
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored May 2, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    99ce405 View commit details
  2. chore(deps): bump @types/connect-history-api-fallback (#4836)

    Bumps [@types/connect-history-api-fallback](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/connect-history-api-fallback) from 1.3.5 to 1.5.0.
    - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
    - [Changelog](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/connect-history-api-fallback/connect-history-api-fallback-tests.ts)
    - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/connect-history-api-fallback)
    
    ---
    updated-dependencies:
    - dependency-name: "@types/connect-history-api-fallback"
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored May 2, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    35b57c0 View commit details
  3. chore(deps-dev): bump @babel/preset-env from 7.21.4 to 7.21.5 (#4842)

    Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.21.4 to 7.21.5.
    - [Release notes](https://github.com/babel/babel/releases)
    - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/babel/babel/commits/v7.21.5/packages/babel-preset-env)
    
    ---
    updated-dependencies:
    - dependency-name: "@babel/preset-env"
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored May 2, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    71d4e4b View commit details
  4. chore(deps-dev): bump @babel/core from 7.21.4 to 7.21.5 (#4840)

    Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.21.4 to 7.21.5.
    - [Release notes](https://github.com/babel/babel/releases)
    - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/babel/babel/commits/v7.21.5/packages/babel-core)
    
    ---
    updated-dependencies:
    - dependency-name: "@babel/core"
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored May 2, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    90bd7ca View commit details

Commits on May 3, 2023

  1. chore(deps-dev): bump @babel/core from 7.21.5 to 7.21.8 (#4844)

    Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.21.5 to 7.21.8.
    - [Release notes](https://github.com/babel/babel/releases)
    - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/babel/babel/commits/v7.21.8/packages/babel-core)
    
    ---
    updated-dependencies:
    - dependency-name: "@babel/core"
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored May 3, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    37cad89 View commit details
  2. chore(deps-dev): bump @babel/eslint-parser from 7.21.3 to 7.21.8 (#4843)

    Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.21.3 to 7.21.8.
    - [Release notes](https://github.com/babel/babel/releases)
    - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/babel/babel/commits/v7.21.8/eslint/babel-eslint-parser)
    
    ---
    updated-dependencies:
    - dependency-name: "@babel/eslint-parser"
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored May 3, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1aef67c View commit details
  3. chore(deps-dev): bump @babel/runtime from 7.21.0 to 7.21.5 (#4841)

    Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.21.0 to 7.21.5.
    - [Release notes](https://github.com/babel/babel/releases)
    - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/babel/babel/commits/v7.21.5/packages/babel-runtime)
    
    ---
    updated-dependencies:
    - dependency-name: "@babel/runtime"
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored May 3, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    217e156 View commit details

Commits on May 4, 2023

  1. chore(deps-dev): bump webpack from 5.81.0 to 5.82.0 (#4845)

    Bumps [webpack](https://github.com/webpack/webpack) from 5.81.0 to 5.82.0.
    - [Release notes](https://github.com/webpack/webpack/releases)
    - [Commits](webpack/webpack@v5.81.0...v5.82.0)
    
    ---
    updated-dependencies:
    - dependency-name: webpack
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored May 4, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ee748a7 View commit details

Commits on May 6, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    aab01b3 View commit details
  2. Copy the full SHA
    51f8a1b View commit details
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,14 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [4.14.0](https://github.com/webpack/webpack-dev-server/compare/v4.13.3...v4.14.0) (2023-05-06)


### Features

* allow CLI to be ESM ([#4837](https://github.com/webpack/webpack-dev-server/issues/4837)) ([bb4a5d9](https://github.com/webpack/webpack-dev-server/commit/bb4a5d9e8f87a89c81d4024085ff6c9ebb6c551b))
* allow filter overlay errors/warnings with function ([#4813](https://github.com/webpack/webpack-dev-server/issues/4813)) ([aab01b3](https://github.com/webpack/webpack-dev-server/commit/aab01b3c4e4fb9ca9ae1c1bbc860a52a06026de6))

### [4.13.3](https://github.com/webpack/webpack-dev-server/compare/v4.13.2...v4.13.3) (2023-04-15)


14 changes: 12 additions & 2 deletions bin/webpack-dev-server.js
Original file line number Diff line number Diff line change
@@ -85,8 +85,18 @@ const runCli = (cli) => {
const pkgPath = require.resolve(`${cli.package}/package.json`);
// eslint-disable-next-line import/no-dynamic-require
const pkg = require(pkgPath);
// eslint-disable-next-line import/no-dynamic-require
require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName]));

if (pkg.type === "module" || /\.mjs/i.test(pkg.bin[cli.binName])) {
import(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName])).catch(
(error) => {
console.error(error);
process.exitCode = 1;
}
);
} else {
// eslint-disable-next-line import/no-dynamic-require
require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName]));
}
};

/**
79 changes: 64 additions & 15 deletions client-src/index.js
Original file line number Diff line number Diff line change
@@ -10,12 +10,20 @@ import sendMessage from "./utils/sendMessage.js";
import reloadApp from "./utils/reloadApp.js";
import createSocketURL from "./utils/createSocketURL.js";

/**
* @typedef {Object} OverlayOptions
* @property {boolean | (error: Error) => boolean} [warnings]
* @property {boolean | (error: Error) => boolean} [errors]
* @property {boolean | (error: Error) => boolean} [runtimeErrors]
* @property {string} [trustedTypesPolicyName]
*/

/**
* @typedef {Object} Options
* @property {boolean} hot
* @property {boolean} liveReload
* @property {boolean} progress
* @property {boolean | { warnings?: boolean, errors?: boolean, runtimeErrors?: boolean, trustedTypesPolicyName?: string }} overlay
* @property {boolean | OverlayOptions} overlay
* @property {string} [logging]
* @property {number} [reconnect]
*/
@@ -27,6 +35,30 @@ import createSocketURL from "./utils/createSocketURL.js";
* @property {string} [previousHash]
*/

/**
* @param {boolean | { warnings?: boolean | string; errors?: boolean | string; runtimeErrors?: boolean | string; }} overlayOptions
*/
const decodeOverlayOptions = (overlayOptions) => {
if (typeof overlayOptions === "object") {
["warnings", "errors", "runtimeErrors"].forEach((property) => {
if (typeof overlayOptions[property] === "string") {
const overlayFilterFunctionString = decodeURIComponent(
overlayOptions[property]
);

// eslint-disable-next-line no-new-func
const overlayFilterFunction = new Function(
"message",
`var callback = ${overlayFilterFunctionString}
return callback(message)`
);

overlayOptions[property] = overlayFilterFunction;
}
});
}
};

/**
* @type {Status}
*/
@@ -83,6 +115,8 @@ if (parsedResourceQuery.overlay) {
runtimeErrors: true,
...options.overlay,
};

decodeOverlayOptions(options.overlay);
}
enabledFeatures.Overlay = true;
}
@@ -173,6 +207,7 @@ const onSocketMessage = {
}

options.overlay = value;
decodeOverlayOptions(options.overlay);
},
/**
* @param {number} value
@@ -266,17 +301,24 @@ const onSocketMessage = {
log.warn(printableWarnings[i]);
}

const needShowOverlayForWarnings =
const overlayWarningsSetting =
typeof options.overlay === "boolean"
? options.overlay
: options.overlay && options.overlay.warnings;

if (needShowOverlayForWarnings) {
overlay.send({
type: "BUILD_ERROR",
level: "warning",
messages: warnings,
});
if (overlayWarningsSetting) {
const warningsToDisplay =
typeof overlayWarningsSetting === "function"
? warnings.filter(overlayWarningsSetting)
: warnings;

if (warningsToDisplay.length) {
overlay.send({
type: "BUILD_ERROR",
level: "warning",
messages: warnings,
});
}
}

if (params && params.preventReloading) {
@@ -303,17 +345,24 @@ const onSocketMessage = {
log.error(printableErrors[i]);
}

const needShowOverlayForErrors =
const overlayErrorsSettings =
typeof options.overlay === "boolean"
? options.overlay
: options.overlay && options.overlay.errors;

if (needShowOverlayForErrors) {
overlay.send({
type: "BUILD_ERROR",
level: "error",
messages: errors,
});
if (overlayErrorsSettings) {
const errorsToDisplay =
typeof overlayErrorsSettings === "function"
? errors.filter(overlayErrorsSettings)
: errors;

if (errorsToDisplay.length) {
overlay.send({
type: "BUILD_ERROR",
level: "error",
messages: errors,
});
}
}
},
/**
44 changes: 30 additions & 14 deletions client-src/overlay.js
Original file line number Diff line number Diff line change
@@ -78,7 +78,7 @@ function formatProblem(type, item) {
/**
* @typedef {Object} CreateOverlayOptions
* @property {string | null} trustedTypesPolicyName
* @property {boolean} [catchRuntimeError]
* @property {boolean | (error: Error) => void} [catchRuntimeError]
*/

/**
@@ -90,6 +90,8 @@ const createOverlay = (options) => {
let iframeContainerElement;
/** @type {HTMLDivElement | null | undefined} */
let containerElement;
/** @type {HTMLDivElement | null | undefined} */
let headerElement;
/** @type {Array<(element: HTMLDivElement) => void>} */
let onLoadQueue = [];
/** @type {TrustedTypePolicy | undefined} */
@@ -124,6 +126,7 @@ const createOverlay = (options) => {
iframeContainerElement.id = "webpack-dev-server-client-overlay";
iframeContainerElement.src = "about:blank";
applyStyle(iframeContainerElement, iframeStyle);

iframeContainerElement.onload = () => {
const contentElement =
/** @type {Document} */
@@ -141,7 +144,7 @@ const createOverlay = (options) => {
contentElement.id = "webpack-dev-server-client-overlay-div";
applyStyle(contentElement, containerStyle);

const headerElement = document.createElement("div");
headerElement = document.createElement("div");

headerElement.innerText = "Compiled with problems:";
applyStyle(headerElement, headerStyle);
@@ -219,9 +222,15 @@ const createOverlay = (options) => {
* @param {string} type
* @param {Array<string | { moduleIdentifier?: string, moduleName?: string, loc?: string, message?: string }>} messages
* @param {string | null} trustedTypesPolicyName
* @param {'build' | 'runtime'} messageSource
*/
function show(type, messages, trustedTypesPolicyName) {
function show(type, messages, trustedTypesPolicyName, messageSource) {
ensureOverlayExists(() => {
headerElement.innerText =
messageSource === "runtime"
? "Uncaught runtime errors:"
: "Compiled with problems:";

messages.forEach((message) => {
const entryElement = document.createElement("div");
const msgStyle =
@@ -267,8 +276,8 @@ const createOverlay = (options) => {
}

const overlayService = createOverlayMachine({
showOverlay: ({ level = "error", messages }) =>
show(level, messages, options.trustedTypesPolicyName),
showOverlay: ({ level = "error", messages, messageSource }) =>
show(level, messages, options.trustedTypesPolicyName, messageSource),
hideOverlay: hide,
});

@@ -284,15 +293,22 @@ const createOverlay = (options) => {
const errorObject =
error instanceof Error ? error : new Error(error || message);

overlayService.send({
type: "RUNTIME_ERROR",
messages: [
{
message: errorObject.message,
stack: parseErrorToStacks(errorObject),
},
],
});
const shouldDisplay =
typeof options.catchRuntimeError === "function"
? options.catchRuntimeError(errorObject)
: true;

if (shouldDisplay) {
overlayService.send({
type: "RUNTIME_ERROR",
messages: [
{
message: errorObject.message,
stack: parseErrorToStacks(errorObject),
},
],
});
}
});
}

5 changes: 5 additions & 0 deletions client-src/overlay/state-machine.js
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import createMachine from "./fsm.js";
* @typedef {Object} ShowOverlayData
* @property {'warning' | 'error'} level
* @property {Array<string | { moduleIdentifier?: string, moduleName?: string, loc?: string, message?: string }>} messages
* @property {'build' | 'runtime'} messageSource
*/

/**
@@ -23,6 +24,7 @@ const createOverlayMachine = (options) => {
context: {
level: "error",
messages: [],
messageSource: "build",
},
states: {
hidden: {
@@ -73,18 +75,21 @@ const createOverlayMachine = (options) => {
return {
messages: [],
level: "error",
messageSource: "build",
};
},
appendMessages: (context, event) => {
return {
messages: context.messages.concat(event.messages),
level: event.level || context.level,
messageSource: event.type === "RUNTIME_ERROR" ? "runtime" : "build",
};
},
setMessages: (context, event) => {
return {
messages: event.messages,
level: event.level || context.level,
messageSource: event.type === "RUNTIME_ERROR" ? "runtime" : "build",
};
},
hideOverlay,
10 changes: 9 additions & 1 deletion examples/client/overlay/app.js
Original file line number Diff line number Diff line change
@@ -5,7 +5,15 @@ const createErrorBtn = require("./error-button");

const target = document.querySelector("#target");

target.insertAdjacentElement("afterend", createErrorBtn());
target.insertAdjacentElement(
"afterend",
createErrorBtn("Click to throw error", "Error message thrown from JS")
);

target.insertAdjacentElement(
"afterend",
createErrorBtn("Click to throw ignored error", "something something")
);

// eslint-disable-next-line import/no-unresolved, import/extensions
const invalid = require("./invalid.js");
22 changes: 14 additions & 8 deletions examples/client/overlay/error-button.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
"use strict";

function unsafeOperation() {
throw new Error("Error message thrown from JS");
}
/**
*
* @param {string} label
* @param {string} errorMessage
* @returns HTMLButtonElement
*/
module.exports = function createErrorButton(label, errorMessage) {
function unsafeOperation() {
throw new Error(errorMessage);
}

function handleButtonClick() {
unsafeOperation();
}
function handleButtonClick() {
unsafeOperation();
}

module.exports = function createErrorButton() {
const errorBtn = document.createElement("button");

errorBtn.addEventListener("click", handleButtonClick);
errorBtn.innerHTML = "Click to throw error";
errorBtn.innerHTML = label;

return errorBtn;
};
21 changes: 20 additions & 1 deletion examples/client/overlay/webpack.config.js
Original file line number Diff line number Diff line change
@@ -10,7 +10,26 @@ module.exports = setup({
entry: "./app.js",
devServer: {
client: {
overlay: true,
overlay: {
warnings: false,
runtimeErrors: (msg) => {
if (msg) {
let msgString;

if (msg instanceof Error) {
msgString = msg.message;
} else if (typeof msg === "string") {
msgString = msg;
}

if (msgString) {
return !/something/i.test(msgString);
}
}

return true;
},
},
},
},
// uncomment to test for IE
51 changes: 44 additions & 7 deletions lib/Server.js
Original file line number Diff line number Diff line change
@@ -154,10 +154,14 @@ const schema = require("./options.json");
* @property {string} [username]
*/

/**
* @typedef {boolean | ((error: Error) => void)} OverlayMessageOptions
*/

/**
* @typedef {Object} ClientConfiguration
* @property {"log" | "info" | "warn" | "error" | "none" | "verbose"} [logging]
* @property {boolean | { warnings?: boolean, errors?: boolean, runtimeErrors?: boolean }} [overlay]
* @property {boolean | { warnings?: OverlayMessageOptions, errors?: OverlayMessageOptions, runtimeErrors?: OverlayMessageOptions }} [overlay]
* @property {boolean} [progress]
* @property {boolean | number} [reconnect]
* @property {"ws" | "sockjs" | string} [webSocketTransport]
@@ -236,6 +240,16 @@ const memoize = (fn) => {

const getExpress = memoize(() => require("express"));

/**
*
* @param {OverlayMessageOptions} [setting]
* @returns
*/
const encodeOverlaySettings = (setting) =>
typeof setting === "function"
? encodeURIComponent(setting.toString())
: setting;

class Server {
/**
* @param {Configuration | Compiler | MultiCompiler} options
@@ -654,12 +668,19 @@ class Server {
}

if (typeof client.overlay !== "undefined") {
searchParams.set(
"overlay",
const overlayString =
typeof client.overlay === "boolean"
? String(client.overlay)
: JSON.stringify(client.overlay)
);
: JSON.stringify({
...client.overlay,
errors: encodeOverlaySettings(client.overlay.errors),
warnings: encodeOverlaySettings(client.overlay.warnings),
runtimeErrors: encodeOverlaySettings(
client.overlay.runtimeErrors
),
});

searchParams.set("overlay", overlayString);
}

if (typeof client.reconnect !== "undefined") {
@@ -2627,11 +2648,27 @@ class Server {
/** @type {ClientConfiguration} */
(this.options.client).overlay
) {
const overlayConfig = /** @type {ClientConfiguration} */ (
this.options.client
).overlay;

this.sendMessage(
[client],
"overlay",
/** @type {ClientConfiguration} */
(this.options.client).overlay
typeof overlayConfig === "object"
? {
...overlayConfig,
errors:
overlayConfig.errors &&
encodeOverlaySettings(overlayConfig.errors),
warnings:
overlayConfig.warnings &&
encodeOverlaySettings(overlayConfig.warnings),
runtimeErrors:
overlayConfig.runtimeErrors &&
encodeOverlaySettings(overlayConfig.runtimeErrors),
}
: overlayConfig
);
}

54 changes: 39 additions & 15 deletions lib/options.json
Original file line number Diff line number Diff line change
@@ -98,25 +98,49 @@
"additionalProperties": false,
"properties": {
"errors": {
"description": "Enables a full-screen overlay in the browser when there are compiler errors.",
"type": "boolean",
"cli": {
"negatedDescription": "Disables the full-screen overlay in the browser when there are compiler errors."
}
"anyOf": [
{
"description": "Enables a full-screen overlay in the browser when there are compiler errors.",
"type": "boolean",
"cli": {
"negatedDescription": "Disables the full-screen overlay in the browser when there are compiler errors."
}
},
{
"instanceof": "Function",
"description": "Filter compiler errors. Return true to include and return false to exclude."
}
]
},
"warnings": {
"description": "Enables a full-screen overlay in the browser when there are compiler warnings.",
"type": "boolean",
"cli": {
"negatedDescription": "Disables the full-screen overlay in the browser when there are compiler warnings."
}
"anyOf": [
{
"description": "Enables a full-screen overlay in the browser when there are compiler warnings.",
"type": "boolean",
"cli": {
"negatedDescription": "Disables the full-screen overlay in the browser when there are compiler warnings."
}
},
{
"instanceof": "Function",
"description": "Filter compiler warnings. Return true to include and return false to exclude."
}
]
},
"runtimeErrors": {
"description": "Enables a full-screen overlay in the browser when there are uncaught runtime errors.",
"type": "boolean",
"cli": {
"negatedDescription": "Disables the full-screen overlay in the browser when there are uncaught runtime errors."
}
"anyOf": [
{
"description": "Enables a full-screen overlay in the browser when there are uncaught runtime errors.",
"type": "boolean",
"cli": {
"negatedDescription": "Disables the full-screen overlay in the browser when there are uncaught runtime errors."
}
},
{
"instanceof": "Function",
"description": "Filter uncaught runtime errors. Return true to include and return false to exclude."
}
]
},
"trustedTypesPolicyName": {
"description": "The name of a Trusted Types policy for the overlay. Defaults to 'webpack-dev-server#overlay'.",
935 changes: 470 additions & 465 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "webpack-dev-server",
"version": "4.13.3",
"version": "4.14.0",
"description": "Serves a webpack app. Updates the browser on changes.",
"bin": "bin/webpack-dev-server.js",
"main": "lib/Server.js",
@@ -129,7 +129,7 @@
"typescript": "^4.9.3",
"url-loader": "^4.1.1",
"wait-for-expect": "^3.0.2",
"webpack": "^5.76.1",
"webpack": "^5.81.0",
"webpack-cli": "^4.7.2",
"webpack-merge": "^5.8.0"
},
28 changes: 24 additions & 4 deletions test/__snapshots__/validate-options.test.js.snap.webpack4
Original file line number Diff line number Diff line change
@@ -107,14 +107,34 @@ exports[`options validate should throw an error on the "client" option with '{"o

exports[`options validate should throw an error on the "client" option with '{"overlay":{"errors":""}}' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.client.overlay.errors should be a boolean.
-> Enables a full-screen overlay in the browser when there are compiler errors."
- options.client should be one of these:
false | object { logging?, overlay?, progress?, reconnect?, webSocketTransport?, webSocketURL? }
-> Allows to specify options for client script in the browser or disable client script.
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverclient
Details:
* options.client.overlay.errors should be one of these:
boolean | function
Details:
* options.client.overlay.errors should be a boolean.
-> Enables a full-screen overlay in the browser when there are compiler errors.
* options.client.overlay.errors should be an instance of function.
-> Filter compiler errors. Return true to include and return false to exclude."
`;

exports[`options validate should throw an error on the "client" option with '{"overlay":{"warnings":""}}' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.client.overlay.warnings should be a boolean.
-> Enables a full-screen overlay in the browser when there are compiler warnings."
- options.client should be one of these:
false | object { logging?, overlay?, progress?, reconnect?, webSocketTransport?, webSocketURL? }
-> Allows to specify options for client script in the browser or disable client script.
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverclient
Details:
* options.client.overlay.warnings should be one of these:
boolean | function
Details:
* options.client.overlay.warnings should be a boolean.
-> Enables a full-screen overlay in the browser when there are compiler warnings.
* options.client.overlay.warnings should be an instance of function.
-> Filter compiler warnings. Return true to include and return false to exclude."
`;

exports[`options validate should throw an error on the "client" option with '{"progress":""}' value 1`] = `
28 changes: 24 additions & 4 deletions test/__snapshots__/validate-options.test.js.snap.webpack5
Original file line number Diff line number Diff line change
@@ -107,14 +107,34 @@ exports[`options validate should throw an error on the "client" option with '{"o

exports[`options validate should throw an error on the "client" option with '{"overlay":{"errors":""}}' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.client.overlay.errors should be a boolean.
-> Enables a full-screen overlay in the browser when there are compiler errors."
- options.client should be one of these:
false | object { logging?, overlay?, progress?, reconnect?, webSocketTransport?, webSocketURL? }
-> Allows to specify options for client script in the browser or disable client script.
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverclient
Details:
* options.client.overlay.errors should be one of these:
boolean | function
Details:
* options.client.overlay.errors should be a boolean.
-> Enables a full-screen overlay in the browser when there are compiler errors.
* options.client.overlay.errors should be an instance of function.
-> Filter compiler errors. Return true to include and return false to exclude."
`;

exports[`options validate should throw an error on the "client" option with '{"overlay":{"warnings":""}}' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.client.overlay.warnings should be a boolean.
-> Enables a full-screen overlay in the browser when there are compiler warnings."
- options.client should be one of these:
false | object { logging?, overlay?, progress?, reconnect?, webSocketTransport?, webSocketURL? }
-> Allows to specify options for client script in the browser or disable client script.
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverclient
Details:
* options.client.overlay.warnings should be one of these:
boolean | function
Details:
* options.client.overlay.warnings should be a boolean.
-> Enables a full-screen overlay in the browser when there are compiler warnings.
* options.client.overlay.warnings should be an instance of function.
-> Filter compiler warnings. Return true to include and return false to exclude."
`;

exports[`options validate should throw an error on the "client" option with '{"progress":""}' value 1`] = `
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@ Array [
"[HMR] Cannot apply update. Need to do a full reload!",
"[HMR] Error: Aborted because ./browser.js is not accepted
Update propagation: ./browser.js
at applyHandler (http://127.0.0.1:8103/browser.js:1077:31)
at applyHandler (http://127.0.0.1:8103/browser.js:1080:31)
at http://127.0.0.1:8103/browser.js:776:21
at Array.map (<anonymous>)
at internalApply (http://127.0.0.1:8103/browser.js:775:54)
296 changes: 296 additions & 0 deletions test/e2e/__snapshots__/overlay.test.js.snap.webpack4
Original file line number Diff line number Diff line change
@@ -2135,3 +2135,299 @@ exports[`overlay should show an error when "client.overlay.warnings" is "true":
</body>
"
`;

exports[`overlay should show error for uncaught runtime error: overlay html 1`] = `
"<body>
<div
id=\\"webpack-dev-server-client-overlay-div\\"
style=\\"
position: fixed;
box-sizing: border-box;
inset: 0px;
width: 100vw;
height: 100vh;
font-size: large;
padding: 2rem 2rem 4rem;
line-height: 1.2;
white-space: pre-wrap;
overflow: auto;
background-color: rgba(0, 0, 0, 0.9);
color: white;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 2em;
white-space: pre-wrap;
font-family: sans-serif;
margin: 0px 2rem 2rem 0px;
flex: 0 0 auto;
max-height: 50%;
overflow: auto;
\\"
>
Uncaught runtime errors:
</div>
<button
aria-label=\\"Dismiss\\"
style=\\"
color: rgb(255, 255, 255);
line-height: 1rem;
font-size: 1.5rem;
padding: 1rem;
cursor: pointer;
position: absolute;
right: 0px;
top: 0px;
background-color: transparent;
border: none;
\\"
>
×
</button>
<div>
<div
style=\\"
background-color: rgba(206, 17, 38, 0.1);
color: rgb(252, 207, 207);
padding: 1rem 1rem 1.5rem;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 1.2em;
margin-bottom: 1rem;
font-family: sans-serif;
\\"
>
ERROR
</div>
<div
style=\\"
line-height: 1.5;
font-size: 1rem;
font-family: Menlo, Consolas, monospace;
\\"
>
Injected error at throwError (&lt;anonymous&gt;:2:15) at
&lt;anonymous&gt;:3:9 at addScriptContent
(__puppeteer_evaluation_script__:9:27)
</div>
</div>
</div>
</div>
</body>
"
`;

exports[`overlay should show error when it is not filtered: overlay html 1`] = `
"<body>
<div
id=\\"webpack-dev-server-client-overlay-div\\"
style=\\"
position: fixed;
box-sizing: border-box;
inset: 0px;
width: 100vw;
height: 100vh;
font-size: large;
padding: 2rem 2rem 4rem;
line-height: 1.2;
white-space: pre-wrap;
overflow: auto;
background-color: rgba(0, 0, 0, 0.9);
color: white;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 2em;
white-space: pre-wrap;
font-family: sans-serif;
margin: 0px 2rem 2rem 0px;
flex: 0 0 auto;
max-height: 50%;
overflow: auto;
\\"
>
Compiled with problems:
</div>
<button
aria-label=\\"Dismiss\\"
style=\\"
color: rgb(255, 255, 255);
line-height: 1rem;
font-size: 1.5rem;
padding: 1rem;
cursor: pointer;
position: absolute;
right: 0px;
top: 0px;
background-color: transparent;
border: none;
\\"
>
×
</button>
<div>
<div
style=\\"
background-color: rgba(206, 17, 38, 0.1);
color: rgb(252, 207, 207);
padding: 1rem 1rem 1.5rem;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 1.2em;
margin-bottom: 1rem;
font-family: sans-serif;
\\"
>
ERROR
</div>
<div
style=\\"
line-height: 1.5;
font-size: 1rem;
font-family: Menlo, Consolas, monospace;
\\"
>
Unfiltered error
</div>
</div>
</div>
</div>
</body>
"
`;

exports[`overlay should show error when it is not filtered: page html 1`] = `
"<body>
<h1>webpack-dev-server is running...</h1>
<script type=\\"text/javascript\\" charset=\\"utf-8\\" src=\\"/main.js\\"></script>

<iframe
id=\\"webpack-dev-server-client-overlay\\"
src=\\"about:blank\\"
style=\\"
position: fixed;
inset: 0px;
width: 100vw;
height: 100vh;
border: none;
z-index: 2147483647;
\\"
></iframe>
</body>
"
`;

exports[`overlay should show warning when it is not filtered: overlay html 1`] = `
"<body>
<div
id=\\"webpack-dev-server-client-overlay-div\\"
style=\\"
position: fixed;
box-sizing: border-box;
inset: 0px;
width: 100vw;
height: 100vh;
font-size: large;
padding: 2rem 2rem 4rem;
line-height: 1.2;
white-space: pre-wrap;
overflow: auto;
background-color: rgba(0, 0, 0, 0.9);
color: white;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 2em;
white-space: pre-wrap;
font-family: sans-serif;
margin: 0px 2rem 2rem 0px;
flex: 0 0 auto;
max-height: 50%;
overflow: auto;
\\"
>
Compiled with problems:
</div>
<button
aria-label=\\"Dismiss\\"
style=\\"
color: rgb(255, 255, 255);
line-height: 1rem;
font-size: 1.5rem;
padding: 1rem;
cursor: pointer;
position: absolute;
right: 0px;
top: 0px;
background-color: transparent;
border: none;
\\"
>
×
</button>
<div>
<div
style=\\"
background-color: rgba(251, 245, 180, 0.1);
color: rgb(251, 245, 180);
padding: 1rem 1rem 1.5rem;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 1.2em;
margin-bottom: 1rem;
font-family: sans-serif;
\\"
>
WARNING
</div>
<div
style=\\"
line-height: 1.5;
font-size: 1rem;
font-family: Menlo, Consolas, monospace;
\\"
>
Unfiltered warning
</div>
</div>
</div>
</div>
</body>
"
`;

exports[`overlay should show warning when it is not filtered: page html 1`] = `
"<body>
<h1>webpack-dev-server is running...</h1>
<script type=\\"text/javascript\\" charset=\\"utf-8\\" src=\\"/main.js\\"></script>

<iframe
id=\\"webpack-dev-server-client-overlay\\"
src=\\"about:blank\\"
style=\\"
position: fixed;
inset: 0px;
width: 100vw;
height: 100vh;
border: none;
z-index: 2147483647;
\\"
></iframe>
</body>
"
`;
296 changes: 296 additions & 0 deletions test/e2e/__snapshots__/overlay.test.js.snap.webpack5
Original file line number Diff line number Diff line change
@@ -2152,6 +2152,197 @@ exports[`overlay should show an error when "client.overlay.warnings" is "true":
"
`;

exports[`overlay should show error for uncaught runtime error: overlay html 1`] = `
"<body>
<div
id=\\"webpack-dev-server-client-overlay-div\\"
style=\\"
position: fixed;
box-sizing: border-box;
inset: 0px;
width: 100vw;
height: 100vh;
font-size: large;
padding: 2rem 2rem 4rem;
line-height: 1.2;
white-space: pre-wrap;
overflow: auto;
background-color: rgba(0, 0, 0, 0.9);
color: white;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 2em;
white-space: pre-wrap;
font-family: sans-serif;
margin: 0px 2rem 2rem 0px;
flex: 0 0 auto;
max-height: 50%;
overflow: auto;
\\"
>
Uncaught runtime errors:
</div>
<button
aria-label=\\"Dismiss\\"
style=\\"
color: rgb(255, 255, 255);
line-height: 1rem;
font-size: 1.5rem;
padding: 1rem;
cursor: pointer;
position: absolute;
right: 0px;
top: 0px;
background-color: transparent;
border: none;
\\"
>
×
</button>
<div>
<div
style=\\"
background-color: rgba(206, 17, 38, 0.1);
color: rgb(252, 207, 207);
padding: 1rem 1rem 1.5rem;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 1.2em;
margin-bottom: 1rem;
font-family: sans-serif;
\\"
>
ERROR
</div>
<div
style=\\"
line-height: 1.5;
font-size: 1rem;
font-family: Menlo, Consolas, monospace;
\\"
>
Injected error at throwError (&lt;anonymous&gt;:2:15) at
&lt;anonymous&gt;:3:9 at addScriptContent
(__puppeteer_evaluation_script__:9:27)
</div>
</div>
</div>
</div>
</body>
"
`;

exports[`overlay should show error when it is not filtered: overlay html 1`] = `
"<body>
<div
id=\\"webpack-dev-server-client-overlay-div\\"
style=\\"
position: fixed;
box-sizing: border-box;
inset: 0px;
width: 100vw;
height: 100vh;
font-size: large;
padding: 2rem 2rem 4rem;
line-height: 1.2;
white-space: pre-wrap;
overflow: auto;
background-color: rgba(0, 0, 0, 0.9);
color: white;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 2em;
white-space: pre-wrap;
font-family: sans-serif;
margin: 0px 2rem 2rem 0px;
flex: 0 0 auto;
max-height: 50%;
overflow: auto;
\\"
>
Compiled with problems:
</div>
<button
aria-label=\\"Dismiss\\"
style=\\"
color: rgb(255, 255, 255);
line-height: 1rem;
font-size: 1.5rem;
padding: 1rem;
cursor: pointer;
position: absolute;
right: 0px;
top: 0px;
background-color: transparent;
border: none;
\\"
>
×
</button>
<div>
<div
style=\\"
background-color: rgba(206, 17, 38, 0.1);
color: rgb(252, 207, 207);
padding: 1rem 1rem 1.5rem;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 1.2em;
margin-bottom: 1rem;
font-family: sans-serif;
\\"
>
ERROR
</div>
<div
style=\\"
line-height: 1.5;
font-size: 1rem;
font-family: Menlo, Consolas, monospace;
\\"
>
Unfiltered error
</div>
</div>
</div>
</div>
</body>
"
`;

exports[`overlay should show error when it is not filtered: page html 1`] = `
"<body>
<h1>webpack-dev-server is running...</h1>
<script type=\\"text/javascript\\" charset=\\"utf-8\\" src=\\"/main.js\\"></script>

<iframe
id=\\"webpack-dev-server-client-overlay\\"
src=\\"about:blank\\"
style=\\"
position: fixed;
inset: 0px;
width: 100vw;
height: 100vh;
border: none;
z-index: 2147483647;
\\"
></iframe>
</body>
"
`;

exports[`overlay should show overlay when Trusted Types are enabled: overlay html 1`] = `
"<body>
<div
@@ -2256,3 +2447,108 @@ exports[`overlay should show overlay when Trusted Types are enabled: page html 1
</body>
"
`;

exports[`overlay should show warning when it is not filtered: overlay html 1`] = `
"<body>
<div
id=\\"webpack-dev-server-client-overlay-div\\"
style=\\"
position: fixed;
box-sizing: border-box;
inset: 0px;
width: 100vw;
height: 100vh;
font-size: large;
padding: 2rem 2rem 4rem;
line-height: 1.2;
white-space: pre-wrap;
overflow: auto;
background-color: rgba(0, 0, 0, 0.9);
color: white;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 2em;
white-space: pre-wrap;
font-family: sans-serif;
margin: 0px 2rem 2rem 0px;
flex: 0 0 auto;
max-height: 50%;
overflow: auto;
\\"
>
Compiled with problems:
</div>
<button
aria-label=\\"Dismiss\\"
style=\\"
color: rgb(255, 255, 255);
line-height: 1rem;
font-size: 1.5rem;
padding: 1rem;
cursor: pointer;
position: absolute;
right: 0px;
top: 0px;
background-color: transparent;
border: none;
\\"
>
×
</button>
<div>
<div
style=\\"
background-color: rgba(251, 245, 180, 0.1);
color: rgb(251, 245, 180);
padding: 1rem 1rem 1.5rem;
\\"
>
<div
style=\\"
color: rgb(232, 59, 70);
font-size: 1.2em;
margin-bottom: 1rem;
font-family: sans-serif;
\\"
>
WARNING
</div>
<div
style=\\"
line-height: 1.5;
font-size: 1rem;
font-family: Menlo, Consolas, monospace;
\\"
>
Unfiltered warning
</div>
</div>
</div>
</div>
</body>
"
`;

exports[`overlay should show warning when it is not filtered: page html 1`] = `
"<body>
<h1>webpack-dev-server is running...</h1>
<script type=\\"text/javascript\\" charset=\\"utf-8\\" src=\\"/main.js\\"></script>

<iframe
id=\\"webpack-dev-server-client-overlay\\"
src=\\"about:blank\\"
style=\\"
position: fixed;
inset: 0px;
width: 100vw;
height: 100vh;
border: none;
z-index: 2147483647;
\\"
></iframe>
</body>
"
`;
248 changes: 248 additions & 0 deletions test/e2e/overlay.test.js
Original file line number Diff line number Diff line change
@@ -596,6 +596,90 @@ describe("overlay", () => {
await server.stop();
});

it("should not show warning when it is filtered", async () => {
const compiler = webpack(config);

new WarningPlugin("My special warning").apply(compiler);

const server = new Server(
{
port,
client: {
overlay: {
warnings: (error) => {
// error is string in webpack 4
const message = typeof error === "string" ? error : error.message;
return message !== "My special warning";
},
},
},
},
compiler
);

await server.start();

const { page, browser } = await runBrowser();

await page.goto(`http://localhost:${port}/`, {
waitUntil: "networkidle0",
});

const overlayHandle = await page.$("#webpack-dev-server-client-overlay");

expect(overlayHandle).toBe(null);

await browser.close();
await server.stop();
});

it("should show warning when it is not filtered", async () => {
const compiler = webpack(config);

new WarningPlugin("Unfiltered warning").apply(compiler);

const server = new Server(
{
port,
client: {
overlay: {
warnings: () => true,
},
},
},
compiler
);

await server.start();

const { page, browser } = await runBrowser();

try {
await page.goto(`http://localhost:${port}/`, {
waitUntil: "networkidle0",
});

const pageHtml = await page.evaluate(() => document.body.outerHTML);
const overlayHandle = await page.$("#webpack-dev-server-client-overlay");
const overlayFrame = await overlayHandle.contentFrame();
const overlayHtml = await overlayFrame.evaluate(
() => document.body.outerHTML
);

expect(prettier.format(pageHtml, { parser: "html" })).toMatchSnapshot(
"page html"
);
expect(prettier.format(overlayHtml, { parser: "html" })).toMatchSnapshot(
"overlay html"
);
} catch (error) {
console.error(error);
}

await browser.close();
await server.stop();
});

it('should show a warning when "client.overlay" is "true"', async () => {
const compiler = webpack(config);

@@ -785,6 +869,95 @@ describe("overlay", () => {
await server.stop();
});

it("should not show error when it is filtered", async () => {
const compiler = webpack(config);

new ErrorPlugin("My special error").apply(compiler);

const server = new Server(
{
port,
client: {
overlay: {
errors: (error) => {
// error is string in webpack 4
const message = typeof error === "string" ? error : error.message;

return message !== "My special error";
},
},
},
},
compiler
);

await server.start();

const { page, browser } = await runBrowser();

try {
await page.goto(`http://localhost:${port}/`, {
waitUntil: "networkidle0",
});

const overlayHandle = await page.$("#webpack-dev-server-client-overlay");

expect(overlayHandle).toBe(null);
} catch (error) {
console.error(error);
}

await browser.close();
await server.stop();
});

it("should show error when it is not filtered", async () => {
const compiler = webpack(config);

new ErrorPlugin("Unfiltered error").apply(compiler);

const server = new Server(
{
port,
client: {
overlay: {
errors: () => true,
},
},
},
compiler
);

await server.start();

const { page, browser } = await runBrowser();

try {
await page.goto(`http://localhost:${port}/`, {
waitUntil: "networkidle0",
});

const pageHtml = await page.evaluate(() => document.body.outerHTML);
const overlayHandle = await page.$("#webpack-dev-server-client-overlay");
const overlayFrame = await overlayHandle.contentFrame();
const overlayHtml = await overlayFrame.evaluate(
() => document.body.outerHTML
);

expect(prettier.format(pageHtml, { parser: "html" })).toMatchSnapshot(
"page html"
);
expect(prettier.format(overlayHtml, { parser: "html" })).toMatchSnapshot(
"overlay html"
);
} catch (error) {
console.error(error);
}

await browser.close();
await server.stop();
});

it('should show an error when "client.overlay" is "true"', async () => {
const compiler = webpack(config);

@@ -1145,4 +1318,79 @@ describe("overlay", () => {
await browser.close();
await server.stop();
});

it("should show error for uncaught runtime error", async () => {
const compiler = webpack(config);

const server = new Server(
{
port,
},
compiler
);

await server.start();

const { page, browser } = await runBrowser();

await page.goto(`http://localhost:${port}/`, {
waitUntil: "networkidle0",
});

await page.addScriptTag({
content: `(function throwError() {
throw new Error('Injected error');
})();`,
});

const overlayHandle = await page.$("#webpack-dev-server-client-overlay");
const overlayFrame = await overlayHandle.contentFrame();
const overlayHtml = await overlayFrame.evaluate(
() => document.body.outerHTML
);

expect(prettier.format(overlayHtml, { parser: "html" })).toMatchSnapshot(
"overlay html"
);

await browser.close();
await server.stop();
});

it("should not show filtered runtime error", async () => {
const compiler = webpack(config);

const server = new Server(
{
port,
client: {
overlay: {
runtimeErrors: (error) => error && !/Injected/.test(error.message),
},
},
},
compiler
);

await server.start();

const { page, browser } = await runBrowser();

await page.goto(`http://localhost:${port}/`, {
waitUntil: "networkidle0",
});

await page.addScriptTag({
content: `(function throwError() {
throw new Error('Injected error');
})();`,
});

const overlayHandle = await page.$("#webpack-dev-server-client-overlay");

expect(overlayHandle).toBe(null);

await browser.close();
await server.stop();
});
});
329 changes: 209 additions & 120 deletions types/lib/Server.d.ts

Large diffs are not rendered by default.