Using <base> -tag is a great solution, and most browsers seem to do this well. Except for some issues with IE, as you might expect ... Obviously, you might also encounter some other funny problems, see the discussion here .
So, for people where this is not an option, I considered an alternative (the "hard way").
Usually you store css / js / static images / other things like this:
index.php js/ css/ imgs/
and you want javascript and style sheets etc. were available, no matter how many collages there are in the url. If your url is /site/action/user/new , your browser will ask
/site/action/user/css/style.css /site/action/user/css/framework/fonts/icons.ttf /site/action/user/js/page.js /site/action/user/js/jquery/jquery.min.js /site/action/user/js/some/library/with/deep/dir/structure/file.map
So, here are some rewrite rules for apache to solve this problem ... First, if the target really exists on disk, do not rewrite:
RewriteCond %{REQUEST_FILENAME} -d [OR] RewriteCond %{REQUEST_FILENAME} -f RewriteRule ^.*$ - [L,QSA]
In IF words, reqest filename is a directory OR IF request filename is a file and then does not overwrite (-) the last rule (L) and passes any GET parameters (QSA, adding a query string). You can also use
RewriteCond %{REQUEST_FILENAME} -d [OR] RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -l RewriteRule ^.*$ - [L,QSA]
if you also need symbolic links. Next, we want javascript and style sheets to be found, even if the queries assume the wrong base directory, as shown above.
RewriteRule ^.*/js/(.*)$ js/$1 [L] RewriteRule ^.*/css/(.*)$ css/$1 [L]
The pattern is pretty obvious, just replace 'css' with the directory name. There is still a problem with this, especially for large sites with lots of javascript and style sheets, libraries, etc. - The regular expression is greedy. For example, if you have a javascript directory, for example:
js/some/library/js/script.js
and your request will go to /site/action/user/new , the browser will request /site/action/user/new/js/some/library/js/script.js , which overwrites, the engine will be rewritten to
js/script.js
because the first .* greedy and matches /site/action/user/new/js/some/library . Switching to a non-greedy regex doesn't really make sense, because "the rewrite mechanism repeats all the rules until the URI is the same before and after iterating over the rules."
There is another problem, and for all directories that need to be freed from rewriting, a relatively "expensive" regular expression is required. Both problems can be fixed by simply placing each static component in a subdirectory with an βunusualβ name (and this is actually the best imo solution - anyone who understands better send it).
The directory structure will look like this:
index.php mystrangedir/js/ mystrangedir/css/ mystrangedir/imgs/
Of course, this needs to be inserted everywhere in the code - for projects with a large existing code base, this can be difficult. However, you only need one regex to exclude the directory, and then:
RewriteRule ^.*/mystrangedir/(.*)$ mystrangedir/$1 [L]
Automated build systems (eg gulp, grunt ....) can be used to check if "mystrangedir" exists as a directory somewhere below itself (which again will reset the rewrite mechanism).
Do not rename mystrangedir to something more sensible as static_content , but the more intelligent it becomes, the more likely it is that the directory name is already in use in some library. If you want an absolutely secure directory name that has never been used before, use a cryptographic hash, for example. 010f8cea4cd34f820a9a01cb3446cb93637a54d840a4f3c106d1d41b030c7bcb . It is quite a long time to fit; you can compromise between uniqueness and regular expression by shortening it.