Update aspnet-webpack to 2.0.0, now supporting HMR when apps are running in virtual directories

This commit is contained in:
Steve Sanderson
2017-07-11 16:23:15 +01:00
parent 44f86eb8a1
commit 8acba88160
2 changed files with 38 additions and 12 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "aspnet-webpack", "name": "aspnet-webpack",
"version": "1.0.29", "version": "2.0.0",
"description": "Helpers for using Webpack in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.", "description": "Helpers for using Webpack in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@@ -108,7 +108,7 @@ function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configurati
const compiler = webpack(webpackConfig); const compiler = webpack(webpackConfig);
app.use(require('webpack-dev-middleware')(compiler, { app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true, noInfo: true,
publicPath: webpackConfig.output.publicPath, publicPath: ensureLeadingSlash(webpackConfig.output.publicPath),
watchOptions: webpackConfig.watchOptions watchOptions: webpackConfig.watchOptions
})); }));
@@ -195,6 +195,14 @@ function copyRecursiveToRealFsSync(from: typeof fs, rootDir: string, exclude: Re
}); });
} }
function ensureLeadingSlash(value: string) {
if (value !== null && value.substring(0, 1) !== '/') {
value = '/' + value;
}
return value;
}
function pathJoinSafe(rootPath: string, filePath: string) { function pathJoinSafe(rootPath: string, filePath: string) {
// On Windows, MemoryFileSystem's readdirSync output produces directory entries like 'C:' // On Windows, MemoryFileSystem's readdirSync output produces directory entries like 'C:'
// which then trigger errors if you call statSync for them. Avoid this by detecting drive // 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
if (!publicPath) { if (!publicPath) {
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)'); 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)');
} }
normalizedPublicPaths.push(removeTrailingSlash(publicPath)); const publicPathNoTrailingSlash = removeTrailingSlash(publicPath);
normalizedPublicPaths.push(publicPathNoTrailingSlash);
// Newer versions of Microsoft.AspNetCore.SpaServices will explicitly pass an HMR endpoint URL // This is the URL the client will connect to, except that since it's a relative URL
// (because it's relative to the app's URL space root, which the client doesn't otherwise know). // (no leading slash), Webpack will resolve it against the runtime <base href> URL
// For back-compatibility, fall back on connecting directly to the underlying HMR server (though // plus it also adds the publicPath
// that won't work if the app is hosted on HTTPS because of the mixed-content rule, and we can't const hmrClientEndpoint = removeLeadingSlash(options.hotModuleReplacementEndpointUrl);
// run the HMR server itself on HTTPS because in general it has no valid cert).
const hmrClientEndpoint = options.hotModuleReplacementEndpointUrl // The URL that we'll proxy (e.g., /__asp_webpack_hmr) // This is the URL inside the Webpack middleware Node server that we'll proxy to.
|| `http://localhost:${listener.address().port}/__webpack_hmr`; // Fall back on absolute URL to bypass proxying // We have to prefix with the public path because Webpack will add the publicPath
const hmrServerEndpoint = options.hotModuleReplacementEndpointUrl // when it resolves hmrClientEndpoint as a relative URL.
|| '/__webpack_hmr'; // URL is relative to webpack dev server root const hmrServerEndpoint = ensureLeadingSlash(publicPathNoTrailingSlash + options.hotModuleReplacementEndpointUrl);
// We always overwrite the 'path' option as it needs to match what the .NET side is expecting // We always overwrite the 'path' option as it needs to match what the .NET side is expecting
const hmrClientOptions = options.suppliedOptions.HotModuleReplacementClientOptions || <StringMap<string>>{}; const hmrClientOptions = options.suppliedOptions.HotModuleReplacementClientOptions || <StringMap<string>>{};
hmrClientOptions['path'] = hmrClientEndpoint; hmrClientOptions['path'] = hmrClientEndpoint;
const dynamicPublicPathKey = 'dynamicPublicPath';
if (!(dynamicPublicPathKey in hmrClientOptions)) {
// dynamicPublicPath default to true, so we can work with nonempty pathbases (virtual directories)
hmrClientOptions[dynamicPublicPathKey] = true;
} else {
// ... but you can set it to any other value explicitly if you want (e.g., false)
hmrClientOptions[dynamicPublicPathKey] = JSON.parse(hmrClientOptions[dynamicPublicPathKey]);
}
attachWebpackDevMiddleware(app, webpackConfig, enableHotModuleReplacement, enableReactHotModuleReplacement, hmrClientOptions, hmrServerEndpoint); attachWebpackDevMiddleware(app, webpackConfig, enableHotModuleReplacement, enableReactHotModuleReplacement, hmrClientOptions, hmrServerEndpoint);
} }
}); });
@@ -292,6 +310,14 @@ export function createWebpackDevServer(callback: CreateDevServerCallback, option
}); });
} }
function removeLeadingSlash(str: string) {
if (str.indexOf('/') === 0) {
str = str.substring(1);
}
return str;
}
function removeTrailingSlash(str: string) { function removeTrailingSlash(str: string) {
if (str.lastIndexOf('/') === str.length - 1) { if (str.lastIndexOf('/') === str.length - 1) {
str = str.substring(0, str.length - 1); str = str.substring(0, str.length - 1);