Как объединить несколько JS приложений с .NET Core (Create React APP + Next JS + .NET Core)

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Всем привет! Пару месяцев назад у нас возникла задача запилить лендос для нашего онлайн сервиса. Наш стек - 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);

И на этом вроде все :)

Источник: https://habr.com/ru/post/583830/


Интересные статьи

Интересные статьи

Предполагалось, что React облегчит разработку, но он создал препятствия. Летом 2018 года, мой босс, Эдриан, попросил меня присоединиться к его звонку по Skype с Джеймсом, техническим дир...
На работе я занимаюсь поддержкой пользователей и обслуживанием коробочной версии CRM Битрикс24, в том числе и написанием бизнес-процессов. Нужно отметить, что на самом деле я не «чист...
Сегодня трудно кого-то удивить возможностью свайпать элементы списка в мобильных приложениях. В одном нашем react-native приложении тоже была такая функциональность, но недавно возникла необходим...
Здравствуйте, сегодня постараюсь рассказать о том, как можно отправить запрос и прочитать ответ от HTTP сервера, используя URLConnection из библиотеки JRE. Сейчас изучаем Java в онлайн режи...
Наш семинар уверенно набирает слушателей и постепенно перерастает офис компании EPAM в Петербурге: мы планируем набрать до 250 разработчиков под одной крышей как в Петербурге, так и в Москве. А в...