В этой статье будет улучшен код примера, чтобы вынести наиболее часто повторяемые области из HTML в подключаемые файлы. Это позволит упростить разработку сайтов, ускорит его редактирование.
Первыми кандидатами на выделение в отдельные файлы может быть хидер и футер сайта. Зачастую информация в этих областях остаётся неизменной на всех страницах сайта, поэтому для уменьшения кода логично вынести их в отдельные файлы. А затем программно подключать их. Рассмотрим простейший HTML документ в проекте:
<!DOCTYPE html>
<html>
<head>
Свойства страницы, правила отображения, стили, скрипты, подключаемые файлы
</head>
<body>
<header>
Верхнее меню и шапка сайта
</header>
<main>
Содержание страницы
</main>
<footer>
Нижнее меню и подвал сайта
</footer>
</body>
</html>
Подключение будет осуществляться через замену содержимого файлов по особой маске. К примеру, можно вместо хидера поставить {{header}}
, а его содержимое будет вынесено в отдельный HTML файл "pages/header.html". Поэтому заготовка страницы из примера выше примет такой вид:
<body>
<header>
{{header}}
</header>
<main>
...
Теперь остаётся только написать код для роутинга через файлы. Скопируем пример из предыдущей статьи ("Роутинг в NodeJS") и модифицируем, добавив обычную текстовую замену в строках через метод "replace":
let http = require('http');
let fs = require('fs');
http.createServer(function(request, response) {
fs.readFile('pages/' + request.url, 'utf8', (error, fileContent) => {
response.setHeader('Content-Type' : 'text/html');
if (!error) { // страница существует
fs.readFile('pages/header.html', 'utf8', (errorHeader, fileContentHeader) => {
if(errorHeader) throw errorHeader;
fileContent = fileContent.replace(/\{\{header\}\}/, fileContentHeader);
response.statusCode = 200;
response.write(fileContent);
response.end();
});
} else { // страница не найдена
fs.readFile('pages/404.html', 'utf8', (error404, fileContent404) => {
if(error404) throw error404;
response.statusCode = 404;
response.write(fileContent404);
response.end();
});
}
});
}).listen(80);
Фактически весь функционал замены реализован в одной строке:
fileContent = fileContent.replace(/\{\{header\}\}/, fileContentHeader);
Она вставляет содержимое файла "pages/header.html" на место, где стоит {{header}}
. Аналогично можно заменять и подвал сайта на {{footer}}
из файла "pages/footer.html". Но обратите внимание, что подключение файлов должно происходить одновременно: либо внутри метода readFile, либо с использованием синхронного метода "readFileSync". Получится так:
let http = require('http');
let fs = require('fs');
http.createServer(function(request, response) {
fs.readFile('pages/' + request.url, 'utf8', (error, fileContent) => {
response.setHeader('Content-Type' : 'text/html');
if (!error) { // страница существует
fs.readFile('pages/header.html', 'utf8', (errorHeader, fileContentHeader) => {
if(errorHeader) throw errorHeader;
fileContent = fileContent.replace(/\{\{header\}\}/, fileContentHeader);
fs.readFile('pages/footer.html', 'utf8', (errorFooter, fileContentFooter) => {
if(errorFooter) throw errorFooter;
fileContent = fileContent.replace(/\{\{footer\}\}/, fileContentFooter);
response.statusCode = 200;
response.write(fileContent);
response.end();
});
});
} else { // страница не найдена
fs.readFile('pages/404.html', 'utf8', (error404, fileContent404) => {
if(error404) throw error404;
response.statusCode = 404;
response.write(fileContent404);
response.end();
});
}
});
}).listen(80);
Минусом такого способа подключения файлов шаблона (через асинхронный метод "readFile") является большая вложенность, которая растёт пропорционально с количеством заменяемых областей. Что снижает читаемой кода.