LINUX.ORG.RU

Как эстетически решить проблему долгой загрузки WEB-страницы?

 ,


1

1

Проблема в следующем, есть WEB-страница управления контроллером. Ресурсов контроллера хватает на отдачу страницы в течение 3 секунд. Эстетически прорисовка всех элементов по мере загрузки выглядит не очень привлекательно. Попытался решить проблему путем показа спинера на время заргузки страницы, визуально все красиво, но спинер также показывается не сразу, т.к. сначала грузится head-блок, в котором относительно увесистый блок стилей.

<html>
  <head>
    <style>
      <!-- блок стилей-->
    </style>
  </head>
  <script>
   <!--код показа спинера, пока не загрузится полностью страница-->
  </script>
  <body>
    <div id="spinner"/>
    <div id="content">
      <!-- сожержание страницы-->
    </div>
  </body>
</html>

Какие есть варианты решения проблемы?

★★★

Перенеси страницу заглушку на другой WEB-сервер, в ней напиши сценарий загрузки страницы с контроллера, чтобы он грузил страницу управления с контроллера и по окончании загрузки заменял заглушку.

kostik87 ★★★★★
()
Ответ на: комментарий от MOPKOBKA

А зачем так много элементов?

Визуализация работы оборудования на анимированных svg, адаптивность интерфейса и т.д.

Сделай поле поиска на AJAX.

Не понял, можно чуть конкретнее? AJAX используется для жанглирования стилями для управления анимацией, вывода параметров и т.п.

nvl ★★★
() автор топика
Ответ на: комментарий от nvl

Я не совсем понял, у тебя «содержимое страницы» уже на странице или скриптом подгружается?

Я подумал, что скриптом, а по умолчанию грузится малюсенькая страница, сразу со спиннером.

Обычно это так делается.

То есть, вот на этой странице у тебя только показ спиннера и загрузка скрипта, который в свою очередь уже заменяет спиннер на содержимое страницы.

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от CrX

Вся страница в одном файле во флеш-памяти контроллера. Не понимаю, что даст разбрасывание кода по разным файлам, если грузиться все будет также неспешно.

nvl ★★★
() автор топика
Ответ на: комментарий от nvl

У тебя маленькая страница, которая только показывает спиннер и всё. Она грузится сразу. Затем по какому-нибудь DOMContentLoaded запускается скрипт, который уже подгружает собственно то, что надо. И скрипты и содержимое, и всё вот это вот остальное.

За счёт того, что страничка со спиннером маленькая, она загрузится быстро.

Или у тебя сам показ спиннера там на мегабайт там наговнокоден?

CrX ★★★★★
()
Ответ на: комментарий от DumLemming

Раз контроллер такой хилый - чего он вообще страницы отдаёт? Жсоны должен передавать а принимать-показывать-отсылать должна статика на вуе/ангуляре

Ресурсов хватает. Только эстетический момент превоначальной загрузки.

nvl ★★★
() автор топика
Ответ на: комментарий от Shadow

Ну svg в base64. Какая разница?

Что это даст? Увеличение размера? И каким образом получать доступ к тегам для применения стилей на лету?

150 байтовый код:

<svg width="300" height="130" xmlns="http://www.w3.org/2000/svg">
<rect width="200" height="100" x="10" y="10" rx="20" ry="20" fill="blue" />
</svg> 

перведи в base64. Получишь 223 байта.

nvl ★★★
() автор топика
Ответ на: комментарий от nvl

Если ты можешь переписать страницу как написали выше - делай.

Но ты сам пишешь, что даже твоя заглушка отдаётся долго.

Как я вижу, если у тебя медленный контроллер - на нём должны быть только исполняющие сценарии, та часть, что реализует функционал.

А то, что показывает заглушку и реализует интерфейс управления вынеси куда-то ещё. В особенности, если таких контроллеров планируется много.

В итоге ты получишь быстрый интерфейс, а необходимая для реализации часть будет на самих контроллерах.

Ну либо, если он один и ты не хочешь выносить - делай как угодно простую быструю заглушку, хоть по центру страницы текстом: «Ждите, идёт загрузка» и на странице скрытый блок, в который подгружается интерфейс, а по окончании загрузки текст удаляется, а блок становится видимым.

kostik87 ★★★★★
()
Ответ на: комментарий от nvl

Ресурсов хватает. Только эстетический момент превоначальной загрузки.

Ну так в чём проблема? В масштабировании? SVG очень ресурсоёмок. https://github.com/arjunmehta/svg-animation-cpu-optimize и тут почитай - https://www.svgontheweb.com/#preparation

