Configure React Dev Server within an ASP.NET Core Application - reactjs

I have an existing ASP.NET Core application (that uses razor pages) and I am trying to convert it, one component at a time, to React until I can completely make it a SPA. The idea is to create an entry point for each of my razor pages until I can combine them all into one SPA. I have most of this working except for the use of webpack-dev-server to serve my bundles. The problem I am having is the ASP.NET app runs on port 44321 and the dev server runs on port 8080 so the script tags in my .cshtml files cannot see the bundles that are being hosted from webpack.
I can temporarily change them from:
<script src="./dist/[name].bundle.js"></script>
To something like:
<script src="http://localhost:8080/[name].bundle.js"></script>
To get around this, but this is not long term solution.
I have created a sample application to showcase what I am trying to accomplish here: https://github.com/jkruse24/AspNetReact.
Is there any way to either get my ASP.Net application to listen on the port that webpack-dev-server is serving to (without changing my script tags) or to have my webpack-dev-server serve to the port that my ASP.Net app is running on?
I have tried to use the .NET CORE SPA middleware (Microsoft.AspNetCore.SpaProxy) but either I have not configured it correctly or I am misunderstanding what it is used for. Upon adding in the below code (which is commented out in my github sample) my application still looks at the .\dist directory for my bundles (which are still there from running actual builds).
if (env.IsDevelopment())
{
app.UseSpa(spa =>
{
spa.Options.SourcePath = "./ClientApp";
spa.UseReactDevelopmentServer(npmScript: "start");
spa.UseProxyToSpaDevelopmentServer("http://localhost:8080");
});
}

I ended up getting this working using the .NET Core SPA Middleware. When I originally tried to used the middleware, it was working fine, but I didn't have my webpack dev server configured to serve my bundles to the correct location.
As you can see above, I was serving them to
http://localhost:8080/[name].bundle.js
when they needed to be served to
http://localhost:8080/dist/[name].bundle.js
My problem was that my webpack publicPath was not set correctly. I made an update commit on my repository here. More specifically, this was the file diff that solved my problem.

Related

React App doesn't make proxy calls after deployed to azure

Simple setup:
React App created with create-react-app
ASP.NET Core web API - a couple of controllers (currently no security until I make it work)
Both the API and Application are deployed to Azure.
When I run the app locally with configured proxy (I contact the deployed API on Azure) it works correctly makes the calls.
If I try the API directly from my machine it works too (PostMan for example)
When I open the deployed React APP - The application loads correctly but the call to the API doesn't get proxy(ed). What I mean it's not returning 404, 403 - it returns status 200, but makes the call to the app itself instead of proxy the request to the API.
I've tried both using "proxy" configuration in package.json as well as using "http-proxy-middleware". Both cases work with locally running app, but not deployed. Here is the configuration of the proxy:
module.exports = function (app) {
app.use(
'/api',
createProxyMiddleware({
target: 'https://XXXXXX.azurewebsites.net',
changeOrigin: true,
})
);
};
I suppose it's something related to the configuration of the node server used when I deploy to azure, but I don't have a clue what.
I've used the following tutorial for deployment: https://websitebeaver.com/deploy-create-react-app-to-azure-app-services
But as seen from content there is no proxy part in it.
After long troubleshooting I realize the issue was due to wrong understanding of the proxy configuration.
So I was not realizing the proxy configuration is respected only in debug mode and totally ignored into prod build. And of course while debugging the issue I was not realizing the Azure Deployment pipe was doing production build. So the resolution was to detect the production/dev on application layer and inject correct URL.
Here I hit another issue - process.env.NODE_ENV, which I was using to distinguish between development and production was undefined into my index.tsx - it was available in App.tsx and all its children, but not in index.tsx where my dependency container was initialized.
What resolved my issue is package called dotenv. Then I've just imported it into index.tsx and the process.env was available.
import * as dotenv from 'dotenv';

How to deploy Next.js app without Node.js server?

