📜 ⬆️ ⬇️

ASP.NET Core 2 Boilerplate with React, Redux and Buns


Finally, that moment came when I could introduce you to the React Core Boilerplate ( GitHub , Visual Studio Marketplace ), or, in other words, a ready-made project template on ASP.NET Core.


Interesting? Welcome under cat.


The main elements of the template:



Own developments written in TypeScript and forks that I fixed:



Objective of the project


The purpose of this project is to support the developers of this stack: to give the opportunity to immediately begin to develop projects, not bothering with the solution of problems of compatibility of technologies in the stack, their configuration. Since the project was created “for people” and contains, in my opinion, an intuitive architecture, it will also be useful for beginners in teaching React, because does not contain problems out of the box for building applications.


Details


How it all began


I am a full-stack developer. Once I loved writing frontend on jQuery - from plugin development to complex sites. However, one day it became clear: the more difficult the project is, the more difficult it is to support sites on this library. Then I decided to study other tools for the development of the frontend. I didn’t like Angular because of my thick abstraction, and after studying the advantages and disadvantages of each framework and library, I made a choice in favor of React, which attracted the fact that HTML and TypeScript can be written in one place (.tsx file) without switching between HTML and script files.


Over time, I loved React. But, to be honest, at first I had to use jQuery in React because of the plug-ins that require it. And then, when I tried to master server rendering due to the well-known problems of SPA and SEO, I learned that jQuery either cannot be friends with it, or it will be a crutch (via jsdom, because a window object is required). I knew that these jQuery plug-ins would be missed. And since then, I started developing plugins for "Vanilla JS" that are somewhat similar in API to plugins running on jQuery.


Server rendering


A few months ago, Microsoft released an update for Visual Studio 2017, which included an ASP.NET Core 2 + TypeScript + React + Redux + Webpack project template with a server prerender using NodeServices. Studying the template, I spent a lot of time to connect SASS via WebPack and update the last one, because studying the documentation, forums and StackOverflow, I did not find the answers I needed to configure this stack, while the documentation was mainly stack with angular. After some time, Microsoft replaced this template with create-react-app without TypeScript and server rendering. Judging by the comments on the Internet, it embarrassed many others, like me. However, I still have that template, and I decided to make my own with blackjack and buns, having dealt with it and solved all the problems at once.


PS: Recently I read that there are so-called opponents of an isomorphic approach to developing applications. What about SEO? Or do you offer to render all paid third-party services? As far as I know, Google can not always index a fat client without a pre-tender. Anyway.


Technical part


React, React Router, Redux



Webpack and modules



NodeServices


NodeServices documentation was not enough to solve some problems: either the HMR fell off, then something did not work. However, having shown patience, after a month and a half, I finally managed to resolve critical moments:


⬝ Instead of the "asp-prerender-module" attribute for the DIV element in View Razor, I had to inject ISpaPrerender into it:


@inject Microsoft.AspNetCore.SpaServices.Prerendering.ISpaPrerenderer prerenderer 

and, manually execute the script:


 var prerenderResult = await prerenderer.RenderToString(%     %, customDataParameter: data); 

Then, from the prerenderResult object, you can drag the rendered HTML React'a and React Helmet into BODY / DIV and HEAD blocks, respectively.


⬝ The domain-task NPM package did not allow using async / await and tools for fetch requests except isomorfic-fetch and fetch from the same npm package. This is fixed by me in the domain-wait package. Now fetch requests are more pleasant to write, especially using axios.


Application architecture


From personal experience, I made some achievements, for example, in all methods of services (except for authorization), to accept a ServiceUser and return a Result object with result or errors. Both such objects + an imitation of the authorization service are already incorporated in the boilerplate. I am an opponent of Identity, and authorization is not suitable for everyone. So, nothing superfluous, and the imitation of authorization is easy to cut out (AccountService, Middleware, ControllerBase).



File structure
 | .gitignore | AppSettings.cs | appsettings.Development.json | appsettings.json | Constants.cs # ,       . | package.json #  NPM. | Program.cs #   . | ReactSSR.WebApp.csproj #   Visual Studio 2017. | README.md | Startup.cs #     middleware  . | tsconfig.json #   TypeScript. | webpack.config.js #   WebPack      . | webpack.config.vendor.js #   WebPack     Vendor-. | +---ClientApp | | boot-client.tsx #       . | | boot-server.tsx #        . | | configureStore.ts #   Redux. | | global.d.ts #      TypeScript   (, ts-nameof, \*.png,  ..) | | Globals.ts #     (,   ). | | routes.tsx #    . | | Ui.ts #    UI (,  ). | | utils.ts #   . | | | +---components #  ( ). | | +---person | | | PersonEditor.tsx # ,    . | | | | | \---shared #  . | | AppRoute.tsx #      ,   . | | ErrorBoundary.tsx # ,    "error boundary".    ,      . | | Footer.tsx #    . | | Loader.tsx # ,   . | | PagingBar.tsx #  . | | TopMenu.tsx #     . | | | +---images | | logo.png #  . | | | +---layouts #  (). | | AuthorizedLayout.tsx | | GuestLayout.tsx | | | +---models #  TypeScript,   . | | ILoginModel.ts | | IPersonModel.ts | | IServiceUser.ts | | ISessionData.ts | | Result.ts #   "Result". | | | +---pages #  . | | ExamplePage.tsx | | HomePage.tsx | | LoginPage.tsx | | | +---services #  JS-,      . | | AccountService.ts # JS-  . | | PersonService.ts # JS- - . | | ServiceBase.ts #   TS-    JS-. | | | +---store #  Redux. | | index.ts #    Redux. | | LoginStore.ts | | PersonStore.ts #   . | | | \---styles | authorizedLayout.scss #    . | guestLayout.scss #    . | loader.scss #    . | main.scss #  . | preloader.css #     . | +---Controllers | AccountController.cs #   . | ControllerBase.cs #       . | MainController.cs #   . | PersonController.cs # -.. | +---Extensions | ServiceCollectionExtensions.cs #  ,   Lazy DI . | +---Infrastructure # ,     . | Result.cs #   "Result"   . | ServiceBase.cs #     ,   Facade/. | +---Models | LoginModel.cs #    . | PersonModel.cs #   . | ServiceUser.cs | SessionData.cs #    . | +---Services #  ,   "Facade". | AccountService.cs #   . | PersonService.cs # -. | +---Views | | \_ViewImports.cshtml | | \_ViewStart.cshtml | | | +---Main | | Index.cshtml #   ,   ,    . | | | \---Shared | Error.cshtml | \---wwwroot #  ,     . favicon.ico 

That's all. Thank you all for your attention and, of course, Happy Coding!


')

Source: https://habr.com/ru/post/426147/


All Articles