Как стать автором
Обновить

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

Время на прочтение3 мин
Количество просмотров5.4K

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

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

Теги:
Хабы:
Всего голосов 6: ↑3 и ↓30
Комментарии8

Публикации

Истории

Работа

Ближайшие события