Использование тега <base>
является хорошим решением, и большинство браузеров, кажется, справляются с этим хорошо. За исключением некоторых проблем с IE, как и следовало ожидать ... Очевидно, вы также можете столкнуться с некоторыми другими забавными проблемами, см. Обсуждение здесь .
Так что для людей, где это не вариант, я посмотрел на альтернативу («трудный путь»).
Обычно вы храните CSS / JS / статические изображения / другие вещи, как это:
index.php
js/
css/
imgs/
и вы хотите, чтобы были доступны JavaScript, таблицы стилей и т. Д., Независимо от количества косых черт в URL. Если ваш URL-адрес /site/action/user/new
, ваш браузер запросит
/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
Итак, вот некоторые правила перезаписи для apache, чтобы решить это ... Во-первых, если цель действительно существует на диске, не переписывайте:
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^.*$ - [L,QSA]
Другими словами, если имя файла запроса IF - это каталог, ИЛИ, если имя файла запроса IF - это файл, то не следует переписывать (-), последнее правило (L) и передавать любые параметры GET (QSA, добавление строки запроса). Вы также можете использовать
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^.*$ - [L,QSA]
если вам также нужны символические ссылки. Затем мы хотим найти javascript и таблицы стилей, даже если запросы принимают неверный базовый каталог, как показано выше.
RewriteRule ^.*/js/(.*)$ js/$1 [L]
RewriteRule ^.*/css/(.*)$ css/$1 [L]
Шаблон довольно очевиден, просто замените 'css' на имя каталога. С этим все еще остается проблема, особенно для больших веб-сайтов с большим количеством javascript и таблиц стилей, библиотек и т. Д. - регулярное выражение является жадным. Например, если у вас есть такой каталог javascript:
js/some/library/js/script.js
и ваш запрос переходит на /site/action/user/new
, браузер запрашивает /site/action/user/new/js/some/library/js/script.js
, который механизм перезаписи затем переписывает на
js/script.js
потому что первый .*
является жадным и соответствует /site/action/user/new/js/some/library
. Переключение на не жадное регулярное выражение на самом деле не имеет смысла, поскольку «механизм перезаписи повторяет все правила до тех пор, пока URI не будет одинаковым до и после итерации по правилам.»
Существует еще одна проблема, заключающаяся в том, что для каждого каталога, который необходимо освободить от перезаписи, требуется относительно «дорогое» регулярное выражение. Обе проблемы можно исправить, просто поместив каждый статический компонент в подкаталог с «необычным» именем (на самом деле это лучшее решение imo - любой, у кого есть идея, опубликуйте его).
Структура каталога будет выглядеть следующим образом:
index.php
mystrangedir/js/
mystrangedir/css/
mystrangedir/imgs/
Конечно, это нужно вставлять повсюду в коде - для проектов с большой существующей кодовой базой это может быть сложно. Однако вам нужно только одно регулярное выражение для освобождения каталога:
RewriteRule ^.*/mystrangedir/(.*)$ mystrangedir/$1 [L]
Автоматизированные системы сборки (например, gulp, grunt ....) можно использовать для проверки, не существует ли mystrangedir в качестве каталога где-либо ниже его самого (что снова приведет к отключению механизма перезаписи).
Не стесняйтесь переименовывать mystrangedir
во что-то более разумное, например static_content
, но чем более разумным оно становится, тем более вероятно, что имя каталога уже используется в некоторой библиотеке. Если вы хотите абсолютно безопасное имя каталога, которое наверняка никогда не использовалось ранее, используйте криптографический хеш, например, 010f8cea4cd34f820a9a01cb3446cb93637a54d840a4f3c106d1d41b030c7bcb
. Это довольно долго, чтобы соответствовать; Вы можете найти компромисс между уникальностью и производительностью регулярных выражений, если его сократить.