А тут пацаны жалуются: https://www.reddit.com/r/html5/comments/4koynj/svg_consuming_too_much_cpu/

anonymous
()
Ответ на: комментарий от anonymous

Ну так в чём проблема? В масштабировании? SVG очень ресурсоёмок.

Написано же в первом сообщении. Проблема не в отрисовке или масштабировании, а в скорости отдачи raw-текста страницы из контроллера.

nvl ★★★
() автор топика
Ответ на: комментарий от kostik87

Но ты сам пишешь, что даже твоя заглушка отдаётся долго.

Не заглушка, а то что перед ней.

Ну либо, если он один и ты не хочешь выносить - делай как угодно простую быструю заглушку, хоть по центру страницы текстом: «Ждите, идёт загрузка» и на странице скрытый блок, в который подгружается интерфейс, а по окончании загрузки текст удаляется, а блок становится видимым.

Ну так так и сделано, проблема в том, что до заглушки блок head, который крадет время

nvl ★★★
() автор топика
Ответ на: комментарий от nvl

Не может head сам по себе так долго отдаваться, скорее всего, у тебя долго формируется сама страница, а точнее долго её отдаётся WEB-сервер или то, что вместо него.

Поэтому я и написал - выноси на отдельный.

Дело твоё, делай как знаешь.

kostik87 ★★★★★
()
Последнее исправление: kostik87 (всего исправлений: 1)
Ответ на: комментарий от nvl

Часть стилей можно вынести в отдельный файл для отложенной загрузки, а оставшиеся (например, нужные для показа спиннера загрузки), оставить в <style>..., но прогнав через какую-нибудь тулзу для минификации css. Отдельный файл тоже через минификатор прогнать, для JS минификаторы тоже есть.

mydibyje ★★★★
()
  1. Всю статику (скрипты, стили и т.п.) сжимай гзипом, клади прям .gz-файлы рядом с оригинальными, и если тебе потом клиент на запрос статики пришлёт Accept-Encoding: gzip, то смело отвечай Content-Encoding: gzip и шли вместо оригинального контента сразу сжатый.

  2. Убедись, что правильно работают заголовки, отвечающие за кеширование, чтобы браузер повторно одно и то же не запрашивал.

  3. Попробуй перенести создание страницы на клиентскую сторону. С сервера тогда нужно будет слать только данные в json или даже в бинарном формате.

static_lab ★★★★★
()

ангуляропроблемы? - не использовать ангуляр. все это mvc, которое так долго пиарили дилетанты от мира вайти типа дяди боба (аналога нашего столярова), лишь тормозят веб, заставляя браузеры и программы на электроне с каждым годом становиться все больше и прожорлевее

P.S.: я тут, конечно, лукавлю, тот же самый Vue.js я продолжу использовать, потому что мне так проще

rtxtxtrx ★★
()
Последнее исправление: rtxtxtrx (всего исправлений: 2)

Сделать статический html + js (картинки заинлайнить туда-же) и отдавать правильные заголовки, чтобы он кэшировался браузером. Сами данные отдавать в виде json на ajax запрос. Получится, что страница прогрузится один раз, а дальше будут лёгкие запросы к api.

m0xf
()

Ресурсов контроллера хватает на отдачу страницы в течение 3 секунд.

Это время отдачи контроллером всего html кода? Или это время отдачи html + js + css + картинок? Или канал от контроллера до браузера сильно влияет? Генерируется ли этот html динамически?

Много вопросов, поэтом дам только советы:

  1. внутри тега html могут быть только теги head и body. Остальные теги это ошибка, браузеры такие ошибки обрабатывают по своему усмотрению;
  2. все css и js я бы перенес в самый низ, перед закрывающим тегом body. В этом случае контроллер будет заниматься только отдачей html и загрузка будет быстрее;
  3. все css и js файлы объеденить в 2 файла: css и js. Их проще кешировать и браузер будет занят скачиванием только 2 файлов.
  4. в html убрать все лишние пробелы и переносы строк, меньше html, быстрее будет загружаться по сети, чуть быстрее будет браузер работать;
  5. если страница рендерится без js, повесить на js атрибут defer
  6. возможно, html и css отдаются каким-нибудь nginx, который дает тормоза на контроллере. В этом случае стоит поискать какие-нибудь более легковесные решения;
  7. посмотреть в html коде на наличие «километровых» списков из select-ов. Они здорово тормозят рендеринг, тут лучше генерацию списка вообще вынести в autocomplete + ajax и подгружать динамически с контроллера;
  8. если html генерируется динамически, то я бы сделал так: сначала отдавалась какая-то статичная html страница, а потом подгружался какой-нибудь json с данными. И этими данными заполнялась бы страница. Общее время загрузки увеличится, но визуально скорость загрузки уменьшится.
