Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add magicHtml option #3717

Merged
merged 6 commits into from
Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ Options:
--ipc [value] Listen to a unix socket.
--live-reload Enables reload/refresh the page(s) when file changes are detected (enabled by default).
--no-live-reload Negative 'live-reload' option.
--magic-html Enables/Disables magic HTML routes (enabled by default).
--no-magic-html Negative 'magic-html' option.
--open [value...] Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to
true to open your default browser).
--no-open Negative 'open' option.
Expand Down
13 changes: 13 additions & 0 deletions bin/cli-flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,19 @@ module.exports = {
simpleType: "boolean",
multiple: false,
},
"magic-html": {
configs: [
{
type: "boolean",
multiple: false,
description: "Enables/Disables magic HTML routes (enabled by default).",
path: "magicHtml",
},
],
description: "Enables/Disables magic HTML routes (enabled by default).",
simpleType: "boolean",
multiple: false,
},
open: {
configs: [
{
Expand Down
7 changes: 6 additions & 1 deletion lib/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,9 @@ class Server {
options.liveReload =
typeof options.liveReload !== "undefined" ? options.liveReload : true;

options.magicHtml =
typeof options.magicHtml !== "undefined" ? options.magicHtml : true;

// https://github.com/webpack/webpack-dev-server/issues/1990
const defaultOpenOptions = { wait: false };
const getOpenItemsFromObject = ({ target, ...rest }) => {
Expand Down Expand Up @@ -1132,7 +1135,9 @@ class Server {
runnableFeatures.push("staticServeIndex", "staticWatch");
}

runnableFeatures.push("magicHtml");
if (this.options.magicHtml) {
runnableFeatures.push("magicHtml");
}

if (this.options.onAfterSetupMiddleware) {
runnableFeatures.push("onAfterSetupMiddleware");
Expand Down
8 changes: 8 additions & 0 deletions lib/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@
"description": "Enables reload/refresh the page(s) when file changes are detected (enabled by default).",
"link": "https://webpack.js.org/configuration/dev-server/#devserverlivereload"
},
"MagicHTML": {
"type": "boolean",
"description": "Enables/Disables magic HTML routes (enabled by default).",
"link": "https://webpack.js.org/configuration/dev-server/#devservermagichtml"
},
"OnAfterSetupMiddleware": {
"instanceof": "Function",
"description": "Provides the ability to execute a custom function and apply custom middleware(s) after all other middlewares.",
Expand Down Expand Up @@ -729,6 +734,9 @@
"liveReload": {
"$ref": "#/definitions/LiveReload"
},
"magicHtml": {
"$ref": "#/definitions/MagicHTML"
},
"onAfterSetupMiddleware": {
"$ref": "#/definitions/OnAfterSetupMiddleware"
},
Expand Down
7 changes: 7 additions & 0 deletions test/__snapshots__/validate-options.test.js.snap.webpack4
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,13 @@ exports[`options validate should throw an error on the "liveReload" option with
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverlivereload"
`;

exports[`options validate should throw an error on the "magicHtml" option with 'string' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.magicHtml should be a boolean.
-> Enables/Disables magic HTML routes (enabled by default).
-> Read more at https://webpack.js.org/configuration/dev-server/#devservermagichtml"
`;

exports[`options validate should throw an error on the "onAfterSetupMiddleware" option with 'false' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.onAfterSetupMiddleware should be an instance of function.
Expand Down
7 changes: 7 additions & 0 deletions test/__snapshots__/validate-options.test.js.snap.webpack5
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,13 @@ exports[`options validate should throw an error on the "liveReload" option with
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverlivereload"
`;

exports[`options validate should throw an error on the "magicHtml" option with 'string' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.magicHtml should be a boolean.
-> Enables/Disables magic HTML routes (enabled by default).
-> Read more at https://webpack.js.org/configuration/dev-server/#devservermagichtml"
`;

exports[`options validate should throw an error on the "onAfterSetupMiddleware" option with 'false' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.onAfterSetupMiddleware should be an instance of function.
Expand Down
2 changes: 2 additions & 0 deletions test/cli/__snapshots__/basic.test.js.snap.webpack4
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ Options:
--ipc [value] Listen to a unix socket.
--live-reload Enables reload/refresh the page(s) when file changes are detected (enabled by default).
--no-live-reload Disables reload/refresh the page(s) when file changes are detected (enabled by default)
--magic-html Enables/Disables magic HTML routes (enabled by default).
--no-magic-html Negative 'magic-html' option.
--open [value...] Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to true to open your default browser).
--no-open Does not open the default browser.
--open-target <value...> Opens specified page in browser.
Expand Down
2 changes: 2 additions & 0 deletions test/cli/__snapshots__/basic.test.js.snap.webpack5
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ Options:
--ipc [value] Listen to a unix socket.
--live-reload Enables reload/refresh the page(s) when file changes are detected (enabled by default).
--no-live-reload Negative 'live-reload' option.
--magic-html Enables/Disables magic HTML routes (enabled by default).
--no-magic-html Negative 'magic-html' option.
--open [value...] Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to true to open your default browser).
--no-open Negative 'open' option.
--open-target <value...> Opens specified page in browser.
Expand Down
18 changes: 18 additions & 0 deletions test/cli/magicHtml-option.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use strict";

const { testBin } = require("../helpers/test-bin");
const port = require("../ports-map")["cli-magic-html"];

describe('"liveReload" CLI option', () => {
it('should work using "--magic-html"', async () => {
const { exitCode } = await testBin(["--port", port, "--magic-html"]);

expect(exitCode).toEqual(0);
});

it('should work using "--no-magic-html"', async () => {
const { exitCode } = await testBin(["--port", port, "--no-magic-html"]);

expect(exitCode).toEqual(0);
});
});
40 changes: 40 additions & 0 deletions test/e2e/__snapshots__/magic-html.test.js.snap.webpack4
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`magicHtml option disabled should not handle GET request to magic async html: console messages 1`] = `
Array [
"Failed to load resource: the server responded with a status of 404 (Not Found)",
]
`;

exports[`magicHtml option disabled should not handle GET request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option disabled should not handle GET request to magic async html: response status 1`] = `404`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: console messages 1`] = `
Array [
"Failed to load resource: the server responded with a status of 404 (Not Found)",
]
`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: response status 1`] = `404`;

exports[`magicHtml option enabled should handle GET request to magic async html: console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`magicHtml option enabled should handle GET request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option enabled should handle GET request to magic async html: response status 1`] = `200`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: console messages 1`] = `Array []`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: response status 1`] = `200`;
40 changes: 40 additions & 0 deletions test/e2e/__snapshots__/magic-html.test.js.snap.webpack5
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`magicHtml option disabled should not handle GET request to magic async html: console messages 1`] = `
Array [
"Failed to load resource: the server responded with a status of 404 (Not Found)",
]
`;

exports[`magicHtml option disabled should not handle GET request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option disabled should not handle GET request to magic async html: response status 1`] = `404`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: console messages 1`] = `
Array [
"Failed to load resource: the server responded with a status of 404 (Not Found)",
]
`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option disabled should not handle HEAD request to magic async html: response status 1`] = `404`;

exports[`magicHtml option enabled should handle GET request to magic async html: console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`magicHtml option enabled should handle GET request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option enabled should handle GET request to magic async html: response status 1`] = `200`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: console messages 1`] = `Array []`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`magicHtml option enabled should handle HEAD request to magic async html: response status 1`] = `200`;
167 changes: 167 additions & 0 deletions test/e2e/magic-html.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
"use strict";

const webpack = require("webpack");
const Server = require("../../lib/Server");
const config = require("../fixtures/client-config/webpack.config");
const runBrowser = require("../helpers/run-browser");
const port = require("../ports-map")["magic-html-option"];

describe("magicHtml option", () => {
describe("enabled", () => {
let compiler;
let server;
let page;
let browser;
let pageErrors;
let consoleMessages;

beforeEach(async () => {
compiler = webpack(config);
server = new Server({ port, magicHtml: true }, compiler);

await server.start();

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

pageErrors = [];
consoleMessages = [];
});

afterEach(async () => {
await browser.close();
await server.stop();
});

it("should handle GET request to magic async html", async () => {
page
.on("console", (message) => {
consoleMessages.push(message);
})
.on("pageerror", (error) => {
pageErrors.push(error);
});

const response = await page.goto(`http://127.0.0.1:${port}/main`, {
waitUntil: "networkidle0",
});

expect(response.headers()["content-type"]).toMatchSnapshot(
"response headers content-type"
);

expect(response.status()).toMatchSnapshot("response status");

expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
"console messages"
);
});

