Skip to content

Commit

Permalink
refactor: code
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Dec 18, 2021
1 parent 2543cd7 commit 8a31a9a
Show file tree
Hide file tree
Showing 9 changed files with 305 additions and 77 deletions.
23 changes: 16 additions & 7 deletions examples/setup-middlewares/README.md
Expand Up @@ -13,13 +13,22 @@ module.exports = {
throw new Error("webpack-dev-server is not defined");
}

const sendResponses = () => {
devServer.app.get("/setup-middleware/some/path", (_, response) => {
response.send("setup-middlewares option GET");
});
};

middlewares.push(sendResponses());
devServer.app.get("/setup-middleware/some/path", (_, response) => {
response.send("setup-middlewares option GET");
});

middlewares.push({
name: "hello-world-test-one",
// `path` is optional
path: "/foo/bar",
middleware: (req, res) => {
res.send("Foo Bar!");
},
});

middlewares.push((req, res) => {
res.send("Hello World!");
});

return middlewares;
},
Expand Down
21 changes: 15 additions & 6 deletions examples/setup-middlewares/webpack.config.js
Expand Up @@ -13,13 +13,22 @@ module.exports = setup({
throw new Error("webpack-dev-server is not defined");
}

const sendResponses = () => {
devServer.app.get("/setup-middleware/some/path", (_, response) => {
response.send("setup-middlewares option GET");
});
};
devServer.app.get("/setup-middleware/some/path", (_, response) => {
response.send("setup-middlewares option GET");
});

middlewares.push(sendResponses());
middlewares.push({
name: "hello-world-test-one",
// `path` is optional
path: "/foo/bar",
middleware: (req, res) => {
res.send("Foo Bar!");
},
});

middlewares.push((req, res) => {
res.send("Hello World!");
});

return middlewares;
},
Expand Down
141 changes: 95 additions & 46 deletions lib/Server.js
Expand Up @@ -1322,6 +1322,7 @@ class Server {
this.setupDevMiddleware();
// Should be after `webpack-dev-middleware`, otherwise other middlewares might rewrite response
this.setupBuiltInRoutes();
this.setupWatchStaticFiles();
this.setupWatchFiles();
this.setupMiddlewares();
this.createServer();
Expand Down Expand Up @@ -1484,22 +1485,14 @@ class Server {
});
}

