Всем привет! Пару месяцев назад у нас возникла задача запилить лендос для нашего онлайн сервиса. Наш стек - Create React App + .Net Core. Погугля немного, мы решили, что хотим запилить лендос на Next JS, но возник вопрос - как это все вместе подружить.
Мы хотели, что бы приложение открывалось по ссылке: yourdomain.com/app, а все остальные ссылки вели бы на лендос.
Для начала в папке, где у Вас лежит ClientApp нужно создать папку LandingApp куда вы добавите второй проект. (Если что, папки можно назвать, как угодно)
После того, как Вы добавите второй проект нужно немного обновить startup.cs, чтобы .Net Core мог "переключать трафик" с одного проекта на другой.
Отключаем endpoint routing в методе ConfigureServices
services.AddMvc(options =>
{
options.EnableEndpointRouting = false;
});
В метод Configure добавляем статичные файлы для CRA
app.UseSpaStaticFiles(new StaticFileOptions() {
RequestPath = "/app"
});
Добавляем маппер, который при переходе по ссылке /app будет открывать наше приложение
app.MapWhen(context => context.Request.Path.Value.StartsWith("/app"), builder =>
{
builder.UseMvc(routes =>
{
routes.MapSpaFallbackRoute(
"app",
new { controller = "", action = "app" }
);
});
builder.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
});
После по дефолту открываем наше Next JS приложение
app.UseSpa(spa =>
{
spa.Options.SourcePath = "LandingApp";
// Для простоты билда, мы забилдили лендос отдельно
// И там скрывается ссылка по типу
// https://yourapp.azurewebsites.net
var url = Configuration.GetSection("urls")["landingUrl"];
if (env.IsDevelopment())
{
url = "http://localhost:3005";
}
spa.UseProxyToSpaDevelopmentServer(url);
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "dev");
}
});
Весь метод Configure
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
_env = env;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
await next();
});
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles(new StaticFileOptions() {
RequestPath = "/app"
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.MapWhen(context => context.Request.Path.Value.StartsWith("/app"), builder =>
{
builder.UseMvc(routes =>
{
routes.MapSpaFallbackRoute(
"app",
new { controller = "", action = "app" }
);
});
builder.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "LandingApp";
var url = Configuration.GetSection("urls")["landingUrl"];
if (env.IsDevelopment())
{
url = "http://localhost:3005";
}
spa.UseProxyToSpaDevelopmentServer(url);
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "dev");
}
});
}
Далее, нам нужно сказать CRA откуда брать бандл т.к. теперь он находится не в корне, а в /app. Для этого, мы в package.json указываем свойство homepage: "/app/"
Если вы используете библиотеку history то нужно указать еще basename: '/app'
import { connectRouter } from 'connected-react-router';
import { createBrowserHistory } from 'history';
export const history = createBrowserHistory({
basename: '/app',
});
export const routerReducer = connectRouter(history);
И на этом вроде все
Мы хотели, что бы приложение открывалось по ссылке: yourdomain.com/app, а все остальные ссылки вели бы на лендос.
Для начала в папке, где у Вас лежит ClientApp нужно создать папку LandingApp куда вы добавите второй проект. (Если что, папки можно назвать, как угодно)
После того, как Вы добавите второй проект нужно немного обновить startup.cs, чтобы .Net Core мог "переключать трафик" с одного проекта на другой.
Отключаем endpoint routing в методе ConfigureServices
services.AddMvc(options =>
{
options.EnableEndpointRouting = false;
});
В метод Configure добавляем статичные файлы для CRA
app.UseSpaStaticFiles(new StaticFileOptions() {
RequestPath = "/app"
});
Добавляем маппер, который при переходе по ссылке /app будет открывать наше приложение
app.MapWhen(context => context.Request.Path.Value.StartsWith("/app"), builder =>
{
builder.UseMvc(routes =>
{
routes.MapSpaFallbackRoute(
"app",
new { controller = "", action = "app" }
);
});
builder.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
});
После по дефолту открываем наше Next JS приложение
app.UseSpa(spa =>
{
spa.Options.SourcePath = "LandingApp";
// Для простоты билда, мы забилдили лендос отдельно
// И там скрывается ссылка по типу
// https://yourapp.azurewebsites.net
var url = Configuration.GetSection("urls")["landingUrl"];
if (env.IsDevelopment())
{
url = "http://localhost:3005";
}
spa.UseProxyToSpaDevelopmentServer(url);
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "dev");
}
});
Весь метод Configure
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
_env = env;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
await next();
});
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles(new StaticFileOptions() {
RequestPath = "/app"
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.MapWhen(context => context.Request.Path.Value.StartsWith("/app"), builder =>
{
builder.UseMvc(routes =>
{
routes.MapSpaFallbackRoute(
"app",
new { controller = "", action = "app" }
);
});
builder.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "LandingApp";
var url = Configuration.GetSection("urls")["landingUrl"];
if (env.IsDevelopment())
{
url = "http://localhost:3005";
}
spa.UseProxyToSpaDevelopmentServer(url);
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "dev");
}
});
}
Далее, нам нужно сказать CRA откуда брать бандл т.к. теперь он находится не в корне, а в /app. Для этого, мы в package.json указываем свойство homepage: "/app/"
Если вы используете библиотеку history то нужно указать еще basename: '/app'
import { connectRouter } from 'connected-react-router';
import { createBrowserHistory } from 'history';
export const history = createBrowserHistory({
basename: '/app',
});
export const routerReducer = connectRouter(history);
И на этом вроде все
Как объединить несколько JS приложений с .NET Core (Create React APP + Next JS + .NET Core)
Всем привет! Пару месяцев назад у нас возникла задача запилить лендос для нашего онлайн сервиса. Наш стек - Create React App + .Net Core. Погугля немного, мы решили, что хотим запилить лендос на Next...
habr.com