adding ssl to my react-app to my heroku server - reactjs

I am trying to add ssl to my heroku server using certbot.
However, the issue I am finding is that I need to create a url to verify my domain -- which is the issue as I cannot seem to add both my server code as well as my client side code to the same heroku server (and get them to both run at the same time which I need to verify the domain..)

Try this:
Begin a certbot manual certificate: sudo certbot certonly --manual
Follow the prompts until you get to the part that says to make a file available at a specific like like yourdomain.tld/.well-known/acme-challenge/longstring123 Do not press Enter to Continue! Take note of both the URL and the "file" data it gives you.
In your server.js, add something like the following:
app.get('/.well-known/acme-challenge/your-long-url-string', function(req, res) {
res.status(200);
res.send('your-long-verification-file-data');
});
Make sure that this Express route handler is above the one you use for React.

I had a similar problem and spent hours trying to figure this out today. My problem was I kept getting a 404 error when trying to access .well-known/acme-challenge/{verification_file}.
The problem wasn't React or Heroku, the problem was that I was using serve -s build (package serve-handler) to serve my app, this is an static server and it won't let you fetch files without an extension. There might be a way to configure it, but I don't know how. Maybe setting headers... Anyhow, I tried files with .txt and it works, but without an extension it redirects to 404.
So instead removed my static server and added ExpressJS to serve the app instead.
To accomplish this:
Step 1
In your project folder run:
npm i express path
Step 2
Create a file in your project folder called server.js and add this code to it. This code will initialize and serve your project.
const express = require("express");
const path = require("path");
const app = express();
app.use(express.static(path.join(__dirname, "build")));
app.get("/*", function (req, res) {
res.sendFile(path.join(__dirname, "build", "index.html"));
});
app.listen(process.env.PORT || 80);
Step 3
If your package.json file under scripts make sure Heroku will initialize your project correctly when deployed:
"scripts": {
...
"start": "node server.js",
...
}
This should do it. Now your project is served by a dynamic server and it will delivery files without an extension. You can remove your serve package now if you aren't going to use it anymore.
Reading
Couple links that might be useful:
https://create-react-app.dev/docs/deployment/
https://expressjs.com/en/starter/hello-world.html

Related

React CRA: When adding subdomain on localhost it says: The development server has disconnected

I am on a project with create-react-app without ejecting.
I wanted to have subdomains on localhost or a fake host for development.
When I added my host in windows hosts file it said invalid host header even if I add HOST=mydevhost.com DANGEROUSLY_DISABLE_HOST_CHECK=true in .env file.
I couldn't make it work without using third party apps so I used Fiddler and it worked as expected now the sites comes up but instantly says:
The development server has disconnected.
Refresh the page if necessary.
The problem is that the fast refresh doesn't work now and I have to refresh the site every time I make a change. Is there anything that I'm doing wrong here? Should I even use something like Fiddler here?
I ended up using react-app-rewired and in config-overrides.js I added the subdomain to allowed host. The final config looks like this:
module.exports = {
webpack: (config, env) => {
return config;
},
devServer: (configFunction) => (proxy, allowedHost) => {
const devServerConfig = configFunction(proxy, allowedHost);
devServerConfig.allowedHosts = ["subdomain.localhost"];
return devServerConfig;
},
};
I thing you can do that from your operating system to point your local domain to your react server, meaning that can create a local domain that points to the app server (host:port).
here's a guideline that may help:
https://www.interserver.net/tips/kb/local-domain-names-ubuntu/
Relevant answers:
How can I develop locally using a domain name instead of 'localhost:3000' in the url with create-react-app?

React routes with two parameters not working on react build

I'm using react router and everything works fine in development, but the production build of the react app is not working when I visit some routes with more than one parameter for example http://localhost:3000/me/edit.
I tried deploying in netlify with the _redirects file, also with nginx and also with serve. None of the three options worked.
It seems to be requesting a file inside the static folder. I will attach two images so you can see what I'm refering to.
This is what I can see under Sources tab:
When I visit http://localhost:3000/me it works fine and this is what I can see on chrome:
When I visit http://localhost:3000/me/edit if leads to a blank page, and it seems to be requesting a file inside me > static > edit which obviously does not exist; and this is what I can see on chrome:
So, I could finally solve this, the problem was that routes with more than one parameter either static or dynamic (eg: /me/edit or /user/:id) were looking for a file inside a folder, in this case me or user which do not exist.
Here's how I solved it:
I created a folder called 'production' inside this folder I ran npm init, I pasted the entire build folder generated by react. Then I created a file called server.js (which is the entry point I specified). This file contains the following:
const express = require('express')
const path = require('path');
const cors = require('cors')
// Initializing express
const app = express()
// Initializing middleware to indicate express where to serve the static files from:
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.use(cors())
const PORT = process.env.PORT || 4000
app.listen(PORT, () => console.log(`Server listening on port ${PORT} 🔥`))
In addition, I added this: <base href="/"> to my index.html file inside the build folder.
On the package.json I added the start script "start": "node server.js" and that's it, never was typing npm start so satisfactory 😂
The entire project now looks like this:

