@@ -108,7 +108,7 @@ function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configurati
108
108
const compiler = webpack ( webpackConfig ) ;
109
109
app . use ( require ( 'webpack-dev-middleware' ) ( compiler , {
110
110
noInfo : true ,
111
- publicPath : webpackConfig . output . publicPath ,
111
+ publicPath : ensureLeadingSlash ( webpackConfig . output . publicPath ) ,
112
112
watchOptions : webpackConfig . watchOptions
113
113
} ) ) ;
114
114
@@ -195,6 +195,14 @@ function copyRecursiveToRealFsSync(from: typeof fs, rootDir: string, exclude: Re
195
195
} ) ;
196
196
}
197
197
198
+ function ensureLeadingSlash ( value : string ) {
199
+ if ( value !== null && value . substring ( 0 , 1 ) !== '/' ) {
200
+ value = '/' + value ;
201
+ }
202
+
203
+ return value ;
204
+ }
205
+
198
206
function pathJoinSafe ( rootPath : string , filePath : string ) {
199
207
// On Windows, MemoryFileSystem's readdirSync output produces directory entries like 'C:'
200
208
// 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
257
265
if ( ! publicPath ) {
258
266
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)' ) ;
259
267
}
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 ) ;
271
280
272
281
// We always overwrite the 'path' option as it needs to match what the .NET side is expecting
273
282
const hmrClientOptions = options . suppliedOptions . HotModuleReplacementClientOptions || < StringMap < string > > { } ;
274
283
hmrClientOptions [ 'path' ] = hmrClientEndpoint ;
275
284
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
+
276
294
attachWebpackDevMiddleware ( app , webpackConfig , enableHotModuleReplacement , enableReactHotModuleReplacement , hmrClientOptions , hmrServerEndpoint ) ;
277
295
}
278
296
} ) ;
@@ -292,6 +310,14 @@ export function createWebpackDevServer(callback: CreateDevServerCallback, option
292
310
} ) ;
293
311
}
294
312
313
+ function removeLeadingSlash ( str : string ) {
314
+ if ( str . indexOf ( '/' ) === 0 ) {
315
+ str = str . substring ( 1 ) ;
316
+ }
317
+
318
+ return str ;
319
+ }
320
+
295
321
function removeTrailingSlash ( str : string ) {
296
322
if ( str . lastIndexOf ( '/' ) === str . length - 1 ) {
297
323
str = str . substring ( 0 , str . length - 1 ) ;
0 commit comments