mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-22 17:47:53 +00:00
Merge branch 'rel/2.0.0-preview2' into dev
This commit is contained in:
@@ -16,7 +16,8 @@
|
|||||||
<PackageReference Include="Internal.AspNetCore.Sdk" Version="$(InternalAspNetCoreSdkVersion)" PrivateAssets="All" />
|
<PackageReference Include="Internal.AspNetCore.Sdk" Version="$(InternalAspNetCoreSdkVersion)" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework' AND '$(OutputType)'=='library'">
|
<ItemGroup Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework'">
|
||||||
<PackageReference Include="NETStandard.Library" Version="$(BundledNETStandardPackageVersion)" />
|
<PackageReference Include="NETStandard.Library" Version="$(BundledNETStandardPackageVersion)" />
|
||||||
|
<PackageReference Include="NETStandard.Library.NETFramework" Version="$(NETStandardLibraryNETFrameworkVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AspNetCoreVersion>2.0.0-*</AspNetCoreVersion>
|
<AspNetCoreVersion>2.0.0-*</AspNetCoreVersion>
|
||||||
<AutoMapperVersion>5.0.2</AutoMapperVersion>
|
<AutoMapperVersion>5.0.2</AutoMapperVersion>
|
||||||
<CoreFxVersion>4.3.0</CoreFxVersion>
|
|
||||||
<InternalAspNetCoreSdkVersion>2.1.0-*</InternalAspNetCoreSdkVersion>
|
<InternalAspNetCoreSdkVersion>2.1.0-*</InternalAspNetCoreSdkVersion>
|
||||||
<JsonNetVersion>10.0.1</JsonNetVersion>
|
<JsonNetVersion>10.0.1</JsonNetVersion>
|
||||||
<NETStandardImplicitPackageVersion>$(BundledNETStandardPackageVersion)</NETStandardImplicitPackageVersion>
|
<NETStandardImplicitPackageVersion>$(BundledNETStandardPackageVersion)</NETStandardImplicitPackageVersion>
|
||||||
|
<NETStandardLibraryNETFrameworkVersion>2.0.0-*</NETStandardLibraryNETFrameworkVersion>
|
||||||
<RuntimeFrameworkVersion Condition="'$(TargetFramework)'=='netcoreapp2.0'">2.0.0-*</RuntimeFrameworkVersion>
|
<RuntimeFrameworkVersion Condition="'$(TargetFramework)'=='netcoreapp2.0'">2.0.0-*</RuntimeFrameworkVersion>
|
||||||
<ThreadingDataflowVersion>4.7.0</ThreadingDataflowVersion>
|
<ThreadingDataflowVersion>4.7.0</ThreadingDataflowVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
<Project>
|
|
||||||
<Target Name="NpmRestore" AfterTargets="Restore" Condition="'$(PreflightRestore)' != 'true'">
|
|
||||||
<ItemGroup>
|
|
||||||
<NpmModules Include="$(RepositoryRoot)**\package.json"
|
|
||||||
Exclude="$(RepositoryRoot)**\node_modules\**\*" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Message Text="Restoring NPM modules for: %0A - @(NpmModules -> '%(FullPath)','%0A - ')" Importance="high" />
|
|
||||||
|
|
||||||
<Exec Command="npm install --silent" WorkingDirectory="%(NpmModules.RootDir)%(Directory)" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<Import Project="..\..\..\build\dependencies.props" />
|
<Import Project="..\..\..\build\common.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<OutputType>exe</OutputType>
|
<OutputType>exe</OutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<Import Project="..\..\..\build\dependencies.props" />
|
<Import Project="..\..\..\build\common.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
|
||||||
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace Webpack.ActionResults
|
|||||||
{
|
{
|
||||||
var nodeServices = context.HttpContext.RequestServices.GetRequiredService<INodeServices>();
|
var nodeServices = context.HttpContext.RequestServices.GetRequiredService<INodeServices>();
|
||||||
var hostEnv = context.HttpContext.RequestServices.GetRequiredService<IHostingEnvironment>();
|
var hostEnv = context.HttpContext.RequestServices.GetRequiredService<IHostingEnvironment>();
|
||||||
|
var applicationLifetime = context.HttpContext.RequestServices.GetRequiredService<IApplicationLifetime>();
|
||||||
var applicationBasePath = hostEnv.ContentRootPath;
|
var applicationBasePath = hostEnv.ContentRootPath;
|
||||||
var request = context.HttpContext.Request;
|
var request = context.HttpContext.Request;
|
||||||
var response = context.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
@@ -34,6 +35,7 @@ namespace Webpack.ActionResults
|
|||||||
var prerenderedHtml = await Prerenderer.RenderToString(
|
var prerenderedHtml = await Prerenderer.RenderToString(
|
||||||
applicationBasePath,
|
applicationBasePath,
|
||||||
nodeServices,
|
nodeServices,
|
||||||
|
applicationLifetime.ApplicationStopping,
|
||||||
_moduleExport,
|
_moduleExport,
|
||||||
request.GetEncodedUrl(),
|
request.GetEncodedUrl(),
|
||||||
request.Path + request.QueryString.Value,
|
request.Path + request.QueryString.Value,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<Import Project="..\..\..\build\dependencies.props" />
|
<Import Project="..\..\..\build\common.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
|
||||||
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>Socket-based RPC for Microsoft.AspNetCore.NodeServices.</Description>
|
<Description>Socket-based RPC for Microsoft.AspNetCore.NodeServices.</Description>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<PackageTags>aspnetcore;aspnetcoremvc;nodeservices</PackageTags>
|
<PackageTags>aspnetcore;aspnetcoremvc;nodeservices</PackageTags>
|
||||||
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -15,14 +15,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
|
<ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
|
|
||||||
<PackageReference Include="Microsoft.Tpl.Dataflow" Version="$(MicrosoftDataflowVersion)" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">
|
|
||||||
<PackageReference Include="System.IO.Pipes" Version="$(CoreFxVersion)" />
|
|
||||||
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="$(ThreadingDataflowVersion)" />
|
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="$(ThreadingDataflowVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,7 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
|||||||
PipeDirection.InOut,
|
PipeDirection.InOut,
|
||||||
PipeOptions.Asynchronous);
|
PipeOptions.Asynchronous);
|
||||||
|
|
||||||
#if NET451
|
|
||||||
_namedPipeClientStream.Connect();
|
|
||||||
#else
|
|
||||||
await _namedPipeClientStream.ConnectAsync().ConfigureAwait(false);
|
await _namedPipeClientStream.ConnectAsync().ConfigureAwait(false);
|
||||||
#endif
|
|
||||||
|
|
||||||
return _namedPipeClientStream;
|
return _namedPipeClientStream;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
|||||||
|
|
||||||
public static StreamConnection Create()
|
public static StreamConnection Create()
|
||||||
{
|
{
|
||||||
#if NET451
|
|
||||||
return new NamedPipeConnection();
|
|
||||||
#else
|
|
||||||
var useNamedPipes = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(
|
var useNamedPipes = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(
|
||||||
System.Runtime.InteropServices.OSPlatform.Windows);
|
System.Runtime.InteropServices.OSPlatform.Windows);
|
||||||
if (useNamedPipes)
|
if (useNamedPipes)
|
||||||
@@ -24,7 +21,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
|||||||
{
|
{
|
||||||
return new UnixDomainSocketConnection();
|
return new UnixDomainSocketConnection();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,16 +10,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
|||||||
private NetworkStream _networkStream;
|
private NetworkStream _networkStream;
|
||||||
private Socket _socket;
|
private Socket _socket;
|
||||||
|
|
||||||
#if NET451
|
|
||||||
public override Task<Stream> Open(string address)
|
|
||||||
{
|
|
||||||
// The 'null' assignments avoid the compiler warnings about unassigned fields.
|
|
||||||
// Note that this whole class isn't supported on .NET 4.5.1, since that's not cross-platform.
|
|
||||||
_networkStream = null;
|
|
||||||
_socket = null;
|
|
||||||
throw new System.PlatformNotSupportedException();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
public override async Task<Stream> Open(string address)
|
public override async Task<Stream> Open(string address)
|
||||||
{
|
{
|
||||||
var endPoint = new UnixDomainSocketEndPoint("/tmp/" + address);
|
var endPoint = new UnixDomainSocketEndPoint("/tmp/" + address);
|
||||||
@@ -28,7 +18,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
|||||||
_networkStream = new NetworkStream(_socket);
|
_networkStream = new NetworkStream(_socket);
|
||||||
return _networkStream;
|
return _networkStream;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -59,11 +59,7 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if NET451
|
|
||||||
_encodedPath = new byte[0];
|
|
||||||
#else
|
|
||||||
_encodedPath = Array.Empty<byte>();
|
_encodedPath = Array.Empty<byte>();
|
||||||
#endif
|
|
||||||
_path = string.Empty;
|
_path = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets
|
|||||||
options.ProjectPath,
|
options.ProjectPath,
|
||||||
options.WatchFileExtensions,
|
options.WatchFileExtensions,
|
||||||
MakeNewCommandLineOptions(socketAddress),
|
MakeNewCommandLineOptions(socketAddress),
|
||||||
|
options.ApplicationStoppingToken,
|
||||||
options.NodeInstanceOutputLogger,
|
options.NodeInstanceOutputLogger,
|
||||||
options.EnvironmentVariables,
|
options.EnvironmentVariables,
|
||||||
options.InvocationTimeoutMilliseconds,
|
options.InvocationTimeoutMilliseconds,
|
||||||
|
|||||||
@@ -12,11 +12,7 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class VirtualConnection : Stream
|
internal class VirtualConnection : Stream
|
||||||
{
|
{
|
||||||
#if NET451
|
|
||||||
private readonly static Task CompletedTask = Task.FromResult((object)null);
|
|
||||||
#else
|
|
||||||
private readonly static Task CompletedTask = Task.CompletedTask;
|
private readonly static Task CompletedTask = Task.CompletedTask;
|
||||||
#endif
|
|
||||||
private VirtualConnectionClient _host;
|
private VirtualConnectionClient _host;
|
||||||
private readonly BufferBlock<byte[]> _receivedDataQueue = new BufferBlock<byte[]>();
|
private readonly BufferBlock<byte[]> _receivedDataQueue = new BufferBlock<byte[]>();
|
||||||
private ArraySegment<byte> _receivedDataNotYetUsed;
|
private ArraySegment<byte> _receivedDataNotYetUsed;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using Microsoft.AspNetCore.NodeServices.HostingModels;
|
using Microsoft.AspNetCore.NodeServices.HostingModels;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -42,6 +43,12 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
EnvironmentVariables["NODE_ENV"] = hostEnv.IsDevelopment() ? "development" : "production"; // De-facto standard values for Node
|
EnvironmentVariables["NODE_ENV"] = hostEnv.IsDevelopment() ? "development" : "production"; // De-facto standard values for Node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var applicationLifetime = serviceProvider.GetService<IApplicationLifetime>();
|
||||||
|
if (applicationLifetime != null)
|
||||||
|
{
|
||||||
|
ApplicationStoppingToken = applicationLifetime.ApplicationStopping;
|
||||||
|
}
|
||||||
|
|
||||||
// If the DI system gives us a logger, use it. Otherwise, set up a default one.
|
// If the DI system gives us a logger, use it. Otherwise, set up a default one.
|
||||||
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
||||||
NodeInstanceOutputLogger = loggerFactory != null
|
NodeInstanceOutputLogger = loggerFactory != null
|
||||||
@@ -93,5 +100,10 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
/// Specifies the maximum duration, in milliseconds, that your .NET code should wait for Node.js RPC calls to return.
|
/// Specifies the maximum duration, in milliseconds, that your .NET code should wait for Node.js RPC calls to return.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int InvocationTimeoutMilliseconds { get; set; }
|
public int InvocationTimeoutMilliseconds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A token that indicates when the host application is stopping.
|
||||||
|
/// </summary>
|
||||||
|
public CancellationToken ApplicationStoppingToken { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,6 +42,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
|||||||
options.ProjectPath,
|
options.ProjectPath,
|
||||||
options.WatchFileExtensions,
|
options.WatchFileExtensions,
|
||||||
MakeCommandLineOptions(port),
|
MakeCommandLineOptions(port),
|
||||||
|
options.ApplicationStoppingToken,
|
||||||
options.NodeInstanceOutputLogger,
|
options.NodeInstanceOutputLogger,
|
||||||
options.EnvironmentVariables,
|
options.EnvironmentVariables,
|
||||||
options.InvocationTimeoutMilliseconds,
|
options.InvocationTimeoutMilliseconds,
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
|||||||
/// <param name="projectPath">The root path of the current project. This is used when resolving Node.js module paths relative to the project root.</param>
|
/// <param name="projectPath">The root path of the current project. This is used when resolving Node.js module paths relative to the project root.</param>
|
||||||
/// <param name="watchFileExtensions">The filename extensions that should be watched within the project root. The Node instance will automatically shut itself down if any matching file changes.</param>
|
/// <param name="watchFileExtensions">The filename extensions that should be watched within the project root. The Node instance will automatically shut itself down if any matching file changes.</param>
|
||||||
/// <param name="commandLineArguments">Additional command-line arguments to be passed to the Node.js instance.</param>
|
/// <param name="commandLineArguments">Additional command-line arguments to be passed to the Node.js instance.</param>
|
||||||
|
/// <param name="applicationStoppingToken">A token that indicates when the host application is stopping.</param>
|
||||||
/// <param name="nodeOutputLogger">The <see cref="ILogger"/> to which the Node.js instance's stdout/stderr (and other log information) should be written.</param>
|
/// <param name="nodeOutputLogger">The <see cref="ILogger"/> to which the Node.js instance's stdout/stderr (and other log information) should be written.</param>
|
||||||
/// <param name="environmentVars">Environment variables to be set on the Node.js process.</param>
|
/// <param name="environmentVars">Environment variables to be set on the Node.js process.</param>
|
||||||
/// <param name="invocationTimeoutMilliseconds">The maximum duration, in milliseconds, to wait for RPC calls to complete.</param>
|
/// <param name="invocationTimeoutMilliseconds">The maximum duration, in milliseconds, to wait for RPC calls to complete.</param>
|
||||||
@@ -55,6 +56,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
|||||||
string projectPath,
|
string projectPath,
|
||||||
string[] watchFileExtensions,
|
string[] watchFileExtensions,
|
||||||
string commandLineArguments,
|
string commandLineArguments,
|
||||||
|
CancellationToken applicationStoppingToken,
|
||||||
ILogger nodeOutputLogger,
|
ILogger nodeOutputLogger,
|
||||||
IDictionary<string, string> environmentVars,
|
IDictionary<string, string> environmentVars,
|
||||||
int invocationTimeoutMilliseconds,
|
int invocationTimeoutMilliseconds,
|
||||||
@@ -67,7 +69,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
|||||||
}
|
}
|
||||||
|
|
||||||
OutputLogger = nodeOutputLogger;
|
OutputLogger = nodeOutputLogger;
|
||||||
_entryPointScript = new StringAsTempFile(entryPointScript);
|
_entryPointScript = new StringAsTempFile(entryPointScript, applicationStoppingToken);
|
||||||
_invocationTimeoutMilliseconds = invocationTimeoutMilliseconds;
|
_invocationTimeoutMilliseconds = invocationTimeoutMilliseconds;
|
||||||
_launchWithDebugging = launchWithDebugging;
|
_launchWithDebugging = launchWithDebugging;
|
||||||
|
|
||||||
@@ -315,11 +317,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
|||||||
|
|
||||||
private static void SetEnvironmentVariable(ProcessStartInfo startInfo, string name, string value)
|
private static void SetEnvironmentVariable(ProcessStartInfo startInfo, string name, string value)
|
||||||
{
|
{
|
||||||
#if NET451
|
|
||||||
startInfo.EnvironmentVariables[name] = value;
|
|
||||||
#else
|
|
||||||
startInfo.Environment[name] = value;
|
startInfo.Environment[name] = value;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Process LaunchNodeProcess(ProcessStartInfo startInfo)
|
private static Process LaunchNodeProcess(ProcessStartInfo startInfo)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>Invoke Node.js modules at runtime in ASP.NET Core applications.</Description>
|
<Description>Invoke Node.js modules at runtime in ASP.NET Core applications.</Description>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<PackageTags>aspnetcore;aspnetcoremvc;nodeservices</PackageTags>
|
<PackageTags>aspnetcore;aspnetcoremvc;nodeservices</PackageTags>
|
||||||
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
@@ -20,12 +20,6 @@
|
|||||||
<PackageReference Include="Newtonsoft.Json" Version="$(JsonNetVersion)" />
|
<PackageReference Include="Newtonsoft.Json" Version="$(JsonNetVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">
|
|
||||||
<PackageReference Include="System.Diagnostics.Process" Version="$(CoreFxVersion)" />
|
|
||||||
<PackageReference Include="System.IO.FileSystem.Watcher" Version="$(CoreFxVersion)" />
|
|
||||||
<PackageReference Include="System.Runtime.Loader" Version="$(CoreFxVersion)" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
|
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
|
||||||
<Exec Command="npm install" />
|
<Exec Command="npm install" />
|
||||||
<Exec Command="node node_modules/webpack/bin/webpack.js" />
|
<Exec Command="node node_modules/webpack/bin/webpack.js" />
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.NodeServices
|
namespace Microsoft.AspNetCore.NodeServices
|
||||||
{
|
{
|
||||||
@@ -11,27 +12,21 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
private bool _disposedValue;
|
private bool _disposedValue;
|
||||||
private bool _hasDeletedTempFile;
|
private bool _hasDeletedTempFile;
|
||||||
private object _fileDeletionLock = new object();
|
private object _fileDeletionLock = new object();
|
||||||
|
private IDisposable _applicationLifetimeRegistration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new instance of <see cref="StringAsTempFile"/>.
|
/// Create a new instance of <see cref="StringAsTempFile"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">The contents of the temporary file to be created.</param>
|
/// <param name="content">The contents of the temporary file to be created.</param>
|
||||||
public StringAsTempFile(string content)
|
/// <param name="applicationStoppingToken">A token that indicates when the host application is stopping.</param>
|
||||||
|
public StringAsTempFile(string content, CancellationToken applicationStoppingToken)
|
||||||
{
|
{
|
||||||
FileName = Path.GetTempFileName();
|
FileName = Path.GetTempFileName();
|
||||||
File.WriteAllText(FileName, content);
|
File.WriteAllText(FileName, content);
|
||||||
|
|
||||||
// Because .NET finalizers don't reliably run when the process is terminating, also
|
// Because .NET finalizers don't reliably run when the process is terminating, also
|
||||||
// add event handlers for other shutdown scenarios.
|
// add event handlers for other shutdown scenarios.
|
||||||
#if NET451
|
_applicationLifetimeRegistration = applicationStoppingToken.Register(EnsureTempFileDeleted);
|
||||||
AppDomain.CurrentDomain.ProcessExit += HandleProcessExit;
|
|
||||||
AppDomain.CurrentDomain.DomainUnload += HandleProcessExit;
|
|
||||||
#else
|
|
||||||
// Note that this still doesn't capture SIGKILL (at least on macOS) - there doesn't
|
|
||||||
// appear to be a way of doing that. So in that case, the temporary file will be
|
|
||||||
// left behind.
|
|
||||||
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += HandleAssemblyUnloading;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -55,12 +50,7 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
// Dispose managed state
|
// Dispose managed state
|
||||||
#if NET451
|
_applicationLifetimeRegistration.Dispose();
|
||||||
AppDomain.CurrentDomain.ProcessExit -= HandleProcessExit;
|
|
||||||
AppDomain.CurrentDomain.DomainUnload -= HandleProcessExit;
|
|
||||||
#else
|
|
||||||
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading -= HandleAssemblyUnloading;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EnsureTempFileDeleted();
|
EnsureTempFileDeleted();
|
||||||
@@ -81,18 +71,6 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NET451
|
|
||||||
private void HandleProcessExit(object sender, EventArgs args)
|
|
||||||
{
|
|
||||||
EnsureTempFileDeleted();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
private void HandleAssemblyUnloading(System.Runtime.Loader.AssemblyLoadContext context)
|
|
||||||
{
|
|
||||||
EnsureTempFileDeleted();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implements the finalization part of the IDisposable pattern by calling Dispose(false).
|
/// Implements the finalization part of the IDisposable pattern by calling Dispose(false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>Helpers for building single-page applications on ASP.NET MVC Core.</Description>
|
<Description>Helpers for building single-page applications on ASP.NET MVC Core.</Description>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<PackageTags>aspnetcore;aspnetcoremvc;nodeservices</PackageTags>
|
<PackageTags>aspnetcore;aspnetcoremvc;nodeservices</PackageTags>
|
||||||
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Content\**\*" />
|
<EmbeddedResource Include="Content\**\*" />
|
||||||
<ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
|
<ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="$(AspNetCoreVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="$(AspNetCoreVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
|
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
@@ -24,6 +25,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
|||||||
private static INodeServices _fallbackNodeServices; // Used only if no INodeServices was registered with DI
|
private static INodeServices _fallbackNodeServices; // Used only if no INodeServices was registered with DI
|
||||||
|
|
||||||
private readonly string _applicationBasePath;
|
private readonly string _applicationBasePath;
|
||||||
|
private readonly CancellationToken _applicationStoppingToken;
|
||||||
private readonly INodeServices _nodeServices;
|
private readonly INodeServices _nodeServices;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -35,6 +37,9 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
|||||||
var hostEnv = (IHostingEnvironment) serviceProvider.GetService(typeof(IHostingEnvironment));
|
var hostEnv = (IHostingEnvironment) serviceProvider.GetService(typeof(IHostingEnvironment));
|
||||||
_nodeServices = (INodeServices) serviceProvider.GetService(typeof(INodeServices)) ?? _fallbackNodeServices;
|
_nodeServices = (INodeServices) serviceProvider.GetService(typeof(INodeServices)) ?? _fallbackNodeServices;
|
||||||
_applicationBasePath = hostEnv.ContentRootPath;
|
_applicationBasePath = hostEnv.ContentRootPath;
|
||||||
|
|
||||||
|
var applicationLifetime = (IApplicationLifetime) serviceProvider.GetService(typeof(IApplicationLifetime));
|
||||||
|
_applicationStoppingToken = applicationLifetime.ApplicationStopping;
|
||||||
|
|
||||||
// Consider removing the following. Having it means you can get away with not putting app.AddNodeServices()
|
// Consider removing the following. Having it means you can get away with not putting app.AddNodeServices()
|
||||||
// in your startup file, but then again it might be confusing that you don't need to.
|
// in your startup file, but then again it might be confusing that you don't need to.
|
||||||
@@ -101,6 +106,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
|||||||
var result = await Prerenderer.RenderToString(
|
var result = await Prerenderer.RenderToString(
|
||||||
_applicationBasePath,
|
_applicationBasePath,
|
||||||
_nodeServices,
|
_nodeServices,
|
||||||
|
_applicationStoppingToken,
|
||||||
new JavaScriptModuleExport(ModuleName)
|
new JavaScriptModuleExport(ModuleName)
|
||||||
{
|
{
|
||||||
ExportName = ExportName
|
ExportName = ExportName
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.NodeServices;
|
using Microsoft.AspNetCore.NodeServices;
|
||||||
|
|
||||||
@@ -9,22 +10,16 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Prerenderer
|
public static class Prerenderer
|
||||||
{
|
{
|
||||||
private static readonly Lazy<StringAsTempFile> NodeScript;
|
private static readonly object CreateNodeScriptLock = new object();
|
||||||
|
|
||||||
static Prerenderer()
|
private static StringAsTempFile NodeScript;
|
||||||
{
|
|
||||||
NodeScript = new Lazy<StringAsTempFile>(() =>
|
|
||||||
{
|
|
||||||
var script = EmbeddedResourceReader.Read(typeof(Prerenderer), "/Content/Node/prerenderer.js");
|
|
||||||
return new StringAsTempFile(script); // Will be cleaned up on process exit
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs server-side prerendering by invoking code in Node.js.
|
/// Performs server-side prerendering by invoking code in Node.js.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="applicationBasePath">The root path to your application. This is used when resolving project-relative paths.</param>
|
/// <param name="applicationBasePath">The root path to your application. This is used when resolving project-relative paths.</param>
|
||||||
/// <param name="nodeServices">The instance of <see cref="INodeServices"/> that will be used to invoke JavaScript code.</param>
|
/// <param name="nodeServices">The instance of <see cref="INodeServices"/> that will be used to invoke JavaScript code.</param>
|
||||||
|
/// <param name="applicationStoppingToken">A token that indicates when the host application is stopping.</param>
|
||||||
/// <param name="bootModule">The path to the JavaScript file containing the prerendering logic.</param>
|
/// <param name="bootModule">The path to the JavaScript file containing the prerendering logic.</param>
|
||||||
/// <param name="requestAbsoluteUrl">The URL of the currently-executing HTTP request. This is supplied to the prerendering code.</param>
|
/// <param name="requestAbsoluteUrl">The URL of the currently-executing HTTP request. This is supplied to the prerendering code.</param>
|
||||||
/// <param name="requestPathAndQuery">The path and query part of the URL of the currently-executing HTTP request. This is supplied to the prerendering code.</param>
|
/// <param name="requestPathAndQuery">The path and query part of the URL of the currently-executing HTTP request. This is supplied to the prerendering code.</param>
|
||||||
@@ -35,6 +30,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
|||||||
public static Task<RenderToStringResult> RenderToString(
|
public static Task<RenderToStringResult> RenderToString(
|
||||||
string applicationBasePath,
|
string applicationBasePath,
|
||||||
INodeServices nodeServices,
|
INodeServices nodeServices,
|
||||||
|
CancellationToken applicationStoppingToken,
|
||||||
JavaScriptModuleExport bootModule,
|
JavaScriptModuleExport bootModule,
|
||||||
string requestAbsoluteUrl,
|
string requestAbsoluteUrl,
|
||||||
string requestPathAndQuery,
|
string requestPathAndQuery,
|
||||||
@@ -43,7 +39,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
|||||||
string requestPathBase)
|
string requestPathBase)
|
||||||
{
|
{
|
||||||
return nodeServices.InvokeExportAsync<RenderToStringResult>(
|
return nodeServices.InvokeExportAsync<RenderToStringResult>(
|
||||||
NodeScript.Value.FileName,
|
GetNodeScriptFilename(applicationStoppingToken),
|
||||||
"renderToString",
|
"renderToString",
|
||||||
applicationBasePath,
|
applicationBasePath,
|
||||||
bootModule,
|
bootModule,
|
||||||
@@ -53,5 +49,19 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
|||||||
timeoutMilliseconds,
|
timeoutMilliseconds,
|
||||||
requestPathBase);
|
requestPathBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetNodeScriptFilename(CancellationToken applicationStoppingToken)
|
||||||
|
{
|
||||||
|
lock(CreateNodeScriptLock)
|
||||||
|
{
|
||||||
|
if (NodeScript == null)
|
||||||
|
{
|
||||||
|
var script = EmbeddedResourceReader.Read(typeof(Prerenderer), "/Content/Node/prerenderer.js");
|
||||||
|
NodeScript = new StringAsTempFile(script, applicationStoppingToken); // Will be cleaned up on process exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NodeScript.FileName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.Builder
|
|||||||
// Get a filename matching the middleware Node script
|
// Get a filename matching the middleware Node script
|
||||||
var script = EmbeddedResourceReader.Read(typeof(WebpackDevMiddleware),
|
var script = EmbeddedResourceReader.Read(typeof(WebpackDevMiddleware),
|
||||||
"/Content/Node/webpack-dev-middleware.js");
|
"/Content/Node/webpack-dev-middleware.js");
|
||||||
var nodeScript = new StringAsTempFile(script); // Will be cleaned up on process exit
|
var nodeScript = new StringAsTempFile(script, nodeServicesOptions.ApplicationStoppingToken); // Will be cleaned up on process exit
|
||||||
|
|
||||||
// Ideally, this would be relative to the application's PathBase (so it could work in virtual directories)
|
// Ideally, this would be relative to the application's PathBase (so it could work in virtual directories)
|
||||||
// but it's not clear that such information exists during application startup, as opposed to within the context
|
// but it's not clear that such information exists during application startup, as opposed to within the context
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-*" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-*" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-*" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-*" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-*" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-*" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user