Create-React-App build - "Uncaught SyntaxError: Unexpected token <"

I realize this question has been asked multiple times but nothing has worked for me...
I'm trying to create a static build of a create-react-app project but I'm getting the following errors:
Uncaught SyntaxError: Unexpected token < 1.ca81c833.chunk.js:1
Uncaught SyntaxError: Unexpected token < main.7ced8661.chunk.js:1
Due to these files being minified, I'm not sure where to begin in debugging them.
Per other SO responses, here are some things I've tried:
//Original index.html file, which gets included in the built file:
<script type="text/babel" src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script>
//package.json
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
//.babelrc file
{
"presets": ["react", "es2015", "stage-1"]
}
Not sure if this is relevant, but I have this on my express server, which I believe is standard:
if (process.env.NODE_ENV === "production") {
app.use(express.static('client/built'));
app.get("*", (req, res) => {
res.sendFile(require('path')
.resolve(__dirname, 'client', 'build', 'index.html'));
})
}
Assuming it's actually a JSX issue, the whole thing is very confusing - shouldn't create-react-app be handling JSX automatically?
UPDATE: I just posted this question but already have a relevant update. I'm able to serve the page statically through pm2 by running pm2 serve build so I think the issue may be with my server configuration.
Thanks this helped me a lot.
Just wanting to add to this with an example from a Create-React-App project that had the same solution:
I received the same error after deploying to heroku.
Uncaught SyntaxError: Unexpected token < after serve -s build
For me the problem was in the packages.json file. The "homepage" parameter i gave was incorrect. Changing this to the correct heroku URL solved the issue.
"homepage": "https://myapp.herokuapp.com/"
Hope this addition is helpful.
I ended up finding an answer here: https://github.com/facebook/create-react-app/issues/1812
I trimmed down the full solution from above, but I changed:
app.use(express.static('client/build'));
app.get("*", (req, res) => {
res.sendFile(require('path')
.resolve(__dirname, 'client', 'build', 'index.html'));
})
to:
const root = require('path').join(__dirname, 'client', 'build')
app.use(express.static(root));
app.get("*", (req, res) => {
res.sendFile('index.html', { root });
})
It's definitely a bit strange to me that the first block didn't work. I assume it has something to do with the relative links in my React project since I do get an index.html file delivered to browser, despite getting the error. Maybe a completely static file would work with the first block, but I'd be interested to know if that's accurate.
just remove
"homepage": "your app url "
from package.json to fix it
Remove the "homepage": "app-url" from package.json. Absence of homepage in package.json will assume that it will be hosted at the server root, or you will serve the build with serve -s build.
And Yes, specifying homepage will be helpful when you are going to deploy the App in a sub-directory of the server root.
To host your app on the IIS with the name somedomain.net and your solution already has a Web API project.
You will map the solution folder with the main Web app i.e., somedomain.net
You will convert the Web API project to Application from IIS.
Then you will convert the build folder of React App to web App just like Web API
To make front-end App working specify the "homepage": "somedomain.net/React-Project/Client-App/build"
I created a build version of react app using "npm run build".
I have a server (node/express).
I wanted to include the build in server side and deploy to heroku. What i did is copied build folder to server root folder and used code in server side startup file:
app.get('/*', function (req, res, next) {
if (!req.path.includes('api'))
res.sendFile(path.join(__dirname, 'build', 'index.html'));
else next();
});
I was getting the same error. So i just set the path for static contents at starting:
var app = express();
//here below
app.use(express.static(path.join(__dirname, 'build')));
And my static index.html was served fine and was able to find resources css and js.
I had faced the same issue when deploying my react build to production. After spending hours trying to figure out what went wrong on a previously working code, I figured out a mistake I made in deployment.
I hadn't copied the folder static inside build to the server because I used scp build/* to copy the build folder in place of scp -r build/*.
I understand that this is not the exact answer to the question asked here. But I had tried out almost all possible options from answers given by experts here before I noticed the error I was making.
Hence, adding this here as a pointer to anyone facing similar issue to verify the deployment steps as well.
UPDATE:
Recently I need to deploy create-react-app project to subpath of client's domain which is http://example.com/foo/bar
This approach is using Nginx, React-Router.
Add PUBLIC_URL to .env file.
+ PUBLIC_URL=/foo/bar
Add basename to <BrowserRouter>.
- <BrowserRouter>
+ <BrowserRouter basename={process.env.PUBLIC_URL}>
Change your Nginx config.
location /foo/bar {
alias /path/to/build;
try_files $uri /$uri /foo/bar/index.html;
}
Here is a create-react-app document about how to build with .env:
Customizing Environment
Hope this solution helps!
Ran into the same issue when I want to deploy the static build of a create-react-app project to my linux server.
I solved with this issue comment on cra's github and the cra's official document about how to deploy production build.
For example:
I want to put the production build website under something like http://example.com/foo/bar.
When I deploy without changing any default settings, I will get this "Uncaught SyntaxError: Unexpected token <" error and nothing shows up on the screen.
Here is the solution:
Add homepage parameter to your package.json.
+ "homepage": "/foo/bar"
Add "/foo/bar" to all of your static resources in css which will be like:
.dummyimage {
- content: url('/dummyimage.jpg');
+ content: url('/foo/bar/dummyimage.jpg');
}
Add "/foo/bar" to all of your links and routes.
- linkTo: '/contact'
+ linkTo: '/foo/bar/contact'
Changing a little of your serve program's code, in node.js/express it will be like:
- app.use(express.static(path.join(__dirname, '/build')));
+ app.use('/foo/bar/', express.static(path.join(__dirname, '/build')));
Build again.
Deploy build/ to the server.
Restart your serve program, like node.js/express.
Problem solved!!
Hope this solution is helpful.
Just remove homepage key in package.json and also don't forgot to remove the basename in BrowserRouter, if you're using the react router.
That's it. It's working
i have faced kind of same issue when i want deploy my react app to github-pages :-
its need's follow few guidelines
Repository name should be in small latter
If project name same as repo name that usefull
addd {
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
} on package.json
add homepage script at the starting of the package.json
{
"homepage": "http://[Username].github.io/[reponame]",
"name": "--",
"version": "--",
"private": boolean,
}
As most of us have already suggested removing homepage property from package.json
Let me explain, why it worked in my case:
Earlier I had setup my project to be hosted on Github pages and as a result, it had homepage property set to something like "https://shubhamshd.github.io/supplyChainApp"
However as there are known navigational errors mainly related to BrowserRouter package on Github-pages, I had to switch to other hosting platforms.
And as I forgot to remove the homepage property, deployment did not work on any of the platforms like Vercel or Netlify.
It was after long hours of search and trial, that I finally stumbled upon this thread, specifically the #Shashwat Gupta and finally managed to resolve it by removing the unwanted homepage property.
If you are deploying your client to S3, when deploying with react-deploy-s3, assign the distribution-id from CloudFront
react-deploy-s3 deploy \
--access-key-id XXXXXXXXXXXXXXXXX \
--secret-access-key XXXXXXXXXXXXXXXXXXXXXXXX \
--bucket XXXXXXX \
--region us-east-1 \
--distribution-id XXXXXXXXXXXXX <---