setupStaticFeature() {
const staticMiddlewares = [];

this.options.static.forEach((staticOption) => {
staticOption.publicPath.forEach((publicPath) => {
staticMiddlewares.push({
publicPath,
middleware: express.static(
staticOption.directory,
staticOption.staticOptions
),
});
setupWatchStaticFiles() {
if (this.options.static.length > 0) {
this.options.static.forEach((staticOption) => {
if (staticOption.watch) {
this.watchFiles(staticOption.directory, staticOption.watch);
}
});
});

return staticMiddlewares;
}
}

setupWatchFiles() {
Expand All @@ -1514,17 +1507,30 @@ class Server {

setupMiddlewares() {
let middlewares = [];

// compress is placed last and uses unshift so that it will be the first middleware used
if (this.options.compress) {
const compress = require("compression");
middlewares.push(compress());
const compression = require("compression");

middlewares.push({ name: "compression", middleware: compression() });
}

if (typeof this.options.onBeforeSetupMiddleware === "function") {
middlewares.push(this.options.onBeforeSetupMiddleware(this));
if (this.options.onBeforeSetupMiddleware) {
this.options.onBeforeSetupMiddleware(this);
}

middlewares.push(this.setHeaders.bind(this), this.middleware);
if (typeof this.options.headers !== "undefined") {
middlewares.push({
name: "set-headers",
path: "*",
middleware: this.setHeaders.bind(this),
});
}

middlewares.push({
name: "webpack-dev-middleware",
middleware: this.middleware,
});

if (this.options.proxy) {
const { createProxyMiddleware } = require("http-proxy-middleware");
Expand Down Expand Up @@ -1573,7 +1579,7 @@ class Server {
this.webSocketProxies.push(proxyMiddleware);
}

const handle = async (req, res, next) => {
const handler = async (req, res, next) => {
if (typeof proxyConfigOrCallback === "function") {
const newProxyConfig = proxyConfigOrCallback(req, res, next);

Expand Down Expand Up @@ -1607,17 +1613,40 @@ class Server {
}
};

middlewares.push(handle);
middlewares.push({
name: "http-proxy-middleware",
middleware: handler,
});
// Also forward error requests to the proxy so it can handle them.
middlewares.push((error, req, res, next) => handle(req, res, next));
middlewares.push({
name: "http-proxy-middleware-error-handler",
middleware: (error, req, res, next) => handler(req, res, next),
});
});

middlewares.push({
name: "webpack-dev-middleware",
middleware: this.middleware,
});
}

if (this.options.static) {
middlewares = [...middlewares, ...this.setupStaticFeature()];
this.options.static.forEach((staticOption) => {
staticOption.publicPath.forEach((publicPath) => {
middlewares.push({
name: "express-static",
path: publicPath,
middleware: express.static(
staticOption.directory,
staticOption.staticOptions
),
});
});
});
}

if (this.options.historyApiFallback) {
const connectHistoryApiFallback = require("connect-history-api-fallback");
const { historyApiFallback } = this.options;

if (
Expand All @@ -1631,13 +1660,31 @@ class Server {
}

// Fall back to /index.html if nothing else matches.
middlewares.push(
require("connect-history-api-fallback")(historyApiFallback),
this.middleware
);
middlewares.push({
name: "connect-history-api-fallback",
middleware: connectHistoryApiFallback(historyApiFallback),
});

// include our middleware to ensure
// it is able to handle '/index.html' request after redirect
middlewares.push({
name: "webpack-dev-middleware",
middleware: this.middleware,
});

if (this.options.static) {
middlewares = [...middlewares, ...this.setupStaticFeature()];
this.options.static.forEach((staticOption) => {
staticOption.publicPath.forEach((publicPath) => {
middlewares.push({
name: "express-static",
path: publicPath,
middleware: express.static(
staticOption.directory,
staticOption.staticOptions
),
});
});
});
}
}

Expand All @@ -1648,7 +1695,8 @@ class Server {
staticOption.publicPath.forEach((publicPath) => {
if (staticOption.serveIndex) {
middlewares.push({
publicPath,
name: "serve-index",
path: publicPath,
middleware: (req, res, next) => {
// serve-index doesn't fallthrough non-get/head request to next middleware
if (req.method !== "GET" && req.method !== "HEAD") {
Expand All @@ -1664,36 +1712,33 @@ class Server {
});
}
});

if (staticOption.watch) {
middlewares.push(
this.watchFiles(staticOption.directory, staticOption.watch)
);
}
});
}

if (this.options.magicHtml) {
middlewares.push(this.serveMagicHtml.bind(this));
middlewares.push({
name: "serve-magic-html",
middleware: this.serveMagicHtml.bind(this),
});
}

if (typeof this.options.onAfterSetupMiddleware === "function") {
middlewares.push(this.options.onAfterSetupMiddleware(this));
if (this.options.onAfterSetupMiddleware) {
this.options.onAfterSetupMiddleware(this);
}

if (typeof this.options.setupMiddlewares === "function") {
middlewares = this.options.setupMiddlewares(middlewares, this);
}

for (const middleware of middlewares) {
if (typeof middleware === "function") {
middlewares.forEach((middleware) => {
if (typeof middleware.path !== "undefined") {
this.app.use(middleware.path, middleware.middleware);
} else if (typeof middleware === "function") {
this.app.use(middleware);
} else {
this.app.use(middleware.middleware);
}

if (typeof middleware === "object") {
this.app.use(middleware.publicPath, middleware.middleware);
}
}
});
}

createServer() {
Expand Down Expand Up @@ -2124,6 +2169,10 @@ class Server {
}

serveMagicHtml(req, res, next) {
if (req.method !== "GET" && req.method !== "HEAD") {
return next();
}

this.middleware.waitUntilValid(() => {
const _path = req.path;

Expand Down
8 changes: 8 additions & 0 deletions test/e2e/__snapshots__/headers.test.js.snap.webpack4
Expand Up @@ -21,6 +21,14 @@ key2=value2"

exports[`headers option as a function should handle GET request with headers as a function: response status 1`] = `200`;

exports[`headers option as a string and support HEAD request should handle HEAD request with headers: console messages 1`] = `Array []`;

exports[`headers option as a string and support HEAD request should handle HEAD request with headers: page errors 1`] = `Array []`;

exports[`headers option as a string and support HEAD request should handle HEAD request with headers: response headers x-foo 1`] = `"dev-server headers"`;

exports[`headers option as a string and support HEAD request should handle HEAD request with headers: response status 1`] = `200`;

exports[`headers option as a string should handle GET request with headers: console messages 1`] = `Array []`;

exports[`headers option as a string should handle GET request with headers: page errors 1`] = `Array []`;
Expand Down
8 changes: 8 additions & 0 deletions test/e2e/__snapshots__/headers.test.js.snap.webpack5
Expand Up @@ -21,6 +21,14 @@ key2=value2"

exports[`headers option as a function should handle GET request with headers as a function: response status 1`] = `200`;

exports[`headers option as a string and support HEAD request should handle HEAD request with headers: console messages 1`] = `Array []`;

exports[`headers option as a string and support HEAD request should handle HEAD request with headers: page errors 1`] = `Array []`;

exports[`headers option as a string and support HEAD request should handle HEAD request with headers: response headers x-foo 1`] = `"dev-server headers"`;

exports[`headers option as a string and support HEAD request should handle HEAD request with headers: response status 1`] = `200`;

exports[`headers option as a string should handle GET request with headers: console messages 1`] = `Array []`;

exports[`headers option as a string should handle GET request with headers: page errors 1`] = `Array []`;
Expand Down
18 changes: 18 additions & 0 deletions test/e2e/__snapshots__/setup-middlewares.test.js.snap.webpack4
Expand Up @@ -6,10 +6,28 @@ exports[`setupMiddlewares option should handle GET request to /setup-middleware/

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response headers content-type 2`] = `"text/html; charset=utf-8"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response headers content-type 3`] = `"text/html; charset=utf-8"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response headers content-type 4`] = `"text/html; charset=utf-8"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response status 1`] = `200`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response status 2`] = `200`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response status 3`] = `200`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response status 4`] = `200`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response text 1`] = `"setup-middlewares option GET"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response text 2`] = `"Hello World with path!"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response text 3`] = `"Hello World without path!"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response text 4`] = `"Hello World as function!"`;

exports[`setupMiddlewares option should handle POST request to /setup-middleware/some/path route: console messages 1`] = `Array []`;

exports[`setupMiddlewares option should handle POST request to /setup-middleware/some/path route: page errors 1`] = `Array []`;
Expand Down
18 changes: 18 additions & 0 deletions test/e2e/__snapshots__/setup-middlewares.test.js.snap.webpack5
Expand Up @@ -6,10 +6,28 @@ exports[`setupMiddlewares option should handle GET request to /setup-middleware/

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response headers content-type 1`] = `"text/html; charset=utf-8"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response headers content-type 2`] = `"text/html; charset=utf-8"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response headers content-type 3`] = `"text/html; charset=utf-8"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response headers content-type 4`] = `"text/html; charset=utf-8"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response status 1`] = `200`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response status 2`] = `200`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response status 3`] = `200`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response status 4`] = `200`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response text 1`] = `"setup-middlewares option GET"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response text 2`] = `"Hello World with path!"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response text 3`] = `"Hello World without path!"`;

exports[`setupMiddlewares option should handle GET request to /setup-middleware/some/path route: response text 4`] = `"Hello World as function!"`;

exports[`setupMiddlewares option should handle POST request to /setup-middleware/some/path route: console messages 1`] = `Array []`;

exports[`setupMiddlewares option should handle POST request to /setup-middleware/some/path route: page errors 1`] = `Array []`;
Expand Down

0 comments on commit 8a31a9a

Please sign in to comment.