Как создать React SPA в старой школе ASP.NET без React.NET с правильным объединением и загрузкой фрагментов
Если вам когда-либо приходилось использовать ASP.NET с современным стеком внешнего интерфейса, вы заметите, что на самом деле невозможно найти какую-либо полезную информацию об этом. Если вы сможете найти что-нибудь для ASP.NET MVC (не ядро), все это будет для React.Net, который страдает от проблем с документацией или старой версии angular. Основная проблема, конечно, заключается в именовании между ASP.NET и ASP.NET Core и невозможности найти что-либо для ASP.NET Classic.
Плохие идеи
Заставлять webpack выводить один гигантский файл bundle.js — ужасная идея. Lighthouse будет ругать вас за большое время начальной загрузки, и по мере роста вашего проекта вам придется включать каждую страницу как часть исходного пакета, который не масштабируется.
Хорошие идеи
Вручную разделить ваш проект на несколько точек входа для каждой страницы, а затем включить его в файл .cshtml
. Это утомительно и все же не лучший способ сделать что-то. Вы можете столкнуться с большим начальным временем загрузки
Лучшая идея
Настройте HtmlWebPackPlugin
для вывода .cshtml
файла, который можно включить в основное представление индекса. Это автоматически сгенерирует частичный файл .cshtml
со всеми автоматически сгенерированными кусками javascript и правильно отложенными тегами script, которые будут загружаться при необходимости. Наряду с React Lazy Loading вы можете получить небольшое время начальной загрузки и загрузку фрагментов по требованию.
В том же месте, что и ваш webpack.config.js, создайте файл с именем template (без расширения. Вам нужно будет извлечь приложение create-react-app)
Содержимое файла должно быть
<%= htmlWebpackPlugin.tags.headTags %>
В webpack.config.js
сделайте так, чтобы ваш HtmlWebPackPlugin
в разделе плагинов выглядел следующим образом
return new HtmlWebPackPlugin({ template: 'template', inject: false, minify: false, filename: `${fileName.replace(path.extname(fileName), '')}.cshtml`, });
Inject false останавливает плагин от автоматического создания полной html-страницы и вместо этого создает только элемент script со всеми включенными частями Javascript.
template указывает на файл шаблона, который вы создали для создания тегов сценария .cshmtl
minify: false остановит плагин, пытающийся неправильно минимизировать файл, что сломает все.
тег имени файла просто использует существующее имя файла html и добавляет .cshtml. Это создаст файл с именем index.cshtml
(при условии, что ваша точка входа index.html
). У меня также есть два плагина для веб-пакетов, один из которых выводит .cshtml
, а другой выводит традиционный html, когда я хочу разрабатывать с использованием сервера разработки веб-пакетов.
Когда вы создаете свой .cshtml вывод, он должен выглядеть примерно так:
<script defer src="/wwwroot/build/590.478c.js"></script><script defer src="/wwwroot/build/index.478c.js"></script><link href="/wwwroot/build/index.bundle.css" rel="stylesheet">
Теперь перейдите к вашему проекту ASP.NET. Вероятно, у вас есть какой-то контроллер под названием Home Controller, который должен загружать главную страницу вашего проекта asp.net. Перейдите к соответствующему представлению для этого контроллера. В представлении (вероятно, также называемом index.cshtml) просто включите вызов RenderPage в ваш построенный проект реагирования вместе с div, называемым корневым элементом.
@{ /**/ ViewBag.Title = "Home Page"; } <div id="root"></div> @{ @RenderPage("~/wwwroot/build/index.cshtml") }
В общем представлении мой выглядит просто так
<!DOCTYPE html> <html> <head lang="en" translate="no"> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title</title> </head> <body> @RenderBody() </body> </html>
Маршрутизация на стороне клиента
Если вы используете маршрутизацию на стороне клиента, вы заметите, что если вы сойдете с основного маршрута и обновите ASP.NET, он не будет знать, что загружать.
Просто создайте универсальный маршрут в своем RouteConfig.cs
Это выглядит как
routes.MapRoute( name: "Everything", url: "{*url}", defaults: new { controller = "Home", action = "Index" }); }
Теперь вся ваша маршрутизация может быть выполнена на стороне клиента, к лучшему или к худшему, и при перезагрузке она приведет вас к тому же месту.
Оттуда я сохраняю свой HomeController
только с одной функцией для загрузки главной страницы. Затем оттуда я помещаю все маршруты API для внешнего интерфейса в ApiController со всем в `/api/‹action›`.
Это своего рода мои наспех написанные мысли о том, как это сделать, если у вас есть какие-либо вопросы, не стесняйтесь, напишите мне по адресу [email protected]