Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions AspNetCore.SpaYarp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net6Startup", "samples\Net6
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetMultipleSpasYarp", "samples\AspNetMultipleSpaYarp\AspNetMultipleSpasYarp.csproj", "{FFE0C2AC-6DEF-4CB4-B987-60B6C1C38912}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetMultipleSpasYarpAuto", "samples\AspNetMultipleSpaYarpAuto\AspNetMultipleSpasYarpAuto.csproj", "{285BD33E-E3FA-43CA-A20E-6D9D28422C05}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -41,6 +43,10 @@ Global
{FFE0C2AC-6DEF-4CB4-B987-60B6C1C38912}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFE0C2AC-6DEF-4CB4-B987-60B6C1C38912}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFE0C2AC-6DEF-4CB4-B987-60B6C1C38912}.Release|Any CPU.Build.0 = Release|Any CPU
{285BD33E-E3FA-43CA-A20E-6D9D28422C05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{285BD33E-E3FA-43CA-A20E-6D9D28422C05}.Debug|Any CPU.Build.0 = Debug|Any CPU
{285BD33E-E3FA-43CA-A20E-6D9D28422C05}.Release|Any CPU.ActiveCfg = Release|Any CPU
{285BD33E-E3FA-43CA-A20E-6D9D28422C05}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -49,6 +55,7 @@ Global
{E3826EDD-0370-4A40-A1F9-1B07ABEBDDFD} = {D05AF6E1-A5A4-429A-AB68-34669DDE7364}
{6E174FC6-F6E0-407A-9F75-1D6B84BB946D} = {D05AF6E1-A5A4-429A-AB68-34669DDE7364}
{FFE0C2AC-6DEF-4CB4-B987-60B6C1C38912} = {D05AF6E1-A5A4-429A-AB68-34669DDE7364}
{285BD33E-E3FA-43CA-A20E-6D9D28422C05} = {D05AF6E1-A5A4-429A-AB68-34669DDE7364}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {64A1B0D6-615B-45D8-9F1C-593B55C3E840}
Expand Down
31 changes: 27 additions & 4 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,38 @@ public class Startup

This feature lets you combine multiple SPA dev servers into one, with each providing its site to a separate path.

There is a sample demonstrating how to do this as well.
There is simple forwarding approach, which expects Dev Servers to be started manually:

```cs
app.UseSpaYarpMiddleware();
app.MapSpaYarp("one", "https://localhost:44478");
app.MapSpaYarp("two", "https://localhost:44479");
app.MapSpaYarpForwarder("one", "https://localhost:44478");
app.MapSpaYarpForwarder("two", "https://localhost:44479");
```

And there is also more complex approach which allows Dev Servers to be started automatically:

```cs
app.MapSpaYarp<DevServerOptionsOne>(preserveMatchedPathSegment: true);
app.MapSpaYarp<DevServerOptionsTwo>(preserveMatchedPathSegment: true);

...

class DevServerOptionsOne : AspNetCore.SpaYarp.SpaDevelopmentServerOptions
{
public override string WorkingDirectory => Path.Combine(base.WorkingDirectory, "ClientAppOne");
public override string PublicPath => "one";
public override string ClientUrl => "https://localhost:44478";
}

class DevServerOptionsTwo : AspNetCore.SpaYarp.SpaDevelopmentServerOptions
{
public override string WorkingDirectory => Path.Combine(base.WorkingDirectory, "ClientAppTwo");
public override string PublicPath => "two";
public override string ClientUrl => "https://localhost:44479";
}
```

There are samples demonstrating how to do this as well.

## Migrate from SpaProxy

This guide assumes that you are using the default ASP.NET Core with Angular Template (but should work the same for other frameworks too).
Expand Down
22 changes: 22 additions & 0 deletions samples/AspNetMultipleSpaYarp/Pages/Index.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@page "/"

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>AspNetMultipleSpasYarp</title>

<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<ul>
<li>
<a href="/one">One</a>
</li>
<li>
<a href="/two">Two</a>
</li>
</ul>
</body>
</html>
16 changes: 6 additions & 10 deletions samples/AspNetMultipleSpaYarp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();

// Like with Microsoft.AspNetCore.SpaProxy, a 'spa.proxy.json' file gets generated based on the values in the project file (SpaRoot, SpaClientUrl, SpaLaunchCommand).
// This file gets not published when using "dotnet publish".
Expand All @@ -21,17 +21,13 @@
app.UseStaticFiles();
app.UseRouting();

app.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");

// The middleware and route endpoint get only added if the 'spa.proxy.json' file exists and the SpaYarp services were added.
app.UseSpaYarpMiddleware();
app.MapSpaYarp("one", "https://localhost:44478");
app.MapSpaYarp("two", "https://localhost:44479");
app.MapRazorPages();

//Route endpoints get only added if the 'spa.proxy.json' file exists and the SpaYarp services were added.
app.MapSpaYarpForwarder("one", "https://localhost:44478");
app.MapSpaYarpForwarder("two", "https://localhost:44479");

// If the SPA proxy is used, this will never be reached.
app.MapFallbackToFile("index.html");

app.Run();
app.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<ImplicitUsings>enable</ImplicitUsings>
<!-- SpaYarp configuration -->
<SpaRootOne>ClientAppOne\</SpaRootOne>
<SpaRootTwo>ClientAppTwo\</SpaRootTwo>
<SpaClientUrl></SpaClientUrl>
<!-- SpaLaunchCommand specified here once, since it is the same for both apps. Otherwise it could've been specified in 'DevServerOptionsOne' and 'DevServerOptionsTwo' classes in Program.cs -->
<SpaLaunchCommand>npm start</SpaLaunchCommand>
</PropertyGroup>

<ItemGroup>
<!-- Don't publish the SPA source files, but do show them in the project files list -->
<Content Remove="$(SpaRootOne)**" />
<None Remove="$(SpaRootOne)**" />
<None Include="$(SpaRootOne)**" Exclude="$(SpaRootOne)node_modules\**" />
</ItemGroup>
<ItemGroup>
<!-- Don't publish the SPA source files, but do show them in the project files list -->
<Content Remove="$(SpaRootTwo)**" />
<None Remove="$(SpaRootTwo)**" />
<None Include="$(SpaRootTwo)**" Exclude="$(SpaRootTwo)node_modules\**" />
</ItemGroup>

<!--<ItemGroup>
<PackageReference Include="AspNetCore.SpaYarp" Version="1.1.0" />
</ItemGroup>-->

<ItemGroup>
<ProjectReference Include="..\..\src\AspNetCore.SpaYarp\AspNetCore.SpaYarp.csproj" />
</ItemGroup>

<!-- Import target file manually. This is not needed if 'AspNetCore.SpaYarp' gets added via NuGet. -->
<Import Project="..\..\src\AspNetCore.SpaYarp\build\AspNetCore.SpaYarp.targets" />

<Target Name="DebugEnsureNodeEnvOne" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRootOne)node_modules') ">
<!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
<Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
<Exec WorkingDirectory="$(SpaRootOne)" Command="npm install" />
</Target>

