Skip to content
This repository was archived by the owner on Apr 8, 2020. It is now read-only.

Commit 8acba88

Browse files
Update aspnet-webpack to 2.0.0, now supporting HMR when apps are running in virtual directories
1 parent 44f86eb commit 8acba88

File tree

2 files changed

+39
-13
lines changed

2 files changed

+39
-13
lines changed

src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "aspnet-webpack",
3-
"version": "1.0.29",
3+
"version": "2.0.0",
44
"description": "Helpers for using Webpack in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
55
"main": "index.js",
66
"scripts": {

src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack/src/WebpackDevMiddleware.ts

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
198206
function 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+
295321
function removeTrailingSlash(str: string) {
296322
if (str.lastIndexOf('/') === str.length - 1) {
297323
str = str.substring(0, str.length - 1);

0 commit comments

Comments
 (0)