From 35c1fcaf22100bca4f63fd89824021b198d6d94b Mon Sep 17 00:00:00 2001 From: William Bradley Date: Mon, 11 Feb 2019 22:41:01 +1300 Subject: [PATCH 1/7] Abstracted ReactDevelopmentServerMiddleware into DevelopmentServerMiddleware, obsoleted old namespace, Added Generic UseDevelopmentServer and Vue UseVueDevelopmentServer. --- .../DevelopmentServerMiddleware.cs} | 26 +++--- .../DevelopmentServerMiddlewareExtensions.cs | 87 +++++++++++++++++++ ...ctDevelopmentServerMiddlewareExtensions.cs | 16 +--- 3 files changed, 104 insertions(+), 25 deletions(-) rename src/Middleware/SpaServices.Extensions/src/{ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs => DevelopmentServer/DevelopmentServerMiddleware.cs} (77%) create mode 100644 src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs diff --git a/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs similarity index 77% rename from src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs rename to src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs index 78a7b4f03f27..bde5e9d7f5c6 100644 --- a/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs +++ b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs @@ -13,16 +13,18 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.SpaServices.Extensions.Util; -namespace Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer +namespace Microsoft.AspNetCore.SpaServices.DevelopmentServer { - internal static class ReactDevelopmentServerMiddleware + internal static class DevelopmentServerMiddleware { private const string LogCategoryName = "Microsoft.AspNetCore.SpaServices"; private static TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(5); // This is a development-time only feature, so a very long timeout is fine public static void Attach( ISpaBuilder spaBuilder, - string npmScriptName) + string npmScriptName, + string waitText, + string serverName = "App") { var sourcePath = spaBuilder.Options.SourcePath; if (string.IsNullOrEmpty(sourcePath)) @@ -38,7 +40,7 @@ public static void Attach( // Start create-react-app and attach to middleware pipeline var appBuilder = spaBuilder.ApplicationBuilder; var logger = LoggerFinder.GetOrCreateLogger(appBuilder, LogCategoryName); - var portTask = StartCreateReactAppServerAsync(sourcePath, npmScriptName, logger); + var portTask = StartCreateAppServerAsync(sourcePath, npmScriptName, waitText, serverName, logger); // Everything we proxy is hardcoded to target http://localhost because: // - the requests are always from the local machine (we're not accepting remote @@ -54,22 +56,22 @@ public static void Attach( // the first request times out, subsequent requests could still work. var timeout = spaBuilder.Options.StartupTimeout; return targetUriTask.WithTimeout(timeout, - $"The create-react-app server did not start listening for requests " + + $"The {serverName} server did not start listening for requests " + $"within the timeout period of {timeout.Seconds} seconds. " + $"Check the log output for error information."); }); } - private static async Task StartCreateReactAppServerAsync( - string sourcePath, string npmScriptName, ILogger logger) + private static async Task StartCreateAppServerAsync( + string sourcePath, string npmScriptName, string waitText, string serverName, ILogger logger) { var portNumber = TcpPortFinder.FindAvailablePort(); - logger.LogInformation($"Starting create-react-app server on port {portNumber}..."); + logger.LogInformation($"Starting {serverName} server on port {portNumber}..."); var envVars = new Dictionary { { "PORT", portNumber.ToString() }, - { "BROWSER", "none" }, // We don't want create-react-app to open its own extra browser window pointing to the internal dev server port + { "BROWSER", "none" }, // We don't want the dev server to open its own extra browser window pointing to the internal dev server port }; var npmScriptRunner = new NpmScriptRunner( sourcePath, npmScriptName, null, envVars); @@ -79,18 +81,18 @@ private static async Task StartCreateReactAppServerAsync( { try { - // Although the React dev server may eventually tell us the URL it's listening on, + // Although the dev server may eventually tell us the URL it's listening on, // it doesn't do so until it's finished compiling, and even then only if there were // no compiler warnings. So instead of waiting for that, consider it ready as soon // as it starts listening for requests. await npmScriptRunner.StdOut.WaitForMatch( - new Regex("Starting the development server", RegexOptions.None, RegexMatchTimeout)); + new Regex(waitText, RegexOptions.None, RegexMatchTimeout)); } catch (EndOfStreamException ex) { throw new InvalidOperationException( $"The NPM script '{npmScriptName}' exited without indicating that the " + - $"create-react-app server was listening for requests. The error output was: " + + $"{serverName} server was listening for requests. The error output was: " + $"{stdErrReader.ReadAsString()}", ex); } } diff --git a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs new file mode 100644 index 000000000000..f609f518cb9b --- /dev/null +++ b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs @@ -0,0 +1,87 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Builder; +using System; + +namespace Microsoft.AspNetCore.SpaServices.DevelopmentServer +{ + /// + /// Extension methods for enabling React development server middleware support. + /// + public static class DevelopmentServerMiddlewareExtensions + { + /// + /// Handles requests by passing them through to an instance of a development npm web server. + /// This means you can always serve up-to-date CLI-built resources without having + /// to run the npm web server manually. + /// + /// This feature should only be used in development. For production deployments, be + /// sure not to enable the npm web server. + /// + /// The . + /// The name of the script in your package.json file that launches the web server. + /// The text snippet identified during the build to indicate the Development Server has compiled and is ready. + /// The name of the Server used in the Console. + public static void UseDevelopmentServer( + this ISpaBuilder spaBuilder, + string npmScript, + string waitText, + string serverName = "App") + { + + if (string.IsNullOrEmpty(waitText)) + { + throw new InvalidOperationException($"To use {nameof(UseDevelopmentServer)}, you must supply a non-empty value for the {nameof(waitText)} parameter. This allows us the find when the Development Server has started."); + } + + if (spaBuilder == null) + { + throw new ArgumentNullException(nameof(spaBuilder)); + } + + var spaOptions = spaBuilder.Options; + + if (string.IsNullOrEmpty(spaOptions.SourcePath)) + { + throw new InvalidOperationException($"To use {nameof(UseDevelopmentServer)}, you must supply a non-empty value for the {nameof(SpaOptions.SourcePath)} property of {nameof(SpaOptions)} when calling {nameof(SpaApplicationBuilderExtensions.UseSpa)}."); + } + + DevelopmentServerMiddleware.Attach(spaBuilder, npmScript); + } + + /// + /// Handles requests by passing them through to an instance of the create-react-app server. + /// This means you can always serve up-to-date CLI-built resources without having + /// to run the create-react-app server manually. + /// + /// This feature should only be used in development. For production deployments, be + /// sure not to enable the create-react-app server. + /// + /// The . + /// The name of the script in your package.json file that launches the create-react-app server. + public static void UseReactDevelopmentServer( + this ISpaBuilder spaBuilder, + string npmScript) + { + UseDevelopmentServer(spaBuilder, npmScript, "Starting the development server", "create-react-app"); + } + + /// + /// Handles requests by passing them through to an instance of the vue-cli-service server. + /// This means you can always serve up-to-date CLI-built resources without having + /// to run the vue-cli-service server manually. + /// + /// This feature should only be used in development. For production deployments, be + /// sure not to enable the vue-cli-service server. + /// + /// The . + /// The name of the script in your package.json file that launches the vue-cli-service server. + public static void UseVueDevelopmentServer( + this ISpaBuilder spaBuilder, + string npmScript) + { + UseDevelopmentServer(spaBuilder, npmScript, "Starting development server...", "vue-cli-service"); + } + } +} diff --git a/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs b/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs index f58a6d1a9dd2..83edae6a322b 100644 --- a/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs +++ b/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.SpaServices.DevelopmentServer; using System; namespace Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer @@ -21,23 +22,12 @@ public static class ReactDevelopmentServerMiddlewareExtensions /// /// The . /// The name of the script in your package.json file that launches the create-react-app server. + [Obsolete("Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer.ReactDevelopmentServerMiddlewareExtensions.UseReactDevelopmentServer is deprecated, please use Microsoft.AspNetCore.SpaServices.DevelopmentServer.DevelopmentServerMiddlewareExtensions.UseReactDevelopmentServer instead.")] public static void UseReactDevelopmentServer( this ISpaBuilder spaBuilder, string npmScript) { - if (spaBuilder == null) - { - throw new ArgumentNullException(nameof(spaBuilder)); - } - - var spaOptions = spaBuilder.Options; - - if (string.IsNullOrEmpty(spaOptions.SourcePath)) - { - throw new InvalidOperationException($"To use {nameof(UseReactDevelopmentServer)}, you must supply a non-empty value for the {nameof(SpaOptions.SourcePath)} property of {nameof(SpaOptions)} when calling {nameof(SpaApplicationBuilderExtensions.UseSpa)}."); - } - - ReactDevelopmentServerMiddleware.Attach(spaBuilder, npmScript); + DevelopmentServerMiddlewareExtensions.UseReactDevelopmentServer(spaBuilder, npmScript); } } } From 8e0b778ce759d860d49f2d10be33dff67a193eba Mon Sep 17 00:00:00 2001 From: William Bradley Date: Mon, 11 Feb 2019 23:00:37 +1300 Subject: [PATCH 2/7] Fixed missing Parameters. --- .../DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs index f609f518cb9b..b7b207d76e19 100644 --- a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs +++ b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs @@ -47,7 +47,7 @@ public static void UseDevelopmentServer( throw new InvalidOperationException($"To use {nameof(UseDevelopmentServer)}, you must supply a non-empty value for the {nameof(SpaOptions.SourcePath)} property of {nameof(SpaOptions)} when calling {nameof(SpaApplicationBuilderExtensions.UseSpa)}."); } - DevelopmentServerMiddleware.Attach(spaBuilder, npmScript); + DevelopmentServerMiddleware.Attach(spaBuilder, npmScript, waitText, serverName); } /// From 09b83c98cdab233e09a04a19697e47f9df088ef4 Mon Sep 17 00:00:00 2001 From: William Bradley Date: Mon, 11 Feb 2019 23:23:32 +1300 Subject: [PATCH 3/7] Fixed React Project Templates to use new Extension. --- .../src/baseline.netcore.json | 48 ++++++++++++++++++- .../content/React-CSharp/Startup.cs | 2 +- .../content/ReactRedux-CSharp/Startup.cs | 2 +- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/Middleware/SpaServices.Extensions/src/baseline.netcore.json b/src/Middleware/SpaServices.Extensions/src/baseline.netcore.json index 21d6857e98e7..f0b6f7e34390 100644 --- a/src/Middleware/SpaServices.Extensions/src/baseline.netcore.json +++ b/src/Middleware/SpaServices.Extensions/src/baseline.netcore.json @@ -477,7 +477,7 @@ "GenericParameters": [] }, { - "Name": "Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer.ReactDevelopmentServerMiddlewareExtensions", + "Name": "Microsoft.AspNetCore.SpaServices.DevelopmentServer.DevelopmentServerMiddlewareExtensions", "Visibility": "Public", "Kind": "Class", "Abstract": true, @@ -485,6 +485,33 @@ "Sealed": true, "ImplementedInterfaces": [], "Members": [ + { + "Kind": "Method", + "Name": "UseDevelopmentServer", + "Parameters": [ + { + "Name": "spaBuilder", + "Type": "Microsoft.AspNetCore.SpaServices.ISpaBuilder" + }, + { + "Name": "npmScript", + "Type": "System.String" + }, + { + "Name": "waitText", + "Type": "System.String" + }, + { + "Name": "serverName", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Method", "Name": "UseReactDevelopmentServer", @@ -503,6 +530,25 @@ "Extension": true, "Visibility": "Public", "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "UseVueDevelopmentServer", + "Parameters": [ + { + "Name": "spaBuilder", + "Type": "Microsoft.AspNetCore.SpaServices.ISpaBuilder" + }, + { + "Name": "npmScript", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] } ], "GenericParameters": [] diff --git a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Startup.cs b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Startup.cs index 9b8508ddab20..b097c72abad6 100644 --- a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Startup.cs @@ -4,7 +4,7 @@ using Microsoft.AspNetCore.HttpsPolicy; #endif using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer; +using Microsoft.AspNetCore.SpaServices.DevelopmentServer; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; diff --git a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Startup.cs b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Startup.cs index 9b8508ddab20..b097c72abad6 100644 --- a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Startup.cs @@ -4,7 +4,7 @@ using Microsoft.AspNetCore.HttpsPolicy; #endif using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer; +using Microsoft.AspNetCore.SpaServices.DevelopmentServer; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; From c25e76b9d44642e6233210d6d6a8519f02cd6db5 Mon Sep 17 00:00:00 2001 From: William Bradley Date: Sat, 23 Feb 2019 13:14:16 +1300 Subject: [PATCH 4/7] Fixed function naming --- .../src/DevelopmentServer/DevelopmentServerMiddleware.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs index bde5e9d7f5c6..37bc88cf4590 100644 --- a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs +++ b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs @@ -40,7 +40,7 @@ public static void Attach( // Start create-react-app and attach to middleware pipeline var appBuilder = spaBuilder.ApplicationBuilder; var logger = LoggerFinder.GetOrCreateLogger(appBuilder, LogCategoryName); - var portTask = StartCreateAppServerAsync(sourcePath, npmScriptName, waitText, serverName, logger); + var portTask = StartDevServerAsync(sourcePath, npmScriptName, waitText, serverName, logger); // Everything we proxy is hardcoded to target http://localhost because: // - the requests are always from the local machine (we're not accepting remote @@ -62,7 +62,7 @@ public static void Attach( }); } - private static async Task StartCreateAppServerAsync( + private static async Task StartDevServerAsync( string sourcePath, string npmScriptName, string waitText, string serverName, ILogger logger) { var portNumber = TcpPortFinder.FindAvailablePort(); From eff333d56f2acded8346155a4139c4f1d065afcd Mon Sep 17 00:00:00 2001 From: Ellis Kenyo Date: Thu, 4 Jul 2019 14:47:14 +0100 Subject: [PATCH 5/7] Amend changes from #7452 - Removed VueDevelopmentServer - Added Dictionary for arguments to DevelopmentServer - Unobseleted ReactDevelopmentServer --- .../DevelopmentServerMiddleware.cs | 7 ++-- .../DevelopmentServerMiddlewareExtensions.cs | 36 +------------------ ...ctDevelopmentServerMiddlewareExtensions.cs | 5 ++- .../src/baseline.netcore.json | 23 +++--------- 4 files changed, 10 insertions(+), 61 deletions(-) diff --git a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs index 37bc88cf4590..dad0614a319d 100644 --- a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs +++ b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs @@ -63,18 +63,17 @@ public static void Attach( } private static async Task StartDevServerAsync( - string sourcePath, string npmScriptName, string waitText, string serverName, ILogger logger) + string sourcePath, string npmScriptName, string waitText, string serverName, ILogger logger, IDictionary extraArgs) { var portNumber = TcpPortFinder.FindAvailablePort(); logger.LogInformation($"Starting {serverName} server on port {portNumber}..."); var envVars = new Dictionary { - { "PORT", portNumber.ToString() }, - { "BROWSER", "none" }, // We don't want the dev server to open its own extra browser window pointing to the internal dev server port + { "PORT", portNumber.ToString() } }; var npmScriptRunner = new NpmScriptRunner( - sourcePath, npmScriptName, null, envVars); + sourcePath, npmScriptName, null, envVars.Union(extraArgs)); npmScriptRunner.AttachToLogger(logger); using (var stdErrReader = new EventedStreamStringReader(npmScriptRunner.StdErr)) diff --git a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs index b7b207d76e19..398aedef99e5 100644 --- a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs +++ b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Builder; @@ -49,39 +49,5 @@ public static void UseDevelopmentServer( DevelopmentServerMiddleware.Attach(spaBuilder, npmScript, waitText, serverName); } - - /// - /// Handles requests by passing them through to an instance of the create-react-app server. - /// This means you can always serve up-to-date CLI-built resources without having - /// to run the create-react-app server manually. - /// - /// This feature should only be used in development. For production deployments, be - /// sure not to enable the create-react-app server. - /// - /// The . - /// The name of the script in your package.json file that launches the create-react-app server. - public static void UseReactDevelopmentServer( - this ISpaBuilder spaBuilder, - string npmScript) - { - UseDevelopmentServer(spaBuilder, npmScript, "Starting the development server", "create-react-app"); - } - - /// - /// Handles requests by passing them through to an instance of the vue-cli-service server. - /// This means you can always serve up-to-date CLI-built resources without having - /// to run the vue-cli-service server manually. - /// - /// This feature should only be used in development. For production deployments, be - /// sure not to enable the vue-cli-service server. - /// - /// The . - /// The name of the script in your package.json file that launches the vue-cli-service server. - public static void UseVueDevelopmentServer( - this ISpaBuilder spaBuilder, - string npmScript) - { - UseDevelopmentServer(spaBuilder, npmScript, "Starting development server...", "vue-cli-service"); - } } } diff --git a/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs b/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs index 83edae6a322b..7972c74fe9b0 100644 --- a/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs +++ b/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Builder; @@ -22,12 +22,11 @@ public static class ReactDevelopmentServerMiddlewareExtensions /// /// The . /// The name of the script in your package.json file that launches the create-react-app server. - [Obsolete("Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer.ReactDevelopmentServerMiddlewareExtensions.UseReactDevelopmentServer is deprecated, please use Microsoft.AspNetCore.SpaServices.DevelopmentServer.DevelopmentServerMiddlewareExtensions.UseReactDevelopmentServer instead.")] public static void UseReactDevelopmentServer( this ISpaBuilder spaBuilder, string npmScript) { - DevelopmentServerMiddlewareExtensions.UseReactDevelopmentServer(spaBuilder, npmScript); + DevelopmentServerMiddlewareExtensions.UseReactDevelopmentServer(spaBuilder, npmScript, "Starting the development server", "create-react-app"); } } } diff --git a/src/Middleware/SpaServices.Extensions/src/baseline.netcore.json b/src/Middleware/SpaServices.Extensions/src/baseline.netcore.json index f0b6f7e34390..0d7fb947d996 100644 --- a/src/Middleware/SpaServices.Extensions/src/baseline.netcore.json +++ b/src/Middleware/SpaServices.Extensions/src/baseline.netcore.json @@ -504,25 +504,10 @@ { "Name": "serverName", "Type": "System.String" - } - ], - "ReturnType": "System.Void", - "Static": true, - "Extension": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "UseReactDevelopmentServer", - "Parameters": [ - { - "Name": "spaBuilder", - "Type": "Microsoft.AspNetCore.SpaServices.ISpaBuilder" }, { - "Name": "npmScript", - "Type": "System.String" + "Name": "extraArgs", + "Type": "System.Collections.Generic.IDictionary" } ], "ReturnType": "System.Void", @@ -533,7 +518,7 @@ }, { "Kind": "Method", - "Name": "UseVueDevelopmentServer", + "Name": "UseReactDevelopmentServer", "Parameters": [ { "Name": "spaBuilder", @@ -868,4 +853,4 @@ "GenericParameters": [] } ] -} \ No newline at end of file +} From 6e30cb2d3c5861c16fb9794dc573ebf921048591 Mon Sep 17 00:00:00 2001 From: Ellis Kenyo Date: Thu, 4 Jul 2019 15:21:54 +0100 Subject: [PATCH 6/7] Better way of merging dictionaries --- .../DevelopmentServerMiddleware.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs index dad0614a319d..e42729a787e0 100644 --- a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs +++ b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs @@ -9,6 +9,7 @@ using System; using System.IO; using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.AspNetCore.SpaServices.Extensions.Util; @@ -63,7 +64,7 @@ public static void Attach( } private static async Task StartDevServerAsync( - string sourcePath, string npmScriptName, string waitText, string serverName, ILogger logger, IDictionary extraArgs) + string sourcePath, string npmScriptName, string waitText, string serverName, ILogger logger, Dictionary extraArgs = null) { var portNumber = TcpPortFinder.FindAvailablePort(); logger.LogInformation($"Starting {serverName} server on port {portNumber}..."); @@ -72,8 +73,17 @@ private static async Task StartDevServerAsync( { { "PORT", portNumber.ToString() } }; + if (extraArgs == null) + { + extraArgs = new Dictionary + { + { "BROWSER", "None" } + }; + } + var extraKeys = new HashSet(extraArgs.Keys); + extraKeys.UnionWith(envVars.Keys); var npmScriptRunner = new NpmScriptRunner( - sourcePath, npmScriptName, null, envVars.Union(extraArgs)); + sourcePath, npmScriptName, null, envVars); npmScriptRunner.AttachToLogger(logger); using (var stdErrReader = new EventedStreamStringReader(npmScriptRunner.StdErr)) From cd918624fcee942d44f6824fb6e4f5dde8674a2c Mon Sep 17 00:00:00 2001 From: Ellis Kenyo Date: Tue, 9 Jul 2019 09:39:46 +0100 Subject: [PATCH 7/7] Tidied up args --- .../DevelopmentServerMiddleware.cs | 19 ++++++++----------- .../DevelopmentServerMiddlewareExtensions.cs | 6 ++++-- ...ctDevelopmentServerMiddlewareExtensions.cs | 2 +- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs index e42729a787e0..81b8608f9b00 100644 --- a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs +++ b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddleware.cs @@ -25,6 +25,7 @@ public static void Attach( ISpaBuilder spaBuilder, string npmScriptName, string waitText, + Dictionary extraArgs, string serverName = "App") { var sourcePath = spaBuilder.Options.SourcePath; @@ -41,7 +42,7 @@ public static void Attach( // Start create-react-app and attach to middleware pipeline var appBuilder = spaBuilder.ApplicationBuilder; var logger = LoggerFinder.GetOrCreateLogger(appBuilder, LogCategoryName); - var portTask = StartDevServerAsync(sourcePath, npmScriptName, waitText, serverName, logger); + var portTask = StartDevServerAsync(sourcePath, npmScriptName, waitText, serverName, logger, extraArgs); // Everything we proxy is hardcoded to target http://localhost because: // - the requests are always from the local machine (we're not accepting remote @@ -73,17 +74,13 @@ private static async Task StartDevServerAsync( { { "PORT", portNumber.ToString() } }; - if (extraArgs == null) - { - extraArgs = new Dictionary - { - { "BROWSER", "None" } - }; - } - var extraKeys = new HashSet(extraArgs.Keys); - extraKeys.UnionWith(envVars.Keys); + + waitText = waitText.Replace("$PORT", portNumber.ToString()); + + extraArgs = extraArgs.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Replace("$PORT", portNumber.ToString())); + var npmScriptRunner = new NpmScriptRunner( - sourcePath, npmScriptName, null, envVars); + sourcePath, npmScriptName, string.Join(" ", extraArgs.Select(x => x.Key + " " + x.Value).ToArray()), envVars); npmScriptRunner.AttachToLogger(logger); using (var stdErrReader = new EventedStreamStringReader(npmScriptRunner.StdErr)) diff --git a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs index 398aedef99e5..84ab1864e786 100644 --- a/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs +++ b/src/Middleware/SpaServices.Extensions/src/DevelopmentServer/DevelopmentServerMiddlewareExtensions.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Builder; using System; +using System.Collections.Generic; namespace Microsoft.AspNetCore.SpaServices.DevelopmentServer { @@ -27,7 +28,8 @@ public static void UseDevelopmentServer( this ISpaBuilder spaBuilder, string npmScript, string waitText, - string serverName = "App") + string serverName = "App", + Dictionary extraArgs = null) { if (string.IsNullOrEmpty(waitText)) @@ -47,7 +49,7 @@ public static void UseDevelopmentServer( throw new InvalidOperationException($"To use {nameof(UseDevelopmentServer)}, you must supply a non-empty value for the {nameof(SpaOptions.SourcePath)} property of {nameof(SpaOptions)} when calling {nameof(SpaApplicationBuilderExtensions.UseSpa)}."); } - DevelopmentServerMiddleware.Attach(spaBuilder, npmScript, waitText, serverName); + DevelopmentServerMiddleware.Attach(spaBuilder, npmScript, waitText, extraArgs, serverName); } } } diff --git a/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs b/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs index 7972c74fe9b0..69ff9677a18e 100644 --- a/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs +++ b/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddlewareExtensions.cs @@ -26,7 +26,7 @@ public static void UseReactDevelopmentServer( this ISpaBuilder spaBuilder, string npmScript) { - DevelopmentServerMiddlewareExtensions.UseReactDevelopmentServer(spaBuilder, npmScript, "Starting the development server", "create-react-app"); + DevelopmentServerMiddlewareExtensions.UseDevelopmentServer(spaBuilder, npmScript, "Starting the development server", "create-react-app"); } } }