<Target Name="DebugEnsureNodeEnvTwo" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRootTwo)node_modules') ">
<!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
<Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
<Exec WorkingDirectory="$(SpaRootTwo)" Command="npm install" />
</Target>

<Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
<!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
<Exec WorkingDirectory="$(SpaRootOne)" Command="npm install" />
<Exec WorkingDirectory="$(SpaRootOne)" Command="npm run build -- --prod" />
<Exec WorkingDirectory="$(SpaRootTwo)" Command="npm install" />
<Exec WorkingDirectory="$(SpaRootTwo)" Command="npm run build -- --prod" />

<!-- Include the newly-built files in the publish output -->
<ItemGroup>
<DistFiles Include="$(SpaRootOne)dist\**; $(SpaRootOne)dist-server\**; $(SpaRootTwo)dist-server\**; $(SpaRootTwo)dist-server\**" />
<ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
<RelativePath>wwwroot\%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</ResolvedFileToPublish>
</ItemGroup>
</Target>

</Project>
17 changes: 17 additions & 0 deletions samples/AspNetMultipleSpaYarpAuto/ClientAppOne/.browserslistrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries

# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support

# You can see what browsers were selected by your queries by running:
# npx browserslist

last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
19 changes: 19 additions & 0 deletions samples/AspNetMultipleSpaYarpAuto/ClientAppOne/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Editor configuration, see http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.ts]
quote_type = single

[*.md]
max_line_length = off
trim_trailing_whitespace = false

[*.{razor,cshtml}]
charset = utf-8-bom
40 changes: 40 additions & 0 deletions samples/AspNetMultipleSpaYarpAuto/ClientAppOne/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.

# compiled output
/dist
/dist-server
/tmp
/out-tsc

# dependencies
/node_modules

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings

# System Files
.DS_Store
Thumbs.db
15 changes: 15 additions & 0 deletions samples/AspNetMultipleSpaYarpAuto/ClientAppOne/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-msedge",
"request": "launch",
"name": "Launch Edge against localhost",
"url": "https://localhost:7113",
"webRoot": "${workspaceFolder}"
}
]
}
27 changes: 27 additions & 0 deletions samples/AspNetMultipleSpaYarpAuto/ClientAppOne/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# AspNetAngularSpaYarp

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2.

## Development server

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.

## Code scaffolding

Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.

## Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.

## Running unit tests

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
Loading