Так а зачем здесь PHP? Отдать статическую html-страничку со столь же статическим js-кодом можно абсолютно любым веб-сервером или даже тупо на github.io закинуть
Синхронный интерфейс взаимодействия — обрабатывает запросы один за другим.
Из первого не следует второе — к WSGI вполне прикручивают потоки или гринлеты (о чём вы сами же потом пишете ниже)
Не поддерживает ... SSE (Server-Sent Events)
SSE — это всего лишь один из вариантов streaming response, который прекрасно делается через WSGI (другое дело, что он будет занимать собой воркер, поэтому делать так обычно не очень разумно)
Синхронный и асинхронный интерфейс взаимодействия — может обрабатывать множество запросов одновременно.
Из первого не следует второе — стандартный event loop в питоне принципиально однопоточный, поэтому, если не обмазываться костылями вроде воркеров или стороннего пула потоков, запросы будут обрабатываться конкурентно, но не одновременно
может применяться в Django (через Channels)
Django уже давно поддерживает ASGI нативно без Channels (единственный мой пост как раз об этом)
Работает по схеме prefork (несколько процессов-воркеров).
То есть для uWSGI вы гринлеты упомянули, а gunicorn, у которого буквально слово green в названии, почему-то решили обидеть
сторонние классы воркеров (gevent/eventlet)
Они не сторонние
Производительность: несколько лучше, чем у Gunicorn в бенчмарках
А вот этот бенчмарк говорит, что uWSGI самый медленный (впрочем, насколько можно верить бенчмарку девятилетней давности, не знаю — но мне до сих пор интересно, что не так с этим бенчмарком)
Многие это сколько в процентном соотношении? Не то чтобы я такие не видел, но большинство из тех что я использую это нативные приложения.
Надо бы кому-нибудь посчитать точную статистику, а то у нас обоих нерепрезентативные выборки возможно
Конечно никто не запрещает, вот только это ограничено пределами одной страницы. Либо будет загружаться и собираться каждый раз с нуля.
Можно использовать htmx или аналоги для превращения многостраничного сайта в типа-одностраничный и объединения их преимуществ (впрочем, и некоторых недостатков тоже), в качестве широко известного примера такого сайта можно взять ВК, у которого с 2011 года музыка «магическим образом» не прерывается при переходам по страницам
Очень смелое заявление, а можно услышать хоть какие-то пруфы?
В соседней ветке выше расписал во всех подробностях
Клиент будет на каждой странице загружать и интерпретировать эти удобства.
Всё ещё htmx, если настолько критично
пропускная способность растет
В последние три года наоборот падает до уровня диалапа 🙃
современные подходы не создают тех "больших" проблем значение которых Вы преувеличиваете.
В соседней ветке выше мне в качестве контрпримера кинули сайт, на котором уже у двух человек прокрутка лагает блин, ничего я не преувеличиваю
Именно! Они должны были догрузиться сами, без долистывания
А на необычных сайтах отображается статус актуальности, обновляющийся в реальном времени.
Если ограничить задачу просто отображением статуса актуальности, то это и на обычных сайтах легко делается (на том же Stack Overflow я такое вижу постоянно)
За пол секунды
А почему вы так уверены, что изменение прилетит именно в первые полсекунды чтения, а не в любой другой момент времени?
Я не знаю, как работает конкретно ваш сайт (но видеть вебсокет в девтулзах как-то страшно), но из жалости к пользователям предположим, что подгрузка изменений выполняется один раз в момент открытия страницы и потом больше ничего не подгружается — но даже в этом случае, учитывая глючность мобильных интернетов, сама подгрузка контента может занять сильно дольше чем полсекунды, а читаю я быстро
А я не хочу тратить трафик на загрузку всех картинок, если прочитав пару параграфов, пойму, что написана чушь.
А решив, что там не чушь, вы уже не сможете нормально прочитать статью, потому что картинки-то не прогрузились, а вы уже ушли в оффлайн и не можете их прогрузить. Ну или не ушли, но беситесь от каждой прогрузки — интернет-то не обещал быть быстрым
И у вас всё ещё есть возможность тыкнуть на другую рандомную статью и получить
ничего, потому что в моём кэше оказалась всего одна статья
Вы даже не поняли, о чём вам говорят.
Прекрасно понял
Проспитесь перед следующим ответом.
Проспитесь перед демонстрацией откровенно сломанного сайта в качестве контрпримера 🙃
Во-первых, это плохо, потому что всё ещё требует JS. Во-вторых, в оффлайне картинки отвалились — ну и какой смысл в таком оффлайне? Лучше бы я увидел обычную ошибку подключения к интернету
Если уже был на станице - статья сразу показывается из кеша.
Возможно, это работает хорошо при автоподгрузке изменений, но на обычном сайте это будет плохо, потому что я рискую увидеть устаревшую версию
В фоне грузится новая версия, если есть изменения, и тут же показывается.
Если прям совсем сразу же показывается новая версия, то это плохо, потому что нарушается консистентность: первую половину я прочитаю старую, вторую половину прочитаю новую и запутаюсь. Лучше просто уведомление вида «Есть изменение, обновить страницу?» Но такое уведомление можно сделать и на классическом многостраничном сайте
Рендерится не вся статья, а лишь то, что попадает в видимую область.
И это ОЧЕНЬ плохо: я хочу заранее загрузить весь контент целиком и потом спокойно его читать без раздражающих подгрузок, а то вон в оффлайне у меня уже картинки отвалились
Парсится статья тоже лениво.
Аналогично предыдущему пункту. Кстати, на моём телефоне прокрутка подтупливает — подозреваю, что поэтому
Если сервер по любой причине не отвечает - приложение не ломается.
А лучше бы ломалось. Я всё в том же оффлайне тыкнул в рандомную статью и получил вечную загрузку — а нельзя мне было сказать «Включи интернет, придурок»?
В общем неудачный пример по (почти) всем параметрам
Версия для поисковиков гораздо приятнее в пользовании: и грузится быстрее, и прокрутка не лагает, и загружается сразу всё целиком, так что можно спокойно читать в оффлайне с картинками
def comment_form(request: HttpRequest, post_id: int) -> HttpResponse:
post = get_object_or_404(Post, pk=post_id)
can_comment = post_can_be_commented_by(post, request.user)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid() and can_comment:
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect(post.get_absolute_url()) + f"#comment{comment.id}"
else:
form = CommentForm()
return render(request, "form.html", {"post": post, "form": form, "can_comment": can_comment})
Обратите внимание на три вещи:
вьюха специально в любом случае возвращает статус 200 и рендерит страницу, позволяя адекватно информировать пользователя о том, что он не может комментировать — а вы так сможете?
я специально добавил проверку can_comment в одной строке с if form.is_valid(): это позволяет вернуть обратно текст комментария, если пользователь был заблокирован в момент набора этого комментария, и таким образом улучшает пользовательский опыт — а вы так сможете? (При желании можно ещё добавить else: form.add_error(...) но это уже вкусовщина)
и мой, и ваш варианты необходимо тестировать — мне нужно убедиться, что я не забыл учесть can_comment перед созданием комментария, а вам нужно убедиться, что вы не забыли использовать user_passes_test (и что вы использовали правильный user_passes_test и ничего не перепутали)
(Ещё бонусом добавил прокрутку к свежесозданному комментарию тоже для улучшения пользовательского опыта)
Можно отправлять коммент если можно менять пост? То есть не может комментировать никто кроме автора поста и админа? Очень странно
Но даже без этого вы как-то удобненько выбрали встроенную в Django проверку, а если надо разрешить комментировать например всё кроме чужих черновиков или запретить комментировать тем кого заблокировал автор поста? (Примеры реальные, с одного из поддерживаемых мной проектов правда этот проект на PHP но не суть)
redirect(post)сработает только если str(post) выдает url
Если сильно приспичит, сервер тоже может использовать API (тем более он и так его использует ради SSR в SPA, но ничего не мешает его использовать и просто так, хотя можно придумать более оптимизированный серверный рендеринг если не лениться)
Как минимум — вы куда-то потеряли рендеринг поста и возвращение обратно к странице с постом, как максимум — как вы огранизуете более сложную логику вроде проверок доступа?
Если мы рассматриваем ситуацию, когда бэк только отдаёт API, а фронт это SPA, самое очевидное — сайт перестаёт работать без JS, пользователь вынужден разрешать на своём устройстве remote code execution и подвергать себя в худшем случае риску безопасности (дыры в песочницах и сторонние каналы никто не отменял), в лучшем случае майнингу бетховенов (утрирую, но суть вы поняли)
Так как бэк вряд ли станет делать эндпоинт, который отдаст всю нужную странице информацию за раз — фронт вслед за хотелками фронтендеров станет отправлять стопицот ajax-запросов на каждый чих: тот же Хабр при открытии комментов отправляет 7 ajax-запросов, хотя теоретически ничего не мешало бы уложиться в один запрос и сэкономить время (и трафик, потому что всё вместе наверняка сожмётся лучше). И нет, отмазки наподобие «можно сперва быстро загрузить и показать основной контент страницы, а уже потом подгружать менее важные части» здесь не прокатят: во-первых, загрузка и запуск JS сами по себе потратят сколько-то времени, а во-вторых, браузеры умеют показывать страницу ещё в процессе загрузки, так что пользователь может сразу начать читать основной контент вообще без использования JS и даже не дожидаясь окончания загрузки этого основного контента — это ВСЕГДА будет быстрее чем рендеринг контента через JS
Если бэк не озаботится чем-то вроде GraphQL — он будет отдавать в том числе ненужную информацию и впустую тратить трафик: тот же Хабр при открытии комментов зачем-то отдаёт полные тексты постов, которые при этом никогда не отображаются
Браузер начинает выполнять двойную работу: сперва он тратит энергию на парсинг json, а потом на преобразование этого json в DOM по замудрёным алгоритмам — это ж какой углеродный след получается, куда только экоактивисты смотрят? А парсинг html никуда не девается, потому что регидратация и потому что на том же Хабре тексты постов всё равно приходят в html (и при этом завёрнутые в json, ага). А устройства у пользователей далеко не новые, и всё это дело успешно тормозит. Всё это можно было бы не только быстро сделать на высокопроизводительном бэке (особенно если взять столь же высокопроизводительный язык, но Rust это же экономически невыгодно ага), но и закэшировать на том же бэке (хотя бы для отдельных частных случаев) и не тратить миллионы часов и ватт пользовательских устройств на бессмысленное повторение одних и тех же действий
А уж как бесит криво сделанная гидратация на некоторых сайтах: сперва за несколько секунд подгружается обычный html, я начинаю его читать, а потом он ВНЕЗАПНО пропадает и заменяется на экран загрузки, чтобы потратить ещё несколько секунд и процентов заряда батареи на преобразование json в тот же самый html! Хочется бить ногами за такое
Ну и ещё не совсем про техническую часть, а скорее про дисциплину — часто фронт оказывается избалован одностраничностью и начинает плевать на семантику. Так как ничего не заставляет использовать родные браузерные механизмы — разработчики фронта начинают велосипедить свои собственные механизмы, которые работают хуже чем родные браузерные и приводят к появлению проблем, которых изначально не появилось бы, если бы фронт не выпендривался. Зачем делать нормальную форму с нормальной кнопкой отправки, если можно просто повесить onclick на div? Пофиг, что форма перестала отправляться по энтеру, будет много жалоб — добавим onkeypress. Зачем делать ссылки через тег <a>, если можно просто повесить onclick на подчёркнутый span? Ну и что, что Ctrl+клик перестал открывать псевдоссылку в новой вкладке, этим пользуются всего 0.00001% пользователей, добавлять обработку event.ctrlKey экономически невыгодно, использовать нормальный <a> ещё более невыгодно
На многостраничных сайтах тоже никто не запрещает использовать JS и сделать богатый UX, это не взаимоисключающие вещи
такой подход позволил разделить компетенции разработчиков на frontend и backend части и разработку их отдельно друг от друга
И ничего хорошего в этом нет, по множеству разных причин это лишь приводит к ухудшению качества сайтов
фронты могут быть web, mobile, smart tv и прочее
Иронично, что в реальности всё происходит наоборот — все всё запихивают в веб, и многие «нативные» приложения являются всего лишь обёртками над webview
Но независимо от этого — ничто не мешает использовать один и тот же api для многостраничного сайта и для нативного приложения, лишь бы было желание нормально организовать структуру бэкенда
Разумеется, ничего не мешает подгружать данные через тот же
requestsточно так же, как это делает JavaScript, без всяких селениумов и плейврайтовТак а зачем здесь PHP? Отдать статическую html-страничку со столь же статическим js-кодом можно абсолютно любым веб-сервером или даже тупо на github.io закинуть
Вам никто не запрещает открывать сцены через панельку FileSystem, наверное? Пока что продолжаю не понимать в чём неудобство
Оно раньше и было по умолчанию, но из-за большого количества жалоб на неожиданное поведение специально отключили
1. А как должно быть удобно?
2. Откроется, если вы поставите галочку Editor Settings → Text Editor → Behavior → Open Dominant Script on Scene Change
3. Я не очень понял в чём проблема, но в любом случае см. п. 2
5. Просто закрыть
Файл debian.cnf создаётся пакетом mysql-server (или пакетом mysql-server-8.0 в более старых убунтах)
Я ожидал эту ссылку, поэтому специально не стал писать «не стало проблемой» — но драйвера-то по-прежнему открытые
Почему для AMD и Intel это не стало настолько непреодолимой проблемой?
Из первого не следует второе — к WSGI вполне прикручивают потоки или гринлеты (о чём вы сами же потом пишете ниже)
SSE — это всего лишь один из вариантов streaming response, который прекрасно делается через WSGI (другое дело, что он будет занимать собой воркер, поэтому делать так обычно не очень разумно)
Из первого не следует второе — стандартный event loop в питоне принципиально однопоточный, поэтому, если не обмазываться костылями вроде воркеров или стороннего пула потоков, запросы будут обрабатываться конкурентно, но не одновременно
Django уже давно поддерживает ASGI нативно без Channels (единственный мой пост как раз об этом)
То есть для uWSGI вы гринлеты упомянули, а gunicorn, у которого буквально слово green в названии, почему-то решили обидеть
Они не сторонние
А вот этот бенчмарк говорит, что uWSGI самый медленный (впрочем, насколько можно верить бенчмарку девятилетней давности, не знаю — но мне до сих пор интересно, что не так с этим бенчмарком)
К вам это тоже относится
Почините лагающую прокрутку хотя бы, прежде чем демонстрировать сайт в качестве контрпримера
Как владелец мобилы из 2017 года я недоволен этим комментарием
Надо бы кому-нибудь посчитать точную статистику, а то у нас обоих нерепрезентативные выборки возможно
Можно использовать htmx или аналоги для превращения многостраничного сайта в типа-одностраничный и объединения их преимуществ (впрочем, и некоторых недостатков тоже), в качестве широко известного примера такого сайта можно взять ВК, у которого с 2011 года музыка «магическим образом» не прерывается при переходам по страницам
В соседней ветке выше расписал во всех подробностях
Всё ещё htmx, если настолько критично
В последние три года наоборот падает до уровня диалапа 🙃
В соседней ветке выше мне в качестве контрпримера кинули сайт, на котором уже у двух человек прокрутка лагает блин, ничего я не преувеличиваю
Именно! Они должны были догрузиться сами, без долистывания
Если ограничить задачу просто отображением статуса актуальности, то это и на обычных сайтах легко делается (на том же Stack Overflow я такое вижу постоянно)
А почему вы так уверены, что изменение прилетит именно в первые полсекунды чтения, а не в любой другой момент времени?
Я не знаю, как работает конкретно ваш сайт (но видеть вебсокет в девтулзах как-то страшно), но из жалости к пользователям предположим, что подгрузка изменений выполняется один раз в момент открытия страницы и потом больше ничего не подгружается — но даже в этом случае, учитывая глючность мобильных интернетов, сама подгрузка контента может занять сильно дольше чем полсекунды, а читаю я быстро
А решив, что там не чушь, вы уже не сможете нормально прочитать статью, потому что картинки-то не прогрузились, а вы уже ушли в оффлайн и не можете их прогрузить. Ну или не ушли, но беситесь от каждой прогрузки — интернет-то не обещал быть быстрым
ничего, потому что в моём кэше оказалась всего одна статья
Прекрасно понял
Проспитесь перед демонстрацией откровенно сломанного сайта в качестве контрпримера 🙃
Во-первых, это плохо, потому что всё ещё требует JS. Во-вторых, в оффлайне картинки отвалились — ну и какой смысл в таком оффлайне? Лучше бы я увидел обычную ошибку подключения к интернету
Возможно, это работает хорошо при автоподгрузке изменений, но на обычном сайте это будет плохо, потому что я рискую увидеть устаревшую версию
Если прям совсем сразу же показывается новая версия, то это плохо, потому что нарушается консистентность: первую половину я прочитаю старую, вторую половину прочитаю новую и запутаюсь. Лучше просто уведомление вида «Есть изменение, обновить страницу?» Но такое уведомление можно сделать и на классическом многостраничном сайте
И это ОЧЕНЬ плохо: я хочу заранее загрузить весь контент целиком и потом спокойно его читать без раздражающих подгрузок, а то вон в оффлайне у меня уже картинки отвалились
Аналогично предыдущему пункту. Кстати, на моём телефоне прокрутка подтупливает — подозреваю, что поэтому
А лучше бы ломалось. Я всё в том же оффлайне тыкнул в рандомную статью и получил вечную загрузку — а нельзя мне было сказать «Включи интернет, придурок»?
В общем неудачный пример по (почти) всем параметрам
Версия для поисковиков гораздо приятнее в пользовании: и грузится быстрее, и прокрутка не лагает, и загружается сразу всё целиком, так что можно спокойно читать в оффлайне с картинками
https://fuckingwebsite.ru/
Обратите внимание на три вещи:
вьюха специально в любом случае возвращает статус 200 и рендерит страницу, позволяя адекватно информировать пользователя о том, что он не может комментировать — а вы так сможете?
я специально добавил проверку
can_commentв одной строке сif form.is_valid(): это позволяет вернуть обратно текст комментария, если пользователь был заблокирован в момент набора этого комментария, и таким образом улучшает пользовательский опыт — а вы так сможете? (При желании можно ещё добавитьelse: form.add_error(...)но это уже вкусовщина)и мой, и ваш варианты необходимо тестировать — мне нужно убедиться, что я не забыл учесть
can_commentперед созданием комментария, а вам нужно убедиться, что вы не забыли использоватьuser_passes_test(и что вы использовали правильныйuser_passes_testи ничего не перепутали)(Ещё бонусом добавил прокрутку к свежесозданному комментарию тоже для улучшения пользовательского опыта)
Можно отправлять коммент если можно менять пост? То есть не может комментировать никто кроме автора поста и админа? Очень странно
Но даже без этого вы как-то удобненько выбрали встроенную в Django проверку, а если надо разрешить комментировать например всё кроме чужих черновиков или запретить комментировать тем кого заблокировал автор поста? (Примеры реальные, с одного из поддерживаемых мной проектов правда этот проект на PHP но не суть)
Вы забыли про
get_absolute_urlЕсли сильно приспичит, сервер тоже может использовать API (тем более он и так его использует ради SSR в SPA, но ничего не мешает его использовать и просто так, хотя можно придумать более оптимизированный серверный рендеринг если не лениться)
Как минимум — вы куда-то потеряли рендеринг поста и возвращение обратно к странице с постом, как максимум — как вы огранизуете более сложную логику вроде проверок доступа?
Справедливости ради с того же pypi.org можно скачать tar.gz, в котором «всего» пара сотен файлов
Много букв
Если мы рассматриваем ситуацию, когда бэк только отдаёт API, а фронт это SPA, самое очевидное — сайт перестаёт работать без JS, пользователь вынужден разрешать на своём устройстве remote code execution и подвергать себя в худшем случае риску безопасности (дыры в песочницах и сторонние каналы никто не отменял), в лучшем случае майнингу бетховенов (утрирую, но суть вы поняли)
Так как бэк вряд ли станет делать эндпоинт, который отдаст всю нужную странице информацию за раз — фронт вслед за хотелками фронтендеров станет отправлять стопицот ajax-запросов на каждый чих: тот же Хабр при открытии комментов отправляет 7 ajax-запросов, хотя теоретически ничего не мешало бы уложиться в один запрос и сэкономить время (и трафик, потому что всё вместе наверняка сожмётся лучше). И нет, отмазки наподобие «можно сперва быстро загрузить и показать основной контент страницы, а уже потом подгружать менее важные части» здесь не прокатят: во-первых, загрузка и запуск JS сами по себе потратят сколько-то времени, а во-вторых, браузеры умеют показывать страницу ещё в процессе загрузки, так что пользователь может сразу начать читать основной контент вообще без использования JS и даже не дожидаясь окончания загрузки этого основного контента — это ВСЕГДА будет быстрее чем рендеринг контента через JS
Если бэк не озаботится чем-то вроде GraphQL — он будет отдавать в том числе ненужную информацию и впустую тратить трафик: тот же Хабр при открытии комментов зачем-то отдаёт полные тексты постов, которые при этом никогда не отображаются
Браузер начинает выполнять двойную работу: сперва он тратит энергию на парсинг json, а потом на преобразование этого json в DOM по замудрёным алгоритмам — это ж какой углеродный след получается, куда только экоактивисты смотрят? А парсинг html никуда не девается, потому что регидратация и потому что на том же Хабре тексты постов всё равно приходят в html (и при этом завёрнутые в json, ага). А устройства у пользователей далеко не новые, и всё это дело успешно тормозит. Всё это можно было бы не только быстро сделать на высокопроизводительном бэке (особенно если взять столь же высокопроизводительный язык, но Rust это же экономически невыгодно ага), но и закэшировать на том же бэке (хотя бы для отдельных частных случаев) и не тратить миллионы часов и ватт пользовательских устройств на бессмысленное повторение одних и тех же действий
А уж как бесит криво сделанная гидратация на некоторых сайтах: сперва за несколько секунд подгружается обычный html, я начинаю его читать, а потом он ВНЕЗАПНО пропадает и заменяется на экран загрузки, чтобы потратить ещё несколько секунд и процентов заряда батареи на преобразование json в тот же самый html! Хочется бить ногами за такое
Ну и ещё не совсем про техническую часть, а скорее про дисциплину — часто фронт оказывается избалован одностраничностью и начинает плевать на семантику. Так как ничего не заставляет использовать родные браузерные механизмы — разработчики фронта начинают велосипедить свои собственные механизмы, которые работают хуже чем родные браузерные и приводят к появлению проблем, которых изначально не появилось бы, если бы фронт не выпендривался. Зачем делать нормальную форму с нормальной кнопкой отправки, если можно просто повесить onclick на div? Пофиг, что форма перестала отправляться по энтеру, будет много жалоб — добавим onkeypress. Зачем делать ссылки через тег <a>, если можно просто повесить onclick на подчёркнутый span? Ну и что, что Ctrl+клик перестал открывать псевдоссылку в новой вкладке, этим пользуются всего 0.00001% пользователей, добавлять обработку event.ctrlKey экономически невыгодно, использовать нормальный <a> ещё более невыгодно
Опять эта пачка заезженных мифов)
На многостраничных сайтах тоже никто не запрещает использовать JS и сделать богатый UX, это не взаимоисключающие вещи
И ничего хорошего в этом нет, по множеству разных причин это лишь приводит к ухудшению качества сайтов
Иронично, что в реальности всё происходит наоборот — все всё запихивают в веб, и многие «нативные» приложения являются всего лишь обёртками над webview
Но независимо от этого — ничто не мешает использовать один и тот же api для многостраничного сайта и для нативного приложения, лишь бы было желание нормально организовать структуру бэкенда