dicos ★★
()
Ответ на: комментарий от Nervous

Да без разницы. DNS lookup и HTTP handshake занимают столько времени, что всё в одном файле даже при увеличении размера повышает отзывчивость «сайта». К ajax это не относится - его работу не видно.

Shadow ★★★★★
()
Последнее исправление: Shadow (всего исправлений: 1)
Ответ на: комментарий от dicos

все css и js файлы объеденить в 2 файла: css и js. Их проще кешировать и браузер будет занят скачиванием только 2 файлов.

это оптимизация из времен HTTP1, когда браузеры качали файлы по одному и разрешалось всего 1-2 соединения до сервера. С мультиплексированием запросов HTTP2+ лучше иметь много мелких файлов, т.к. код в них не будет ждать когда загрузится и распарзится весь мегабандл, который и в 3с может не влезть

Syncro ★★★★★
()

Самое простое - отдать другую страницу с айфреймом и крутилкой. Когда внуренняя готова, кинуть наверх эвент и убрать крутилку.

ya-betmen ★★★★★
()

все скрипты можно засовывать в хед, привязка кода к верстке делается при помощи Custom Elements

https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements

модульность при маленьких размером файлах достигается нативной модульностью es6 (script type=«module», импорты и вот это все)

показывать и прятать спинер можно эвентами, которые будут выбрасывать ваши компоненты (начал рендерится/думать - выбросил эвент «показать спинер», закончил - «спрятать»), а привязать его к процессу загрузки ресурсов вроде можно захукавшись в метод fetch, которым они скачиваются

Syncro ★★★★★
()
Последнее исправление: Syncro (всего исправлений: 1)
Ответ на: комментарий от ya-betmen

с мультплексированием нужно только по одному на сервер на самом деле, т.к. все запросы пакуются в один канал который прокачивает их без поднятия и закрытия соединений на каждый запрос(кажется это есть уже даже в HTTP 1.1) что было главным тормозом старого веба и это, кстати, дополнительно повышает ценность маленьких по размеру ресурсов, а не склеенных бандлов

Syncro ★★★★★
()
Последнее исправление: Syncro (всего исправлений: 1)
Ответ на: комментарий от ya-betmen

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

Syncro ★★★★★
()
Последнее исправление: Syncro (всего исправлений: 1)
Ответ на: комментарий от Syncro

все запросы пакуются в один канал который прокачивает их без поднятия и закрытия соединений на каждый запрос(кажется это есть уже даже в HTTP 1.1)

У меня жопа горит с этих «современных технологий», а «эксперты» даже до конца не понимаю, зачем эти, прости господи, технологии вообще создавалась.

Асинхронная загрузка нескольких ресурсов через одно соединение было уже в HTTP 1.1, в котором определили заголовок Connection: close и незакрытие соединения при его отстутствии. И в том числе этот протокол позволял слать следующий запрос, не дожидаясь ответа на предыдущий, но ответы приходят строго в том же порядке, что и запросы, что создает проблему ожидания крупного ответа последующими ответами. Если у тебя стоит задача «полностью загрузить сайт за минимальное время», то HTTP/2 вообще ничего не решает. Даже более того, на слабых сервера он может создавать лавинообразный эффект, поскольку у него пик нагрузки на сервер происходит при старте, клиенту ничего не стоит старт повторить, а вот серверу при этом тяжело, что может создать причины для повтора на стороне клиента, и так далее.

Лично меня весь этот цирк бесит потому, что вместо решения проблемы утяжеления веба Google идёт в противоположном направлении — создания технологий для оптимизации загрузки еще более тяжелых вебстраниц путём применения еще более мощных серверов. Подчёркиваю последнее — если ваш серер не может вывезти увеличенный трафик или просто нет достаточной ширины канала (не скорости, как раз медленные каналы для того же Quick не проблема), то все эти новомодные погремушки вам не нужны и HTTP 1.1 вам выше крыши.

byko3y ★★★★
()

Как эстетически решить проблему долгой загрузки WEB-страницы?

Ну по классике: покрути юзера на спиннере, покажи градусник с процентами, на 99% выдай «ну, не шмолгла»

