@@ -108,7 +108,7 @@ function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configurati
108108 const compiler = webpack ( webpackConfig ) ;
109109 app . use ( require ( 'webpack-dev-middleware' ) ( compiler , {
110110 noInfo : true ,
111- publicPath : webpackConfig . output . publicPath ,
111+ publicPath : ensureLeadingSlash ( webpackConfig . output . publicPath ) ,
112112 watchOptions : webpackConfig . watchOptions
113113 } ) ) ;
114114
@@ -195,6 +195,14 @@ function copyRecursiveToRealFsSync(from: typeof fs, rootDir: string, exclude: Re
195195 } ) ;
196196}
197197
198+ function ensureLeadingSlash ( value : string ) {
199+ if ( value !== null && value . substring ( 0 , 1 ) !== '/' ) {
200+ value = '/' + value ;
201+ }
202+
203+ return value ;
204+ }
205+
198206function pathJoinSafe ( rootPath : string , filePath : string ) {
199207 // On Windows, MemoryFileSystem's readdirSync output produces directory entries like 'C:'
200208 // which then trigger errors if you call statSync for them. Avoid this by detecting drive
@@ -257,22 +265,32 @@ export function createWebpackDevServer(callback: CreateDevServerCallback, option
257265 if ( ! publicPath ) {
258266 throw new Error ( 'To use the Webpack dev server, you must specify a value for \'publicPath\' on the \'output\' section of your webpack config (for any configuration that targets browsers)' ) ;
259267 }
260- normalizedPublicPaths . push ( removeTrailingSlash ( publicPath ) ) ;
261-
262- // Newer versions of Microsoft.AspNetCore.SpaServices will explicitly pass an HMR endpoint URL
263- // (because it's relative to the app's URL space root, which the client doesn't otherwise know).
264- // For back-compatibility, fall back on connecting directly to the underlying HMR server (though
265- // that won't work if the app is hosted on HTTPS because of the mixed-content rule, and we can't
266- // run the HMR server itself on HTTPS because in general it has no valid cert).
267- const hmrClientEndpoint = options . hotModuleReplacementEndpointUrl // The URL that we'll proxy (e.g., /__asp_webpack_hmr)
268- || `http://localhost:${ listener . address ( ) . port } /__webpack_hmr` ; // Fall back on absolute URL to bypass proxying
269- const hmrServerEndpoint = options . hotModuleReplacementEndpointUrl
270- || '/__webpack_hmr' ; // URL is relative to webpack dev server root
268+ const publicPathNoTrailingSlash = removeTrailingSlash ( publicPath ) ;
269+ normalizedPublicPaths . push ( publicPathNoTrailingSlash ) ;
270+
271+ // This is the URL the client will connect to, except that since it's a relative URL
272+ // (no leading slash), Webpack will resolve it against the runtime <base href> URL
273+ // plus it also adds the publicPath
274+ const hmrClientEndpoint = removeLeadingSlash ( options . hotModuleReplacementEndpointUrl ) ;
275+
276+ // This is the URL inside the Webpack middleware Node server that we'll proxy to.
277+ // We have to prefix with the public path because Webpack will add the publicPath
278+ // when it resolves hmrClientEndpoint as a relative URL.
279+ const hmrServerEndpoint = ensureLeadingSlash ( publicPathNoTrailingSlash + options . hotModuleReplacementEndpointUrl ) ;
271280
272281 // We always overwrite the 'path' option as it needs to match what the .NET side is expecting
273282 const hmrClientOptions = options . suppliedOptions . HotModuleReplacementClientOptions || < StringMap < string > > { } ;
274283 hmrClientOptions [ 'path' ] = hmrClientEndpoint ;
275284
285+ const dynamicPublicPathKey = 'dynamicPublicPath' ;
286+ if ( ! ( dynamicPublicPathKey in hmrClientOptions ) ) {
287+ // dynamicPublicPath default to true, so we can work with nonempty pathbases (virtual directories)
288+ hmrClientOptions [ dynamicPublicPathKey ] = true ;
289+ } else {
290+ // ... but you can set it to any other value explicitly if you want (e.g., false)
291+ hmrClientOptions [ dynamicPublicPathKey ] = JSON . parse ( hmrClientOptions [ dynamicPublicPathKey ] ) ;
292+ }
293+
276294 attachWebpackDevMiddleware ( app , webpackConfig , enableHotModuleReplacement , enableReactHotModuleReplacement , hmrClientOptions , hmrServerEndpoint ) ;
277295 }
278296 } ) ;
@@ -292,6 +310,14 @@ export function createWebpackDevServer(callback: CreateDevServerCallback, option
292310 } ) ;
293311}
294312
313+ function removeLeadingSlash ( str : string ) {
314+ if ( str . indexOf ( '/' ) === 0 ) {
315+ str = str . substring ( 1 ) ;
316+ }
317+
318+ return str ;
319+ }
320+
295321function removeTrailingSlash ( str : string ) {
296322 if ( str . lastIndexOf ( '/' ) === str . length - 1 ) {
297323 str = str . substring ( 0 , str . length - 1 ) ;
0 commit comments