I was hoping to deploy a Next.js app with Laravel API. I had developed React apps with CRA and in those I used the API server to serve the index.html of the CRA as the entry point of the app.
But in Next.js, after development I get to know that it needs a Node.js server to serve (which is my bad, didn't notice that). There is an option next export that builds a static representation of the Next.js app and it has an index.html. I am serving the index.html as the entry of the app by my Laravel API. It is serving the page, but just some of the static contents.
What I was hoping to know is it possible to host the aPI and the Next app from a single PHP shared hosting without any node server? If so, how? If not so, what could be the alternatives?
Actually the acepted answer is completly wrong, when you do yarn build and in your package.json is set like "build": "next build && next export", you will get an out folder which all the items in there are used to build without node.js server
Now since you are using laravel, and you use the out folder you will only load half of the page because the routes are not set properly. for that to work you need to edit your next.config.js edit it to
module.exports = {
distDir: '/resources/views',
assetPrefix: '/resources/views',
}
These will set the root directory to the root one in Laravel. now this will work for SPA (single page application) only for the dynamic routes you need to match with a view file for each one that you have in your out folder
For each route that you have you need to create a new "get" route in laravel
Route::get('/', function () {
return require resource_path('views/index.html');
});
Route::get('/contacts', function () {
return require resource_path('views/contacts.html');
});
Route::get('/post/{slug}', function () {
return require resource_path('views/post/[slug].html');
});
Notice that you can pass a wildcard for dynamic routes and they are all gonna work. once you do that and you deploy route out folder inside /resources/views in Laravel it's going to work
Apparently there is no alternative to nodejs server, which is not an option for me currently, so I unfortunately had to abandon next.js and create a CRA app and used as much from the next.js as I could.

Build React app with express backend for domain http://example.com

I have a web application in React that I needed to implement a contact form. The application is created using create-react-app and the server folder added. For the form I used sendgrid mail. Does the server work on port 4567, how do the app build to work on the domain? It is a one-page application.
Thx, it is important.
When running in production, a React app is simple HTML, CSS, and JavaScript. These files are sent from your server to a client when requested in the same way that requests/responses are handled for any web page. There are a few steps that need to be done before your React app is ready for production
1: Create a Production Build
First you need to create a production build of your app. This process takes all of your separate .js or .jsx files and puts them together into a single minified file, and the same for .css. Then your index.html is updated to include a link to the CSS and script to the JS. This is done so that only three files will need to be sent rather than the 10s or 100s that exist in development.
If you used create-react-app to start your application, you can use the command:
npm run build
to do this. Otherwise, you need to have webpack installed, and then run:
node_modules/.bin/webpack --config webpack.prod.js --mode production
(which you might want to add as a script to package.json).
See React: Optimizing Performance for more.
2. Serve your Application
Now your server should have a route for your application and when it receives a request on that route, the server should respond by sending index.html from your client/build/ directory (where client/ is the directory of the React app).
Here is an example with Node/Express as the server (in app.js):
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname), 'client', 'build', 'index.html');
});
Note that this is just the way to send a static file using Node and can easily be done with any server.
Additional
You mentioned you want to submit forms with your application. If your routes for receiving POST requests match the routes that the forms are on (e.g. form is on /form and server listens for POST on /form) you can just use the default HTML form submission. However this is not a great way to do things when using React because then routing will be controlled by your server rather than by React. Instead you should use some sort of AJAX method to submit the form.
Since your server is now serving your React app (rather than React serving itself as in development), you can just make relative requests and those requests will be made to your server. For example the request (using the fetch API):
const models = await fetch('/api/models');
Will be made to your_host/api/models by default.
in the package.json add
"proxy": "http://localhost:4567"

react + webpack - pass POST data to build

Coming from a PHP background, I used to have an index.php which does two things:
serve the webpage if no parameters were set;
or serve JSON data when a specific POST parameter was included in the request.
Something like this:
// -- index.php
<?php
if ($_POST["some_parameter"]) {
...
echo json_encode(someArrayData);
exit(0);
}
?>
<html>
...
</html>
I have built the complete frontend application with npm, webpack, webpack-dev-server, and react. Having completed the first part, how can I effectively serve JSON data instead of HTML when a request includes a specific POST parameter?
I can see 2 ways of doing this:
Build the frontend as usual and everytime I build the bundle, modify index.html, inject my PHP code in it, and rename it to index.php. I then would have to run this folder via apache or nginx, so I'd be able to run the index.php script. This method is downright ugly and is probably the worst way to do it.
Run a separate PHP server which just serves data or redirects to the static webpack-generated build. All requests should then start from this server, and this server determines whether to serve data or redirect to the frontend. The problem comes to neatly passing the POST data received from the request to the static react app. As far as I know, the only way to do this would be to include a URL (GET) parameter to the redirect and manually parse it with javascript on the frontend. This is a dirty solution, in my opinion.
So, to summarize:
I need an efficient way to get POST data in a react/webpack/webpack-dev-server environment.
It should work with my hot-module-replacement dev setup.
I'm fine with switching to a node-based backend like express.
There shouldn't be any ajax involved in the static react app.
Any ideas? There has to be a way to do this properly.
UPDATE: I solved this by simply copying an index.php from my source directory to my build directory via the webpack config. I serve the build folder to a PHP server and keep a webpack --watch building my source.
I lose built-in features like auto-reload and css injection, but it's worth the convenience of not having to implement SSR for a very simple task (getting a single POST variable).
For anyone interested, I also added 2 npm scripts:
npm run start runs my original webpack-dev-server with hot-reload, serving static content including a static index.html file
npm run static runs the webpack --watch which copies the index.php file to the build directory
This lets me have hot-reloading when developing frontend, and allows POST data fetching when programming logic.
It's easy, convenient, and works on most web hosting providers.

HTML5Mode, AngularJS and Grunt Build Control

Hoping someone can answer this because I'm struggling...
I have an angular js app that was build with the yo-angular generator. All works fine with deploying through grunt build control, as long as I'm not using the #-free "html5mode."
However, once I enable html5mode to remove the # from my routing and then deploy, my app on github pages doesn't point to the correct source for its scripts and such... For instance, I'm getting a 404 error because it's looking for http://{{user name}}.github.io/scripts/{{name of file}}, instead of http://{{user name}}.github.io/{{app name}}/scripts/{{name of file}}
How can I get it to point to the correct directory?
Hope this makes sense. I'll share more if needed!
You also need to configure the server. The configuration change will depend on what technology you are using to host the app on the server. How to configure your server to work with html5mode

Resources