remove index.html from URL react app on S3 and CloudFront - reactjs

I am hosting multiple react apps on one s3 bucket, that is connected to a CloudFront distro.
The react apps are placed in folders so for example the calculating app is located in /calculate in the S3 bucket.
I fixed issues that happened because react wasn't using paths in a relative way to the index.html (I added "homepage":"./" to the package.json). But I am struggling to remove the index.html from the URL for the end user.
Basically I want the index.html to appear when going on https://{domain}/calculate/ not https://{domain}/calculate/index.html . Does someone know how to fix this issue?
Thanks

You can make a file just called ".htaccess" in the root directory and add the following to it:
RewriteEngine on
# Remove .html (or htm) from visible URL (permanent redirect)
RewriteCond %{REQUEST_URI} ^/(.+)\.html?$ [nocase]
RewriteRule ^ /%1 [L,R=301]
# Quietly point back to the HTML file (temporary/undefined redirect):
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [END]

Related

Angular deployment with no .htaccess

I'm trying to deploy a site, but the server this need deploying on can't have an .htaccess file. On our test server we have the following as the .htaccess file:
RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html
How can we remove the need for the htaccess? It's fine to have the # in the URL if this is the only way?
I've found a way so posting the answer to help anyone with the same issue.
The index.html page was loading but all the assets, css and js files were 404ing, when building for production you can add a base-href which I added and pointed to the directory in the server.
ng build --prod --base-href /path/to/site/root/
This then worked, the only other thing I had to change was I was referencing some assets like this:
/assets/images/logo.png
Which I had to change to this for the base href to then work:
./assets/images/logo.png
Everything is working as I want it now without any .htaccess
The other thing to note is that without an .htaccess file the site will only work with the useHash enabled.

After page refresh react page not working

I have create a bundle of react project by npm run build and create a virtual host file which is pointing to build folder, the application is working fine with different route, but when I page refresh other then root route then page not working.
This image is without page Load:
https://i.stack.imgur.com/EnBOU.png
But after page load it giving me this error.
https://i.stack.imgur.com/GooRM.png
Hi Please make base href on build index.html file inside head tag like this.
<base href="/reactapp/" /> // your root folder path
and add a .htaccess file in the root, paste below code inside the .htaccess.
<IfModule mod_rewrite.c>
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Rewrite everything else to index.html
# to allow html5 state links
RewriteRule ^ index.html [L]
</IfModule>
I hope it's useful for you.
Thanks

Setup .htaccess file for multiple React sites on the same domain

I am trying to modify my .htaccess file to run two different React websites at the same time, but they are both on the same domain.
Let's say I am serving /www. I want:
domain.com/website1 to load /www/website1/index.html
and
domain.com/website2 to load /www/website2/index.html
They are React sites using react-router, so I need every URL to forward to the respective index.html file for routing to work properly. For example, /www/website1/foo/bar should forward to /www/website1/index.html.
I am having trouble finding examples since I am not forwarding based on the domain.
My .htaccess file currently looks like this, which works for React sites because it forwards everything to /index.html:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

.htaccess for subfolder of AngularJS app with HTML5 mode

Overview :
I have an AngularJS application that uses $locationProvider.html5Mode(true) and it is served from an Apache server. Until now I used the source code to be accessed from the others and I just needed a redirect to index.html for the angularJS's HTML5 mode. So I had this for the .htaccess file for my /app folder.
.htaccess :
<IfModule mod_rewrite.c>
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]
</IfModule>
Modifications :
I then added Grunt for minifying the whole solution that is generated in the /dist folder of the app(so now the minified solution is found at /app/dist). I would now like to route the whole traffic of my app to the minified version, without making the users change the link. So, in practice I would like to redirect every call from /app to /app/dist.
Directory Structure now :
app
dist
minified versions(css,html,js)
I tried using some conditions from here in /app's .htaccess and moved the other .htaccess file in /app/dist, but with no success. I don't even know if the two can be combined in this way. I know I can use the dist folder as /app instead, but I wouldn't really want this, as /app is a repo and it is way easier to keep it updated. So how can I manage to achieve this with redirecting?
Also, as a second thing, is it possible to put a flag somehow so I let alpha users use the normal (not-minified) version for better debugging?
Update:
I added a sample project for this here. I just kept the initial .htaccess files that i showed above and you can check that both versions(/test and /test/dist) work as stated above. Also, it probably has some unused code and dependencies, but I just cut the other parts from my project(don't judge :D).
For this I used the initial configuration with AngularJS 1.4.8 that could generate some errors like the one stated here and here. Feel free to update the AngularJS version to 1.5.8(the last stable release of Angular 1), but take in consideration the comments on Cosmin Ababei's post as well. Also, the project uses npm for installing grunt(and other extensions for grunt), bower for angular and some other basic components and grunt for building the minified version(actually, it's just concatenating resources in same files for now). If you need to change the dependencies, please don't forget to run bower install. If you want to regenerate the dist folder, don't forget to run npm install and grunt build.
I'll assume that inside the /dist directory you have index.html with the updated URLs which point to the minified resources and the correct <base> tag. Note that the <base> tag must point to the /dist folder - just append /dist to the value you're using for the uncompressed index.html and you'd be fine.
With those things in order, here's the updated .htaccess file:
RewriteEngine On
# Don't rewrite files
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# If the ALPHA_USER cookie is set, serve the uncompressed files
RewriteCond %{HTTP_COOKIE} ALPHA_USER [NC]
RewriteRule ^ index.html [L]
# Rewrite everything
RewriteRule ^ dist/index.html [L]
You'll notice two things:
I've removed RewriteCond %{REQUEST_FILENAME} -d as most likely you don't need to serve whole directories
I've added the ALPHA_USER cookie which would redirect the users to the uncompressed files. This cookie can have any value you desire.
Inside public_html => /app => .htaccess try this :
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ dist/index.html [L]
Note : HTML <base> tag should be point to the dist folder. I hope this solution will work as per your expectations.

Refreshing a URL in AngularJS

We have built an application with AngularJS, it is currently hosted on a shared cPanel hosting. However, whenever we do a refresh on any page we are at with ? in the url. It will break.
I have read extensively on Stackoverflow, I understand it is because of the browser doesn't know which page to load and hence we need to set the base url in the header. We tried setting the base url and did some htaccess settings but it is still not working.
Try to click on any link from the website and refresh that page. You will notice it failed to work.
Any kind soul can point us to the right directions on how we can solve this?
Edit 1:
I have these in htaccess and notice the only url with ? will refuse to load correct.
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !/api
# otherwise forward it to index.html
RewriteRule ^.*$ - [NC,L]
RewriteRule ^/* /index.html [NC,L]
I tried to reproduce the Issue but its not showing any # tag in the URL as mentioned. Can you please explain in details.
The issue didn't come from htaccess but the folder name. For instance,
config(function($stateProvider) {
$stateProvider.state('search', {
url: '/search?page&loc&seaters&owner&min_price&max_price',
The problem is when our folder is also call search, Apache will attempt to go to search folder first (due to the htaccess) and because they can find the folder, it will read the folder directory.
We fixed it by naming the folder example: search-html and change all the templateUrl required to search-html and it solves the issue.

Resources