Cannot GET index.html Azure Linux Web App

We created a Linux Web App in Microsoft Azure. The application is static written with React (html and Javascript).
We copied the code into the wwwroot folder, but the application only showing only hostingstart.html and when we try to get page index.html we have this error:
Cannot GET /index.html
We tried with a sample of Azure in GitHub (https://github.com/Azure-Samples/html-docs-hello-world) but the error is the same.
The url is this: https://consoleadmin.azurewebsites.net/index.html
Last week the application was running correctly.
We forget to do something?
MAY 2020 - You don't have to add any javascript files or config files anywhere. Let me explain.
I was facing this exact same issue and wasted 6 hours trying everything including the most popular answer to this question. While the accepted answer is a nice workaround (but requires more work than just adding the index.js file), there's something a simpler than that.
You see, when you just deploy an Azure Web App (or App Service as it is also called), two things happen:
The web app by default points to opt/startup/hostingstart.html
It also puts a hostingstart.html in home/site/wwwroot
When you deploy your code, it replaces hostingstart.html in home/site/wwwroot but the app is still pointing to opt/startup/hostingstart.html. If you want to verify this, try deleting opt/startup/hostingstart.html file and your web app will throw a "CANNOT GET/" error.
So how to change the default pointer? It's simpler than it looks:
Go to Configuration tab on your web app and add the following code to startup script:
pm2 serve /home/site/wwwroot --no-daemon
If this web app is a client-side single-page-app and you're having issues with routing, then add --spa to the above command as follows:
pm2 serve /home/site/wwwroot --no-daemon --spa
This will tell the web app to serve wwwroot folder. And that's it.
Image for reference:
Screenshot explaination
PS: If you only set the startup script without deploying your code, it will still show the hostingstart.html because by default that file lies in the wwwroot folder.
Ok you are gonna love this. This happened to me today also. Same exact thing.
I am pretty sure the azure team flipped a switch somewhere and we fell through a crack.
I found this obscure answer with no votes and it did the trick (with a little extra finagling)
BONUS! this also fixed my router issues I was having only on the deployed site (not local):
Credit: #stormwild: Default documents not serving on node web app hosted on Azure
From #stormwild's post see here:
https://blogs.msdn.microsoft.com/waws/2017/09/08/things-you-should-know-web-apps-and-linux/#NodeHome
Steps:
Go to your azure portal, select your app service and launch ssh
In ssh terminal, navigate via command line to /home/site/wwwroot
create index.js there with the following code:
var express = require('express');
var server = express();
var options = {
index: 'index.html'
};
server.use('/', express.static('/home/site/wwwroot', options));
server.listen(process.env.PORT);
NOTE: Be sure to run npm install --save express also in this folder else your app service will crash on startup
Be sure to restart your app service if it doesn't do so automagically
A workaround, I changed the webapp stack to PHP 7
Another solution would be to add a file called ecoysystem.config.js right next to your index.html file.
module.exports = {
apps: [
{
script: "npx serve -s"
}
]
};
This will tell pm2 to associate all requests to index.html as your app service starts up.
Very helpful information here: https://burkeholland.github.io/posts/static-site-azure/

Multi Tenant App in React

I'm building a multi tenant app in React (with Webpack setup via base, dev and prod config files), and I'm wondering the best way to create and access per-tenant variables.
When I run my app with:
npm run start tenant1
I am able to access tenant1 in Webpack by using this:
const tenant1 = process.argv[process.argv.length -1];
However, now I'm wondering what is the best way to make that variable globally accessible. My hope is to use that variable to the create a folder structure within the app along the lines of:
/app/${tenant}/img/
/app/${tenant}/css/
/app/${tenant}/components/
Ideally without having to import a variable into every single javascript file.
Any suggestions or links to existing setups would be greatly appreciated.
Update Jan 2019:
I've found a way to achieve this with Create-react-app, not perfect but it works and achieves the following:
Run a React app on port 3000 that works for multiple domains simultaneously.
Forward all requests not handled by React to a back end.
Optionally use SSL in development.
Create-react-app has a proxy option that is very easy to setup. Simply add the following line to your package.json file:
"proxy": "http://localhost:5000"
However, this will not work for multiple domains. There is a more advanced proxy configuration available.
After following these steps, you will be able to control where different requests are sent, but it does not entirely provide the ability to proxy multiple domains - to achieve this:
Create the file .env in the root of your create-react-app project.
Add the following to it:
NODE_PATH=src/
DANGEROUSLY_DISABLE_HOST_CHECK=true
# optionally add this line for SSL in development
HTTPS=true
From the advanced proxy instructions above, you should end up with a file called setupProxy.js in the root of your /src folder - change to the following:
const proxy = require('http-proxy-middleware')
const options = { target: 'https://[::1]:8000', secure: false }
module.exports = function(app) {
app.use(proxy('/api', options))
app.use(proxy('/graphql', options))
}
The magic part is the https://[::1]: 8000, which will forward all domains from the root request to the same back end. This doesn't seem to be well documented anywhere, but I believe it is the IPv6 equivalent of 127.0.0.1.
After this, you can add entries to your hosts file (for example: 127.0.0.1 some-domain.example.com), and in your React app use just the paths (/api or /graphql) and requests should be proxied to the same domain as the browser is running on.
Original answer:
I ended up taking a fairly manual approach to this.
I'm using a react/redux boilerplate, but I've modified the npm scripts like so:
"start:tenant1": "cp -r ./tenants/tenant1 ./app/tenant && cross-env NODE_ENV=development node server",
"start:tenant2": "cp -r ./tenants/tenant2 ./app/tenant && cross-env NODE_ENV=development node server",
Each tenant folder is copied to the app when the development server is run with the relevant command, and files are named the same within each tenant folder (masthead.svg, vars.js, etc) so that imports throughout the app can be static.
Mostly this works because I'm not using a node server in production, a static build folder is generated by the boilerplate.
Hope this helps someone.

Resources