anonymous
()
Ответ на: комментарий от byko3y

откуда лавинобразный эффект и увеличенный трафик, если соединение используется одно и протокол бинарный? Разве что от того, что даже глаз включение HTTP2 делает любой «сайт» быстрым как лавинообразный эффект, но балансировать нагрузку снижая эффективность наверное так себе идея.

Syncro ★★★★★
()
Ответ на: комментарий от Shadow

всё в одном файле даже при увеличении размера повышает отзывчивость

Ты не правильно понял, нет отдельных файлов svg, svg-код прямо в теле страницы: https://www.w3schools.com/html/tryit.asp?filename=tryhtml_svg_circle

nvl ★★★
() автор топика
Ответ на: комментарий от ya-betmen

он должен порождать дочерние колбасилки, иначе будет использовать только одно ядро и блокироваться как раз всякими большими файлами, IO и вычислениями, а даже на нищеконтроллерах ядер может быть от 2х штук

Syncro ★★★★★
()
Последнее исправление: Syncro (всего исправлений: 1)
Ответ на: комментарий от Syncro

откуда лавинобразный эффект и увеличенный трафик, если соединение используется одно и протокол бинарный?

Если у тебя один клиент и один сервер (как в исходном сообщении) ­— ниоткуда. Если много серверов и много клиентов — возникают проблемы.

Разве что от того, что даже глаз включение HTTP2 делает любой «сайт» быстрым как лавинообразный эффект, но балансировать нагрузку снижая эффективность наверное так себе идея.

Ты наверное пропустил какое-то слово в этом предложении. HTTP/2 делает сайт быстрым при условии, что принимающий соединение сервер сможет выдать ответ в ускоренном темпе. Именно в единственном числе, «сервер», потому что распределение нагрузки по всяким там CDN и зеркалам требует нескольких соединений, что опять нивелирует преимущества HTTP/2.

Обычно такие оптимизаторы/2.0 любят проверять ускорение загрузки сайта в условиях «один браузер и один сервер», докалдывают начальству про успешный успех, а потом внезапно выясняется, что подключение тысячи клиентов просто ложит сервер. У меня на работе не так давно гении что-то такое сотворили и доложили наверх экстраполяцию, мол «это мы на четырех клиентах протестировали, а на 400 клиентах будет еще в 100 раз быстрее» — хотя по факту там на четырех клиента сервер на последнем издыхании работал.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

CDN и зеркалам

это оптимизация для преодоления лимита на 1-2 соединения одного клиента к серверу. Если ресурсных файлов было от штук от 50и они в этом случае выстраивались в очередь. Учитывая, что код тогда был не модульным и все равно ждал полной загрузки целесообразо было слепить все в один-два файла и прогрузить за один присест. Больше толку от этого мало, т.к. и браузеры и серверы умеют кешировать.

в ускоренном темпе

ускорение достигается уровнем выше, ну сам сервер может быть ускорен если умеет работать асинхронно, но как это может повысить нагрузку на него из ваших аргументов не ясно.

Syncro ★★★★★
()
Ответ на: комментарий от Syncro

это оптимизация для преодоления лимита на 1-2 соединения одного клиента к серверу.

Нет, браузера уже давно из коробки делают несколько соединений параллельно, что-то типа 8 штук, и держат очередь запросов, чтобы при большем числе запросов в очереди потихоньку раскидывать запросы по этим восьми соединениями. Просто в HTTP/1.1 это делается по восьми соединениями, а в HTTP/2 — в одном соединении восемью потоками.

Учитывая, что код тогда был не модульным и все равно ждал полной загрузки

Сейчас цельная страница точно так же требует полной загрузки используемых ресурсов — просто стало модно подгружать также и ресурсы, которые сейчас не нужны.

ускорение достигается уровнем выше, ну сам сервер может быть ускорен если умеет работать асинхронно, но как это может повысить нагрузку на него из ваших аргументов не ясно.

У всех компонентов современного сервера есть оптимальная параллеллизация находится где-то на уровне десятков потоков — это касается как вычислений на CPU, так и доступа к SSD накопителю. Если ты выполняешь больше задач — у тебя просто растёт задержка и накладные расходы на синхронизацию. Асинхронность в том же nginx по большей части решает проблему стоимости системных вызовов, в остальном ты уткнёшся в те же десятки параллельных задач, которые, между прочим, существуют в ядре даже если твой nginx работает только в одном потоке.

byko3y ★★★★
()