08.01.2021, 14:59
|
Профессор
|
|
Регистрация: 21.09.2015
Сообщений: 196
|
|
express response.render по нескольким шаблонам
Всем привет!
Только начала изучать Node.js, подтолкните, пожалуйста, в нужном направлении.
Основная задача: создать одностраничный опросник.
Вопросы решила описать через json. Для каждого вопроса указывается id, текст вопроса, варианты ответа, тип вопроса и т.д.
Для каждого типа вопроса создала шаблон (pug). Отдельно для вопросов radio (единственный выбор), checkbox (множественный выбор), open (текстовый ответ, вписываемый в textarea) и т.д.
Пример шаблона для вопроса-radio:
include outer.pug
table.inner_table
each val in answ
tr
td
label #[input(type='radio', name=`${id}`, value=`${val.r}`, id=`${id}_${val.r}`)] !{val.lab}
Дальше, думала перебирать json и в зависимости от типа рендерить нужный шаблон:
let jsonData = require('./study.json');
app.get("/", function(request, response){
for (let i=0; i<jsonData.length; i++){
if (jsonData[i].type == "radio"){
response.render("radio", jsonData[i]);
}//и т.д.
}
//response.send("Главная страница");
});
Я понимаю, что это не правильно, да оно так и не работает.
Подскажите, пожалуйста, каким способом можно подгрузить несколько шаблонов на одну страницу?
Если я совсем в не ту сторону думаю, пожалуйста, тоже выскажитесь. Может надо совсем все по другому делать?
|
|
08.01.2021, 16:40
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,795
|
|
Я с этим шаблонизатором не знаком, однако обычно рендерят не каждый элемент "вручную" в контроллере, а передают из контроллера набор данных в шаблонизатор и он уже рендерит страницу.
response.render не просто рендерит представление, но еще и отправляет его сразу же клиенту.
Цитата:
|
Renders a view and sends the rendered HTML string to the client. Optional parameters:а
|
© http://expressjs.com/ru/api.html#res.render
У шаблонизатора pug есть директива " include" для подключения в текущий шаблон других шаблонов.
|
|
08.01.2021, 18:31
|
Профессор
|
|
Регистрация: 21.09.2015
Сообщений: 196
|
|
Nexus, спасибо большое за ответ!
Цитата:
|
Я с этим шаблонизатором не знаком
|
Я ни с каким не знакома Выбрала, который по синтаксису понравился.
А Вы каким пользуетесь, если не секрет?
Т.е. я правильно понимаю, что в контроллере я должна оставить только передачу считанного json в шаблон, а цикл по массиву и подгрузку других шаблонов по условию уже в шаблоне сделать?
как-то так:
let jsonData = require('./study.json');
app.get("/", function(request, response){
response.render("main", jsonData);
//response.send("Главная страница");
});
а в шаблоне
for (let i=0; i<jsonData.length; i++){
if (jsonData[i].type == "radio"){
include radio.pug
}//и т.д.
}
ну с нормальным синтаксисом естественно, я просто пока не изучила его.
|
|
08.01.2021, 19:32
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,795
|
|
Сообщение от Manyasha
|
А Вы каким пользуетесь, если не секрет?
|
Неплохо знаю Smarty и Blade, но это вам не поможет, ибо стэк другой. Последний год шаблонизоторами не пользуюсь вовсе, т.к. фронт полностью на React.
Сообщение от Manyasha
|
Т.е. я правильно понимаю, что в контроллере я должна оставить только передачу считанного json в шаблон, а цикл по массиву и подгрузку других шаблонов по условию уже в шаблоне сделать?
|
Я бы сделал именно так, да.
|
|
09.01.2021, 03:41
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Понятия не имею о внутренностях node, его шаблонах, но, если так по условию include radio.pug, то почему не проще?
for (let i=0; i<jsonData.length; i++) include jsonData[i].type + ".pug";
|
|
09.01.2021, 11:58
|
Профессор
|
|
Регистрация: 21.09.2015
Сообщений: 196
|
|
Nexus, Спасибо! Думала на счет react, но решила, что шаблонизатор попроще изучить будет. Постараюсь остаться пока на pug.
laimas, Спасибо! Наверное можно и так, буду изучать.
|
|
09.01.2021, 14:04
|
Профессор
|
|
Регистрация: 21.09.2015
Сообщений: 196
|
|
Пока не выходит сделать все в шаблоне, но нашла другой вариант.
Выкладываю рабочее решение
const express = require("express");
const pug = require('pug');
const app = express();
app.set("view engine", "pug");
let jsonData = require('./study.json');
app.get("/", function (request, response) {
var html = '';
for (let i = 0; i < jsonData.length; i++) {
var layout = pug.compileFile('views/' + jsonData[i].type + '.pug');
var html = html + layout(jsonData[i]);
}
response.send(html);
});
app.listen(3000);
Шаблоны остались как были:
include outer.pug
table.inner_table
each val in answ
tr
td
label #[input(type='radio', name=`${id}`, value=`${val.r}`, id=`${id}_${val.r}`)] !{val.lab}
Теперь проблема в том, что когда я увеличиваю количество вопросов до 1000 (примерное реальное количество), время загрузки страницы слишком долгое. Так что буду пытаться все-таки все в шаблоне сделать, может так быстрее будет.
Если что-то получится, выложу сюда.
|
|
09.01.2021, 17:17
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,795
|
|
Сообщение от Manyasha
|
Теперь проблема в том, что когда я увеличиваю количество вопросов до 1000 (примерное реальное количество), время загрузки страницы слишком долгое.
|
Если я правильно понял разметку шаблона, то у вас на каждый вопрос создается по отдельной таблице, которая содержит несколько строк и всего одну колонку. + что-то, что подключается в шаблоне outer.pug.
Если для каждая таблица содержит только одну колонку, то не лучше ли таблицы заменить на div? Это уменьшит и кол-во элементов на странице (браузер немного выдохнет), и кол-во передаваемой информации на клиент (увеличится скорость полной загрузки страницы).
На каждый отдельный вопрос вы создаете отдельную функцию-рендерер. Мне это кажется слишком затратным, я бы складывал созданный экземпляр рендерера в объект/карту и доставал при необходимости. У Pug, я думаю, есть механизмы внутреннего кеша, однако описанный подход все же должен сократить время рендерера.
Так же список вопросов необязательно рендерить каждый раз заново, его можно кешировать.
Главное заранее задаться вопросом инвалидации кеша, иначе потом может возникнуть вопрос типа: «изменил какой-то вопрос, а на сайте ничего не меняется. Что не так?».
Ну и не стоит забывать о сжатии передаваемых данных на клиент, это также сократить кол-во передаваемых данных на клиент, что ускорит скорость полной загрузки страницы.
|
|
11.01.2021, 11:14
|
Профессор
|
|
Регистрация: 21.09.2015
Сообщений: 196
|
|
Nexus,
целый вечер потратила на ковыряние шаблона, пытаясь его заставить отображать все вопросы в цикле. А сегодня с утра глянула, блин, оказалось, что я вместо объекта в response.render массив пихала
Всего-то нужно было так сделать
response.render("main", {"jsonData": jsonData});
вместо response.render("main", jsonData);
Теперь все заработало отображается все супер быстро!
Сообщение от Nexus
|
Так же список вопросов необязательно рендерить каждый раз заново, его можно кешировать.
Главное заранее задаться вопросом инвалидации кеша, иначе потом может возникнуть вопрос типа: «изменил какой-то вопрос, а на сайте ничего не меняется. Что не так?».
|
Я обязательно озабочусь этим опросом, у меня еще и скрипты и стили будут, которые тоже неплохо бы было кэшировать. На счет инвалидации кеша - пока сложный вопрос для меня, т.к. действительно эта анкета будет часто меняться. Буду изучать мат часть.
Спасибо за советы по сокращению html и сжатию файлов.
Я попробовала на своем тесте в 1000 вопросов, теперь шаблон так быстро все рендерит (300-500 мс), что разницы совсем не увидела.
Но перед запуском этой странички в рабочий режим, сожму все файлики.
|
|
11.01.2021, 16:09
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,795
|
|
Сообщение от Manyasha
|
Но перед запуском этой странички в рабочий режим, сожму все файлики.
|
Сжатие с помощью express
Сжатие с помощью Nginx: NGINX.Docs, ruhighload
Какие-то внутренние файлы смысла сжимать нет, вы только потеряете возможность вносить в них изменения без декомпрессии.
|
|
|
|