diff --git a/lib/Server.js b/lib/Server.js index 4b810fe887..de00af8208 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -342,8 +342,17 @@ class Server { const contentBasePublicPath = this.options.contentBasePublicPath; if (Array.isArray(contentBase)) { - contentBase.forEach((item) => { - this.app.use(contentBasePublicPath, express.static(item)); + contentBase.forEach((item, index) => { + let publicPath = contentBasePublicPath; + + if ( + Array.isArray(contentBasePublicPath) && + contentBasePublicPath[index] + ) { + publicPath = contentBasePublicPath[index] || contentBasePublicPath[0]; + } + + this.app.use(publicPath, express.static(item)); }); } else if (isAbsoluteUrl(String(contentBase))) { this.log.warn( diff --git a/lib/options.json b/lib/options.json index 0936c4f5f9..ab67fdd5d3 100644 --- a/lib/options.json +++ b/lib/options.json @@ -52,7 +52,18 @@ "type": "boolean" }, "contentBasePublicPath": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1 + } + ] }, "contentBase": { "anyOf": [ @@ -463,7 +474,7 @@ "quiet": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverquiet-)", "reporter": "should be {Function} (https://github.com/webpack/webpack-dev-middleware#reporter)", "requestCert": "should be {Boolean}", - "contentBasePublicPath": "should be {String} (https://webpack.js.org/configuration/dev-server/#devservercontentbasepublicpath)", + "contentBasePublicPath": "should be {String|Array} (https://webpack.js.org/configuration/dev-server/#devservercontentbasepublicpath)", "serveIndex": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverserveindex)", "serverSideRender": "should be {Boolean} (https://github.com/webpack/webpack-dev-middleware#serversiderender)", "setup": "should be {Function} (https://webpack.js.org/configuration/dev-server/#devserversetup)", diff --git a/test/server/contentBasePublicPath-option.test.js b/test/server/contentBasePublicPath-option.test.js index 752002fcde..404c0b9437 100644 --- a/test/server/contentBasePublicPath-option.test.js +++ b/test/server/contentBasePublicPath-option.test.js @@ -16,6 +16,7 @@ const contentBaseOther = path.resolve( ); const contentBasePublicPath = '/serve-content-base-at-this-url'; +const contentBasePublicOtherPath = '/serve-other-content-at-this-url'; describe('contentBasePublicPath option', () => { let server; @@ -292,4 +293,45 @@ describe('contentBasePublicPath option', () => { req.patch(`${contentBasePublicPath}/`).expect(404, done); }); }); + + describe('multiple contentBasePublicPath entries', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + contentBase: [contentBasePublic, contentBaseOther], + contentBasePublicPath: [ + contentBasePublicPath, + contentBasePublicOtherPath, + ], + watchContentBase: true, + port, + }, + done + ); + req = request(server.app); + }); + + afterAll((done) => { + testServer.close(() => { + done(); + }); + }); + + it('Request the first path to index', (done) => { + req.get(`${contentBasePublicPath}/`).expect(200, /Heyo/, done); + }); + + it('Request the first path to other file', (done) => { + req + .get(`${contentBasePublicPath}/other.html`) + .expect(200, /Other html/, done); + }); + + it('Request the second path to foo', (done) => { + req + .get(`${contentBasePublicOtherPath}/foo.html`) + .expect(200, /Foo!/, done); + }); + }); });