it("should handle HEAD request to magic async html", async () => {
await page.setRequestInterception(true);

page
.on("console", (message) => {
consoleMessages.push(message);
})
.on("pageerror", (error) => {
pageErrors.push(error);
})
.on("request", (interceptedRequest) => {
interceptedRequest.continue({ method: "HEAD" });
});

const response = await page.goto(`http://127.0.0.1:${port}/main`, {
waitUntil: "networkidle0",
});

expect(response.headers()["content-type"]).toMatchSnapshot(
"response headers content-type"
);

expect(response.status()).toMatchSnapshot("response status");

expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
"console messages"
);
});
});

describe("disabled", () => {
let compiler;
let server;
let page;
let browser;
let pageErrors;
let consoleMessages;

beforeEach(async () => {
compiler = webpack(config);
server = new Server({ port, magicHtml: false }, compiler);

await server.start();

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

pageErrors = [];
consoleMessages = [];
});

afterEach(async () => {
await browser.close();
await server.stop();
});

it("should not handle GET request to magic async html", async () => {
page
.on("console", (message) => {
consoleMessages.push(message);
})
.on("pageerror", (error) => {
pageErrors.push(error);
});

const response = await page.goto(`http://127.0.0.1:${port}/main`, {
waitUntil: "networkidle0",
});

expect(response.headers()["content-type"]).toMatchSnapshot(
"response headers content-type"
);

expect(response.status()).toMatchSnapshot("response status");

expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
"console messages"
);
});

it("should not handle HEAD request to magic async html", async () => {
await page.setRequestInterception(true);

page
.on("console", (message) => {
consoleMessages.push(message);
})
.on("pageerror", (error) => {
pageErrors.push(error);
})
.on("request", (interceptedRequest) => {
interceptedRequest.continue({ method: "HEAD" });
});

const response = await page.goto(`http://127.0.0.1:${port}/main`, {
waitUntil: "networkidle0",
});

expect(response.headers()["content-type"]).toMatchSnapshot(
"response headers content-type"
);

expect(response.status()).toMatchSnapshot("response status");

expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
"console messages"
);
});
});
});