EDIT 1 Thank you very much for your responsiveness and patience!.
I am developing a SPA router, so everything happens in index.html. It uses HTML5 History API to rewrite the history and it would be awesome to create SEO friendly URLs.
Some sections are already on the index.html and others are loaded dynamically with ajax or fetch (if that matters)
The app has the next basic directory structure
assets/
css/
img/
js/
modules/
partials/
vendor/
index.html
Now in the router mainly there are sections and subsections, I am rewriting sections as a subdirectory, and subsections as sub-subdirectory
example.com/index.html <--- where the magic happens
But index.html is also ugly, it would be preferable to rewrite it to (not really needed as it happens naturally, but nice to have)
example.com R=301 <permanent
Then, when the user navigates to a section the url will be rewritten by history api as:
example.com/customers
But if the user reloads the website, he gets error 404
Then, when the user navigates to a subsection of that section he will see in the url bar
example.com/customers/casestudy
But again, if the user reloads, he gets error 404
What I want is to permanently re-write those URLs to index.html and its router/state manager will restore(load/show) the correct state.
The goal of this, is that URLs are SEO friendly and that search engines can index correctly each section of the website. Also if we need to hand a URL of our site to a customer/partner/stakeholder/anybody
example.com/mydata is better than example.com/index.html/#/dataFragment25654789
Thanks in advance
EDIT 02 The next .htaccess works fine
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
except when trying to load a subsection
example.com/customer/mydata
Then it gets uncaught SyntaxError: Unexpected Token '<' the same as @MrWhite answer
OLD QUESTION
I want to permanently rewrite requests to any file or subdirectory to my index.html
as it will dispatch the correct views, but preserving the subdirectory structure, no files allowed. I can't get it to work especially with sub-subdirectories
- example.com/index.html
or anyother.file
---> example.com/
- example.com/mydirectory/
or example.com/mydirectory/anyfile.file
to /index.html
URL should look example.com/mydirectory
- example.com/mydirectory/mydirectory
or example.com/mydirectory/anyfile.file
to /index.html
URL should look example.com/mydirectory/mydirectory
It sounds (from your updated question) that you "simply" need a standard front-controller type pattern... rewrite everything to /index.html
(in the document root) except for requests to static resources.
For example, in your root .htaccess
file:
# Allow mod_dir to serve index.html when requesting the directory
DirectoryIndex index.html
RewriteEngine On
# Front-controller (exclude static resources)
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_URI} !^/(assets|css|img|js|modules|partials|vendor)/
RewriteRule . index.html [L]
index.html
must then look at the requested URL in order to determine how to route the request.
Note that for any requests involving multiple path segments like /customers/casestudy
then you will need to ensure you are using root-relative URLs (starting with a slash) or absolute URLs (scheme + hostname) to your static resources (JS, CSS, images, etc.). Any relative URLs will naturally be relative to the client-side URL and will likely fail to resolve.
The first RewriteRule
above prevents the following rule being reprocessed after the initial rewrite, to prevent a rewrite loop (and minor optimisation).
The condition that checks the requested URL against the REQUEST_URI
server variable ensures we don't rewrite any resources in the known subdirectories. This is a more optimal way of checking that the file (or directory) does not exist on the filesystem before rewriting, since filesystem checks are relatively expensive. However, on systems that don't necessarily have a concisely defined structure then the filesystem check may be necessary.
But
index.html
is also ugly, it would be preferable to rewrite it to (not really needed as it happens naturally, but nice to have)
Yes, you don't need to specify /index.html
in the URL as mod_dir will issue an internal subrequest for index.html
when requesting the root directory (that's what the DirectoryIndex index.html
directive does).
However, you could issue an external redirect if /index.html
is requested directly by the user (or inadvertently linked to by 3rd parties / search engines). Internally you should be linking to /
, not /index.html
- as you don't want to redirect normal users.
For example, immediately after the RewriteEngine
directive (and before the front-controller):
# Redirect "/index.html" to "/"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.html$ / [R=302,L]
The condition that checks against the REDIRECT_STATUS
environment variable ensures we don't get a redirect loop (since the later rule rewrites the request back to index.html
). REDIRECT_STATUS
is not set on the initial request and is set to "200" after the first successful rewrite.
Note that this is currently a 302 (temporary) redirect. Only change it to 301 (permanent) after you have confirmed that this works OK. 301s are cached persistently by the browser so can make testing problematic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With