Проект, который никак не удаётся столкнуть

Опять накатывало «уплотнение жизни», из-за которого долго не писал в блог. Всё началось с того, что взялся за очередную freelance-задачу — оптимизиацию скорости загрузки сайта. Сначала долго не мог заставить себя начать. Потом, когда всё же приступил, обнаружил, что всё плохо — на сервере стоит CentOS с древним-древним Apache, не поддерживающим HTTP/2. Нашёл возможность поставить более новую версию обходными путями, но оказалось, что для поддержки HTTP/2 нужно переключаться из preforked mode в какой-то другой. Почему-то я думал, что там PHP работает в режиме Apache module, который только в preforked и доступен, и не стал этого делать. Вместо этого решил было поставить nginx. Потом вспомнил, что у клиентов установлен ISPmanager, и если я поставлю nginx, то возможность управления сайтами через него может перестать работать.
В этот момент я совсем было расстроился, но потом пришло в голову, что видел, что через ISPManager можно управлять и сайтами на nginx, а значит, где-то в настройках должна быть возможность переключения. После недолгого поиска возможность нашлась. Причём оказалось, что ISPManager может и сам nginx поставить, и автоматически конфиги сконвертировать. Затем решил переключить версию PHP с 5.4 на 7.1, чтобы уменьшить время генерации страницы. Сайт просто вырубился без каких-либо сообщений об ошибках. Покопавшись, я обнаружил, что проблема в том, что в скрипте магазина используется работа через расширение mysql вместо mysqli. Хорошо, что я с этим уже сталкивался, и было готовое решение. Дальше осталось только настроить сжатие, кеширование, включить HTTP/2 и радоваться тому, как резко подросли показатели скорости сайта. Потом для полного счастья включил еще TLS 1.3.
Но увы, радость была недолгой. Оказалось, что горе-оптимизаторы, которые занимались сайтом до меня, применили жульнический приём: отключали часть скриптов, если User-agent содержит Lighthouse. Когда я это убрал, оценка упала чуть ли не до того же уровня, который был изначально. Было жутко обидно. Потом, правда, удалось решить часть проблем минификацией некоторых скриптов и асинхронной загрузкой вспомогательных CSS.
Потом ещё немного повозился с уменьшением CLS (то, насколько «ездит» изображение по экрану при загрузке), переводом картинок в WebP, прописыванием всяких alt, height, width, другими мелкими оптимизациями, и считал, что дело сделано. Вдобавок ещё переписал несколько SQL-запросов, ускорив их почти в два раза, чтобы уменьшить время выдачи HTML-страницы.
В итоге добился показателей порядка 90 даже для мобильной версии, и уже было считал задачу выполненной. Но решил проверить и другие страницы сайта. И там всё оказалось гораздо хуже, чем я ожидал: там показатель производительности просел примерно до 50. Отчасти из-за того, что опять же предыдущие оптимизаторы для главной сделали отдельный CSS без лишних правил, а на остальных грузился здоровенный общий, отчасти — из-за того, что в картинках товаров использовался формат JPEG с неоптимальным сжатием. Пришлось переводить картинки на WebP. На первый взгляд, задача простая, но проблема вылезла оттуда, откуда я её не ждал: с ключом, который использовался скриптом генерации картинок. Почему-то на мобильной версии использовался скрипт от главной страницы, а ключи там были разные, так как использовали inode от файла конфигурации. И я полдня возился, прежде чем нашёл это! Но в итоге всё же картинки на WebP перевёл и хоть как-то улучшил показатели и внутренних страниц сайта.
К этому моменту я уже вместо радости по поводу того, что удалось сделать пусть даже и отдалённый закоулок Интернета легче и быстрее, а значит, сделать шажок к своему идеалу «дружелюбный мир для бедных», стал испытывать злость по поводу того, что никак не могу закончить и вернуться к своим основным задачам: прохождению курса по информаицонной безопасности и разработке MLFW. Но увы, злоключения на этом не кончились. Оказалось, когда я переносил оптимизированный запрос с мобильной версии сайта на основную, я закомментировал оба: и старый, и новый. Но вместо того, чтобы просто вырубить сайт с какой-нибудь ошибкой или просто пустым экраном, это породило весьма неожиданный баг: в карточке товары показывались по одной цене, а в корзину попадали по другой. (В этом магазине в своё время сделали очень кривое решение: в базе хранят оптовую цену, а розничную считают в скрипте, причём код скопипастили в несколько разных мест, поэтому периодически такие проблемы всплывают.)
На исправление этого ушла минута. Но проблема в том, что оптимизацией я занимался ночью, утром ушёл спать, и сообщение об этой ошибке прочитал только вечером, когда сайт уже часов пять провисел в таком состоянии.
Ну и сегодня заказчики выявили ещё одну проблему: полезли ошибки во взаимодействии со СберМегаМаркетом. Причём, судя по логам, наблюдались они ещё 5 июля, до того, как я затеял все эти переделки. Но такой уж я человек, что мне проще сделать как надо, чем тратить силы на объяснение и доказывание неспециалистам того, что с моими действиями это никак не связано. Там тоже оказалось всё непросто: в МегаМаркете почему-то получение сведений об остатках переключили с feedа на ручное управление, где они благополучно обнулились, и переключить обратно не получалось. Пришлось писать в техподдержку, где тоже подтормаживали, и только через 20 минут проблема вроде бы решилась. По крайней мере, у товаров статус поменялся на «в продаже».
В общем, из-за всего этого только сегодня возвращаюсь к нормальной жизни, хотя изначально думал, что ещё в воскресенье смогу почувствовать себя свободным человеком. Опять жизнь в состоянии вечного опоздания…