Когда вокруг так много новых технологий, непросто понять, на изучение какой стоит потратить время.
(Karl Seguin)
Сейчас наступило интересное время, когда одни новые технологии стремительно меняются другими новыми, которые тоже быстро меняются. Положительная производная этого процесса в том, что, пока крутится этот технологический калейдоскоп, работа для девелопера найдётся. Но, иногда возникают задачи, для решения которых, говоря образным языком, лучше подойдёт не новая бензопила, а пилочка в старом перочинном ножике.
В статье показан приём разработки сайта, когда основной результат достигается за счёт использования базовых механизмов открытых стандартов.
Архитектура: Frontend, статический HTTP-сервер, XmlHttpRequest (XHR), REST.
IDE: Notepad, Notepad++ (Windows), Gedit (Linux).
Совместимость: браузер должен поддерживать JavaScript и HTML DOM.
Суть приёма
Сайт разрабатывается на основе HTML-страницы, через которую организован доступ к файлам контента. HTML-страниц, по замыслу разработчика, может быть сколько угодно, но, для достижения полной функциональности, и одной будет достаточно. В HTML-странице, ссылки на файлы контента, описываются в виде обычных HTML-ссылок, по правилам REST. За счёт расположения ссылок в одном месте, достигается ссылочная целостность.
Контент располагается в текстовых файлах и представляет собой текст, отформатированный типовой HTML-разметкой. Ограничений на расположение файлов контента нет, но будет логично, если их разместить в тематических разделах (директориях). Файлы контента не имеют связи с HTML-страницей и могут быть показаны на одной или нескольких HTML-страницах.
Сперва подгружается HTML-страница. Затем определяется и подгружается файл контента. Имя файла контента прописано в URL HTML-ссылки и определяется по правилам REST. Подгрузка файла контента осуществляется через XHR.
Ограничений никаких нет. Дизайн, код, наименования переменных и другие девелоперские соглашения — типовые для подобных разработок. Нет никакой специальной разметки, обычно применяемой для шаблонов.
Всё это немного напоминает SSI, только на Frontend-е.
Как это работает
Считать URL HTML-ссылки и определить параметры:
function getUrlParametr(parName) {
var params = location.search.substring(1).split("&");
for (var i = 0; i < params.length; i++) {
if (params[i].split("=")[0] == parName) {
return params[i].split("=")[1];
}
}
return "";
}
Количество и наименование параметров определяет разработчик, главное, чтобы в HTML-cтранице, был предусмотрен функционал по их обработке.
Загрузить и отобразить контент:
function loadXMLDoc(divName, contentFile) {
var xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
document.getElementById(divName).innerHTML = xmlhttp.responseText; // отобразить контент
}
}
xmlhttp.open("GET",contentFile,true);
xmlhttp.send();
}
В параметре «id» задано расположение файла контента, которое определяется после загрузки HTML-cтраницы:
function onPageLoad() {
var paramId = getUrlParametr("id");
if(paramId == "") paramId = "/xdata/news.htm"; // дефолтный контент
loadXMLDoc("div_body",paramId);
}
<body onload='onPageLoad()'>
HTML-ссылка составлена так, что HTML-страница ссылается на саму себя, но с разными значениями параметра «id»:
<a href='site-1-page.htm?id=/it/it-box.txt'>ИТ копилка</a>
Для добавления нового контента, надо просто создать файл контента и добавить HTML-ссылку. Расширение файла контента может быть любым, но будет удобнее, если оно будет соответствовать известному MIME-типу, например «txt» или «htm». Так будет проще перенести сайт на внешний ресурс.
Это ключевые аспекты для создания информационного сайта. Интерактивность, при необходимости, может быть добавлена на основе веб-сервисов. Если же используется больше одной HTML-страницы, то можно, например, разработать одно меню для всех страниц, которое будет загружаться по тому же принципу, что и контент. Это облегчит поддержание ссылочной целостности, но расплатой будет лишний XHR запрос.
Как вместо файла контента вставить HTML-страницу
Чтобы в базовую HTML-страницу вставить другую HTML-страницу, проще всего использовать HTML-тег iframe. В этом случае XHR не нужен. В URL надо добавить ещё один параметр, например «iframe», и обрабатывать его при загрузке базовой HTML-страницы:
function onPageLoad() {
var paramId = getUrlParametr("id");
var paramIframe = getUrlParametr("iframe");
if(paramId == "") paramId = "/it/it-box.txt"; // дефолтный контент
if(paramIframe == "" || paramIframe == "0") loadXMLDoc("div_body",paramId);
if(paramIframe == "1") document.getElementById("div_body").innerHTML = "<iframe src='" + paramId + "'></iframe>";
}
Ключевое отличие состоит в том, что файл контента встроится в DOM базовой HTML-страницы и будет обработан единым CSS, а HTML-страница, подгруженная в iframe, нет.
Когда HTML-страница расположена не в корне
Бывает нужно разработать не весь сайт, а, например, тематический раздел. Чтобы HTML-ссылки оставались актуальными, надо учитывать путь к разделу:
function onPageLoad(rootPath) {
var paramId = getUrlParametr("id");
var paramIframe = getUrlParametr("iframe");
if(paramIframe == "" || paramIframe == 0) {
if(paramId == "") paramId = rootPath + "/it/it-box.txt"
else paramId = rootPath + paramId;
loadXMLDoc("div_body",paramId);
}
if(paramIframe == 1) {
paramId = rootPath + paramId;
document.getElementById("div_body").innerHTML = "<iframe src='" + paramId + "' width='100%' height='400'></iframe>";
}
if(paramIframe == 2) {
document.getElementById("div_body").innerHTML = "<iframe src='" + paramId + "' width='100%' height='400'></iframe>";
}
}
}
<body onload='onPageLoad("/stencil-html-site-on-one-page")'>
Так выглядит, например, код примера к статье на GitHub-е.
Готовый шаблон
Если остались вопросы, то можно посмотреть демо сайта (GitHub) и скачать шаблон сайта (GitHub). Демо и шаблон представляют собой готовый макет и наполнены безобидным контентом.
Разработку можно вести на любом статическом HTTP-сервере, установленном локально, а потом перенести «как есть» в любое место сети.
Сильные и слабые стороны
Сильные:
- Простота, мобильность, компактность кода.
- Нет привязки к технологиям и БД (роль БД выполняет файловая система). В основе — только открытые спецификации и стандарты.
- Просто создавать и сопровождать резервные копии (простым копированием).
Cлабые:
- Frondend проигрывает Backend-у по функциональности. Сложная функциональность может оказаться значительно более трудоёмкой в разработке.
- В браузере должен быть разрешён JavaScript.
Ссылки к статье
Архитектура REST
Типы HTTP-запросов и философия REST
XMLHTTPRequest: описание, применение, частые проблемы
Основы XMLHttpRequest
DOM: работа с HTML-страницей
JavaScript HTML DOM Document
BOM Location Object
Window.location
Комментарии (32)
pepelsbey
27.05.2015 16:58+18Вы кажется забыли объяснить, зачем вы заново реализуете то, что браузеры и так умеют делать без JavaScript: запрашивать HTML-страницы по ссылкам.
vedenin1980
27.05.2015 17:30+1Не говоря уже о том что настроив переадресацию запросов в .htaccess можно сделать как бы эмуляцию signle page application, то есть пользователь будет вводить url?id=533&folder=ddd, а получать содержимое файла /ddd/553.html, да и ссылки в iframe работают без всякого JS.
demimurych
28.05.2015 02:00Кажется Вы не поняли иронию pepelsbey. Вопрос не в красивых ссылках, а в том какая непосредственно выгода в использовании своего собственного механизма загрузки контента.
vedenin1980
28.05.2015 10:00Ну выгода есть, angular'ы и backbon'ы ценны именно за собственный механизм загрузки контента, но придумывать такой топорный велосипед смысла нет никакого, уж лучше использовать классический механизм ifram'ов, он устарел лет на 15-20, но это лучше чем такой велосипед.
zBit
27.05.2015 17:45+8Больше похоже на хабрасуицид, если честно :)
SPA зародились уже ооочень давно, ты опоздал с материалом лет на 10 :)
ПридиркиНи одна из перечисленных IDE не является IDE, это текстовые редакторы.
Ещё и с перезагрузкой страниц…
Ещё и в текстовых файлах…
Ещё и вёрстка табличная…
Ну совсем грустно ;(
А для тех, кто понимает, что создавать свой велосипед не всегда оправдано — есть AngularJS.maximw
27.05.2015 18:56+2У вас в getUrlParametr() ошибка.
Если значение параметра содержит знак равно, то будет возращено обрезанное значение от начала до первого вхождения знака равно.
example.com?test=123&test1=22=33=444
console.log(getUrlParametr('test1')); // "22"
Kano
27.05.2015 19:48-2Для новичков которые только только познают азы веба очень даже ничего, но стиль изложения для них будет трудноват для понимания. Такие вещи нужно описывать наиболее простым языком, который способен понять школьник.
zBit
27.05.2015 19:53+2Мне кажется, что по началу лучше не изобретать свои велосипеды, а учиться использовать уже существующие инструменты. Всё же создать качественный велосипед, как мне кажется, может только опытный программист и делать он это будет только при острой необходимости.
Поэтому, совет всем новичкам: не тратьте время на это дело, лучше изучайте уже существующие инструменты.
Ну и, ИМХО, учиться по статьям человека, который тоже учиться — плохая затея.TheShock
28.05.2015 14:44+2На самом деле по началу как раз очень хорошо изобретать велосипеды, что помогает понять, как оно устроено внутри, а вот уже в серьезной разработке использовать крутые либы
vedenin1980
28.05.2015 14:59Нее, это не тот велосипед, который нужно изобретать. Если бы автор попытался повторить что-то вроде angularJS (ну или хотя бы JQuery), флаг ему в руки, а в «изобретение» велосипеда с деревянными колесами ничего хорошего не даст.
gonzazoid
27.05.2015 20:57+3для новичков с азами веба это не надо — у них есть html import, custom elements, shadow dom и html templates, которые уже сейчас работают везде с полифилами, а к моменту овладения новичками азов — имхо, будут работать везде нативно.
gag_fenix
28.05.2015 14:27+2Жаль, поисковики не увидят всей этой красоты…
dshster
28.05.2015 18:28Нормальные поисковики умеют видеть хеш-линки в ссылках (#!) и перенаправлять запрос на ?_escaped_fragment_=, а там уже умный сервер запускает phantomjs, который чудненько умеет исполнять javascript и выдавать результат. Angularjs так и индексируется.
apelserg Автор
29.05.2015 13:38+5У-уф — холодный душ полезен для здоровья.
Надо признать, что большинство замечаний, даже издевательских, это правда — описанный подход не является новой технологией (об этом честно сказано в первом абзаце).
Использую этот подход пару-тройку лет, но в интернете целостного описания или примера не нашёл. А выгода есть. Как сказал классик «Не эстетично, зато просто, дёшево и практично». Так появилась эта публикация.
Заметки на полях:
- Это не SPA, хотя внешне очень похоже. Есть SPA-верся, но проще и полезнее эта, например иногда хочется Shift+Ссылка.
- Это не замена AngularJS. Если надо — Angular легко уживается внутри.
- Это не велосипед. Велосипед не может состоять из одной функции в пять строк. А суть всего подхода — в применении функции разбора URL.
- По-поводу табличной вёрстки. Демо не имеет отношения к дизайну, его цель — показать наглядный и целостный пример.
- По-поводу Notepad. Профит применения дефолтных текстовых редакторов:
- Всегда и везде под рукой, быстро открываются, не глючат, не устанавливаются по пол дня.
- За всё время для этого проекта не потребовалось ничего сложнее (это правда).
zBit
29.05.2015 16:51+2Ещё ещё один холодный душ :)
Это не SPA, хотя внешне очень похоже
В заголовке написано "Сайт на основе одной HTML-страницы". Единственное, чем ваш SPA отличается от нормального SPA — перезагрузка страницы.
Есть SPA-верся, но проще и полезнее эта, например иногда хочется Shift+Ссылка.
Если руки совсем не кривые, то на AngularJS работает и клик средней клавишей и shift+клик по ссылке.
Велосипед не может состоять из одной функции в пять строк
Кто сказал? :)
Профит применения дефолтных текстовых редакторов
А ещё он по-дефолту сохраняет файлы в _не utf-8_, не видит unix line endings, в нём нет подсветки синтаксиса, нет автодополнений, да там вообще нифига нет, кроме поля в котором можно ввести какой-то текст :) (Мы же про Notepad, а не про Notepad++?)
И по поводубыстро открываются, не глючат, не устанавливаются по пол дня
SublimeText тоже текстовый редактор, устанавливается считанные секунды, запускается моментально, работает быстро, не глючит (без корявых плагинов), при правильном подходе прекрасно расширяется до функциональности IDE.
Грусть, тоска, печаль…
SelenIT2
29.05.2015 17:02+3Поддерживаю за оптимизм и адекватность в ответ на критику (даже издевательскую). Дерзайте, пусть у вас получится и что-то действительно новое!
быстро открываются, не глючат
К сожалению, в отношении встроенного Notepad оба утверждения как минимум спорны (помимо упомянутой в комментах проблемы с UTF-8 без BOM, стоит отметить трудности открытия в нем больших файлов, плюс время от времени обнаруживаемые приколы типа старинного «Bush hid the facts»:). Моя любимая золотая середина — Notepad++ (особенно standalone-версия, не требующая установки).
Evgeny42
На дворе 2007, ребята придумывают signle page application.
signalizator
В 2007 spa уже были, начало было в 2005 году.
Rastishka
vedenin1980
А если бы добавили тег «юмор»…
SelenIT2
Ну а что, Notepad действительно давал огромную гибкость и свободу по сравнению, например, с фронтпейджем (в конце 90-х еще был прикол, когда его предлагали скачать как «лучший в мире редактор для верстки BrutalHTML», да и вес архива был очень притягательным в эпоху диалапа:). Вот только с поддержкой UTF-8 без BOM у него так себе…
vedenin1980
Но какое это все имеет отношение к IDE (Интегрированной среде разработки)? Что в блокноте интегрированого-то?
SelenIT2
Он сам интегрирован в Windows =)
vedenin1980
Не, не пойдет. Вот far с плагином подсветки синтакиса и плагином ftp можно технически обозвать простейшей IDE для html/js/php.
SelenIT2
Если вынести за скобки PHP, в наши дни такой IDE можно обозвать и любой браузер с Dev Tools…