Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 08.01.2021, 14:59
Профессор
Отправить личное сообщение для Manyasha Посмотреть профиль Найти все сообщения от Manyasha
 
Регистрация: 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("Главная страница"); 
});


Я понимаю, что это не правильно, да оно так и не работает.

Подскажите, пожалуйста, каким способом можно подгрузить несколько шаблонов на одну страницу?
Если я совсем в не ту сторону думаю, пожалуйста, тоже выскажитесь. Может надо совсем все по другому делать?
Ответить с цитированием
  #2 (permalink)  
Старый 08.01.2021, 16:40
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,708

Я с этим шаблонизатором не знаком, однако обычно рендерят не каждый элемент "вручную" в контроллере, а передают из контроллера набор данных в шаблонизатор и он уже рендерит страницу.

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" для подключения в текущий шаблон других шаблонов.
Ответить с цитированием
  #3 (permalink)  
Старый 08.01.2021, 18:31
Профессор
Отправить личное сообщение для Manyasha Посмотреть профиль Найти все сообщения от Manyasha
 
Регистрация: 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
       }//и т.д.
   }

ну с нормальным синтаксисом естественно, я просто пока не изучила его.
Ответить с цитированием
  #4 (permalink)  
Старый 08.01.2021, 19:32
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,708

Сообщение от Manyasha
А Вы каким пользуетесь, если не секрет?
Неплохо знаю Smarty и Blade, но это вам не поможет, ибо стэк другой. Последний год шаблонизоторами не пользуюсь вовсе, т.к. фронт полностью на React.

Сообщение от Manyasha
Т.е. я правильно понимаю, что в контроллере я должна оставить только передачу считанного json в шаблон, а цикл по массиву и подгрузку других шаблонов по условию уже в шаблоне сделать?
Я бы сделал именно так, да.
Ответить с цитированием
  #5 (permalink)  
Старый 09.01.2021, 03:41
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Понятия не имею о внутренностях node, его шаблонах, но, если так по условию include radio.pug, то почему не проще?
for (let i=0; i<jsonData.length; i++) include jsonData[i].type + ".pug";
Ответить с цитированием
  #6 (permalink)  
Старый 09.01.2021, 11:58
Профессор
Отправить личное сообщение для Manyasha Посмотреть профиль Найти все сообщения от Manyasha
 
Регистрация: 21.09.2015
Сообщений: 196

Nexus, Спасибо! Думала на счет react, но решила, что шаблонизатор попроще изучить будет. Постараюсь остаться пока на pug.

laimas, Спасибо! Наверное можно и так, буду изучать.
Ответить с цитированием
  #7 (permalink)  
Старый 09.01.2021, 14:04
Профессор
Отправить личное сообщение для Manyasha Посмотреть профиль Найти все сообщения от Manyasha
 
Регистрация: 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 (примерное реальное количество), время загрузки страницы слишком долгое. Так что буду пытаться все-таки все в шаблоне сделать, может так быстрее будет.

Если что-то получится, выложу сюда.
Ответить с цитированием
  #8 (permalink)  
Старый 09.01.2021, 17:17
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,708

Сообщение от Manyasha
Теперь проблема в том, что когда я увеличиваю количество вопросов до 1000 (примерное реальное количество), время загрузки страницы слишком долгое.
Если я правильно понял разметку шаблона, то у вас на каждый вопрос создается по отдельной таблице, которая содержит несколько строк и всего одну колонку. + что-то, что подключается в шаблоне outer.pug.
Если для каждая таблица содержит только одну колонку, то не лучше ли таблицы заменить на div? Это уменьшит и кол-во элементов на странице (браузер немного выдохнет), и кол-во передаваемой информации на клиент (увеличится скорость полной загрузки страницы).

На каждый отдельный вопрос вы создаете отдельную функцию-рендерер. Мне это кажется слишком затратным, я бы складывал созданный экземпляр рендерера в объект/карту и доставал при необходимости. У Pug, я думаю, есть механизмы внутреннего кеша, однако описанный подход все же должен сократить время рендерера.

Так же список вопросов необязательно рендерить каждый раз заново, его можно кешировать.
Главное заранее задаться вопросом инвалидации кеша, иначе потом может возникнуть вопрос типа: «изменил какой-то вопрос, а на сайте ничего не меняется. Что не так?».

Ну и не стоит забывать о сжатии передаваемых данных на клиент, это также сократить кол-во передаваемых данных на клиент, что ускорит скорость полной загрузки страницы.
Ответить с цитированием
  #9 (permalink)  
Старый 11.01.2021, 11:14
Профессор
Отправить личное сообщение для Manyasha Посмотреть профиль Найти все сообщения от Manyasha
 
Регистрация: 21.09.2015
Сообщений: 196

Nexus,
целый вечер потратила на ковыряние шаблона, пытаясь его заставить отображать все вопросы в цикле. А сегодня с утра глянула, блин, оказалось, что я вместо объекта в response.render массив пихала
Всего-то нужно было так сделать
response.render("main", {"jsonData": jsonData});

вместо response.render("main", jsonData);
Теперь все заработало отображается все супер быстро!

Сообщение от Nexus Посмотреть сообщение
Так же список вопросов необязательно рендерить каждый раз заново, его можно кешировать.
Главное заранее задаться вопросом инвалидации кеша, иначе потом может возникнуть вопрос типа: «изменил какой-то вопрос, а на сайте ничего не меняется. Что не так?».
Я обязательно озабочусь этим опросом, у меня еще и скрипты и стили будут, которые тоже неплохо бы было кэшировать. На счет инвалидации кеша - пока сложный вопрос для меня, т.к. действительно эта анкета будет часто меняться. Буду изучать мат часть.

Спасибо за советы по сокращению html и сжатию файлов.
Я попробовала на своем тесте в 1000 вопросов, теперь шаблон так быстро все рендерит (300-500 мс), что разницы совсем не увидела.
Но перед запуском этой странички в рабочий режим, сожму все файлики.
Ответить с цитированием
  #10 (permalink)  
Старый 11.01.2021, 16:09
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,708

Сообщение от Manyasha
Но перед запуском этой странички в рабочий режим, сожму все файлики.
Сжатие с помощью express
Сжатие с помощью Nginx: NGINX.Docs, ruhighload
Какие-то внутренние файлы смысла сжимать нет, вы только потеряете возможность вносить в них изменения без декомпрессии.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
node.js + express + compression = непонятки titan83 Node.JS 0 29.01.2018 17:54
Многостроничное приложение на Express АнонимныйПарень Общие вопросы Javascript 1 19.07.2017 15:51
express app.sendFile('index.html') не удается получить связанные файлы. Astrey Node.JS 1 06.07.2017 17:25
HTTPS Server на Express Maxman Node.JS 1 20.01.2016 15:20
ошибка при вызове из консоли глобального модуля express в node.js в windows 8.1 jazznet AJAX и COMET 1 16.06.2015 10:30