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

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';

Related

Configure React Dev Server within an ASP.NET Core Application

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.

locally host firebase backend with react frontend together, for debugging

I am building a react website with firebase functions backend.
I'm using firebase serve to locally host the node.js backend that I connect to my react code through express API endpoints, and I am using react-scripts start to test my react frontend app.
all my get requests in my react app use /some endpoint to communicate with my firebase localserver. But they are running on different ports. firebase serves it on localhost:5000 while react live server hosts it at localhost:3000.
I tried many things and couldn't get any useful way to make this work. I at last added my react project as a subfolder in my firebase project and made the hosting public path at firebase.json to my react build directory. It works now but I always have to run npm run build on my react app on every change, to make it compile my app into the build directory, which is painfully slow.
What is the proper way to do this? debug react app and firebase backend together.
I finally enabled cross-origin-requests on my server using cors module
Serverside code
const cors = require("cors");
app.get("/test", (req, res) => {
return cors()(req, res, async () => {
res.send("working...");
});
});
Serverside code
And then adding a simple config file in the react side, to switch between debugging and deployed testing really helped.
config.js
var domain = "";
// domain = "http://localhost:5000";
export {domain}
then whenever I use apis in react, I simply comment/uncomment the second line to switch between local and deployed testing.
Then whenever I use APIs, I append `domain` before every url in all references, eg fetch requests
import { domain } from "config.js";
fetch(domain + "/int-search", ...
Then it worked fine running both the firebase backend and the react application on localhost, using firebase serve and npm start for my react app.

Base URL Discrepancy Between Localhost and Deployed - create-react-app

I am building a web application from the ASP.Net Core React template, whose "ClientApp" React portion appears to be a 'create-react-app' project. When I deploy the app to IIS, it gets hosted in a subfolder from the root, i.e. http://myserver.com/SubApp. Because of this, I have changed the "homepage" value in package.json to http://myserver.com/SubApp.
What I am now experiencing is that when I am making fetch calls in my javascript code locally, if I use fetch('/myendpoint'), the the url requested locally is https://localhost:44315/myendpoint (which works), but when deployed, this url becomes http://myserver.com/myendpoint, which does not work.
Conversely, when I make the endpont fetch('myendpoint') (no leading slash), the server requests the correct URL http://myserver.com/SubApp/myendpoint but localhost fetches the incorrect URL, https://localhost:44315/SubApp/myendpoint.
I understand that the leading slash makes the request from the root, but the root appears to be different in localhost vs. on the server.
For local debugging purposes, I tried setting a proxy in package.json to https://localhost:44315 so that hopefully fetch('myendpoint') (no leading slash) would work in my local environment, but when I try this, chrome prompts me to sign in repeatedly without ever successfully making the request.
I feel like I am almost there, but I must be missing something. How can I configure my package.json (or other project configuration) to make the fetch commands succeed on both localhost and my server, without doing something hacky like checking the URL in the javascript code before every fetch?
What you need is Proxying API Requests in Development.
It easily allows you to call any endpoint in development and forward it to your backend or other location without CORS issues or your problem of mismatched endpoints.
You will have to use the manual configuration option, since the default proxy setup only helps with host/port forwarding.
Install http-proxy-middleware as a dev dependency:
$ npm -i http-proxy-middleware --save-dev
Following the guide linked above, you can use this configuration:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/SubApp/*',
createProxyMiddleware({
target: 'localhost://44315', // or anything else, point to your dev backend
pathRewrite: {
'^/SubApp': '/', // remove base path
},
})
);
};
You can then fetch with the /SubApp part in the request which will be removed in developement. You can use other configurations to achieve this, this is one example.
I had this same experience as well and found that setting the homepage value in the package.json is a dead end. What you want to do is make use of the PUBLIC_URL environment variable to set a full absolute url in your .env . There may be a way to use relative urls, but there were some edge cases that just made it cleaner to use an absolute URL.
When you set this environment variable you want to make use of it in the following places:
Your Routes (if you use react router)
The path should be prefixed by process.env.PUBLIC_URL
Your internal links should also be prefixed by the env var.

Deploying React + API apps on two different hosts

I'm trying to figure out what are the best practices to deploy a React app that consumes an API on a different host in production.
Currently in DEV I have the following:
frontend - React app running on webpack server: http://localhost:3000/
backend - API (django-rest) running on: http://localhost:7000/
Right now I define the API url in package.json proxy attribute: "proxy": "http://localhost:7000/", and I make API calls using Axios to api/something/something/ etc.
Both apps are standalone with separate repos and I'd like to keep it that way (I don't want to merge both apps into a single codebase.)
My question:
What is the best way to configure React in production to consume the production URL?
Use process.env.NODE_ENV to find out the current environment and assign the proper url to your base url constant.
In development, you will get process.env.NODE_ENV as "development" and in production, you will get process.env.NODE_ENV as "production".

Deploying Create React App to a subdirectory but make API calls to parent path

I'm deploying my Create React App to a specific path in a larger non-React webapp. For example, I will say the webapp path is www.example.com and the React app is deployed at www.example.com/react/
I have done this by setting the "homepage" property in package.json of the React app to "homepage": "/react", which does properly serve the static files from the /react/ path on my server.
However, when I make API calls from my react app, they go to /react/api/etc instead of /api/etc.
I can configure axios to use a hardcoded base path of www.example.com, but I deploy this to multiple environments with different URLs and need a solution that doesn't rely on a hardcoded value.
I could also write a workaround on the server side, but it would be less clean / mess with my logging and request statistics.
I would love a clean solution if one exists.
what if you used the window.location property in your axios config object:
{
baseURL: `${location.hostname}/api/` // or window.location.hostname
}

Resources